SkillAgentSearch skills...

RealVectorFramework

Zero Overhead Abstractions for Vector Algorithms

Install / Use

/learn @sandialabs/RealVectorFramework
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

RealVectorFramework (RVF)

A header-only, generic C++20 framework for vector operations and numerical algorithms built on TInCuP customization points. RVF provides a unified interface for linear algebra operations that works with any vector-like type, enabling high-performance numerical computing with pluggable backends.

Key Features

  • 🔧 Generic by Design: Works with any vector type (std::vector, custom types, GPU vectors)
  • Zero-Overhead Abstractions: Compile-time polymorphism via C++20 concepts
  • 🧩 Pluggable Backends: Easy integration with specialized libraries (BLAS, CUDA, etc.)
  • 📊 Rich Algorithm Suite: Trust region methods, conjugate gradient, optimization algorithms
  • 🏗️ Memory Management: Advanced memory arena system for high-performance computing
  • 🎯 Concept-Driven: Strong type safety with expressive concepts

Quick Start

#include "rvf.hpp"
#include "operations/std_cpo_impl.hpp"  // Enable std::vector support

using namespace rvf;
using Vector = std::vector<double>;

// Create and manipulate vectors using RVF operations
Vector x = {1.0, 2.0, 3.0};
auto y_clone = clone(x);           // Clone vector
auto& y = deref_if_needed(y_clone); // Get reference

scale_in_place(y, 2.0);            // y *= 2.0  
axpy_in_place(y, 1.5, x);          // y += 1.5 * x
double dot = inner_product(x, y);   // Compute x · y

Core Customization Point Objects (CPOs)

RVF provides a complete set of vector operations through Customization Point Objects that can be specialized for any vector type:

📐 Basic Operations

| CPO | Description | Usage | |-----|-------------|-------| | clone(v) | Create a copy of vector v | auto v2 = clone(v1); | | dimension(v) | Get vector size/dimension | size_t n = dimension(v); | | inner_product(x, y) | Compute dot product x · y | double dot = inner_product(x, y); | | deref_if_needed(v) | Dereference wrapper types | auto& ref = deref_if_needed(clone(v)); |

In-Place Operations

| CPO | Description | Mathematical Equivalent | |-----|-------------|-------------------------| | scale_in_place(v, α) | Scale vector by scalar | v ← α * v | | add_in_place(y, x) | Vector addition | y ← y + x | | axpy_in_place(y, α, x) | Scaled addition | y ← y + α * x |

🔄 Advanced Operations

| CPO | Description | Purpose | |-----|-------------|---------| | self_map_c<F, Vec> | Function maps vector to same size space | Concept for operators like Hessians | | unary_in_place(v, f) | Apply unary function element-wise | Custom transformations | | binary_in_place(z, x, y, f) | Apply binary function element-wise | Element-wise operations | | variadic_in_place(v, f, args...) | Variadic element-wise operations | Complex transformations |

🏗️ Memory Arena Integration

| CPO | Description | Use Case | |-----|-------------|----------| | arena_integration | Memory pool allocation | High-frequency allocations | | arena_observers | Memory usage tracking | Performance analysis |

Cloning Idiom (Owner + Reference)

Many RVF operations accept and return either values or smart-pointer-like wrappers. The clone CPO may therefore return either a value (e.g., std::vector<double>) or a wrapper (e.g., std::unique_ptr<std::vector<double>>). Use deref_if_needed to obtain a reference to the underlying vector.

Recommended idiom: keep the owner and the reference adjacent to avoid lifetime issues and to satisfy concept-constrained APIs (which check types before applying conversions).

auto cl = rvf::clone(x); auto& xr = rvf::deref_if_needed(cl);
// use xr as a regular vector; cl owns storage so xr stays valid

Rationale:

  • Concept checks run before implicit conversions, so passing temporary wrappers to functions constrained on real_vector_c will fail. Binding a reference (xr) avoids this.
  • Keeping the owner (cl) and the reference (xr) adjacent makes the code read more mathematically while preventing dangling references.

This idiom is used throughout the algorithms in this repo (e.g., Conjugate Gradient, Sherman–Morrison, gradient descent with bounds).


Algorithms & Solvers

RVF provides a comprehensive suite of numerical algorithms for optimization and linear algebra:

🎯 Optimization Algorithms

Trust Region Methods

  • TruncatedCG: Steihaug-Toint truncated conjugate gradient for trust region subproblems
    // Create solver instance (clones objective once)
    TruncatedCG<Objective, Vector> tcg_solver(objective, x_template);
    
    // Solve trust region subproblem: min g^T s + (1/2) s^T H s, ||s|| ≤ δ
    auto result = tcg_solver.solve(x_current, step, trust_radius, params);
    
    // Check termination status
    switch (result.status) {
      case TerminationStatus::CONVERGED: /* ... */
      case TerminationStatus::NEGATIVE_CURVATURE: /* ... */
      case TerminationStatus::TRUST_REGION_BOUNDARY: /* ... */
    }
    

Line Search Methods

  • gradient_descent_bounds: Projected gradient descent with bound constraints and backtracking line search
    // Define bound constraints
    bound_constraints<Vector> bounds{lower, upper};
    
    // Solve: min f(x) subject to lower ≤ x ≤ upper  
    gradient_descent_bounds(objective, bounds, x, grad_tol, step_size, max_iter);
    

🔢 Linear Algebra Algorithms

Conjugate Gradient

  • conjugate_gradient: Iterative solver for symmetric positive definite systems
    // Solve A*x = b using conjugate gradient
    auto result = conjugate_gradient(A_operator, b, x_initial, tolerance, max_iter);
    

Sherman-Morrison Formula

  • sherman_morrison_solve: Efficient rank-1 update to matrix inverse
    // Solve (A + u*v^T)*x = b efficiently when A^{-1} is known
    sherman_morrison_solve(A_inv_action, u, v, b, x);
    

📊 Algorithm Features

| Algorithm | Problem Type | Key Features | |-----------|-------------|--------------| | TruncatedCG | Trust region subproblems | Negative curvature handling, boundary detection | | gradient_descent_bounds | Bound-constrained optimization | Projection, backtracking line search | | conjugate_gradient | Linear systems (SPD) | Iterative, matrix-free capable | | sherman_morrison | Low-rank matrix updates | O(n) complexity for rank-1 updates |


Objective Function Framework

RVF provides a concept-driven framework for defining objective functions with automatic differentiation support:

🎯 Core Concepts

// Objective function concepts (output arguments first)
template<typename F, typename Vec>
concept objective_value_c = requires(const F& f, const Vec& x) {
  { f.value(x) } -> std::convertible_to<vector_value_t<Vec>>;
};

template<typename F, typename Vec>  
concept objective_gradient_c = requires(const F& f, const Vec& x, Vec& g) {
  { f.gradient(g, x) } -> std::same_as<void>;  // g = ∇f(x)
};

template<typename F, typename Vec>
concept objective_hess_vec_c = requires(const F& f, const Vec& x, const Vec& v, Vec& hv) {  
  { f.hessVec(hv, v, x) } -> std::same_as<void>;  // hv = H*v where H = ∇²f(x)
};

📈 Example: Zakharov Test Function

// f(x) = x^T x + (1/4)(k^T x)^2 + (1/16)(k^T x)^4
auto zakharov = make_zakharov_objective(k_vector);

Vector x = {1.0, 2.0, 3.0};
Vector grad(3), hess_vec_result(3), direction(3);

double f_val = zakharov.value(x);           // Evaluate f(x)  
zakharov.gradient(grad, x);                 // ∇f(x) → grad
zakharov.hessVec(hess_vec_result, direction, x);  // H*direction → result

Examples & Tutorials

RVF includes comprehensive examples demonstrating various features and use cases:

🚀 Getting Started Examples

  • examples/main.cpp: Basic RVF usage with generic tag_invoke implementations
  • examples/traits_vs_ranges.cpp: Backend specialization using operations/std_cpo_impl.hpp

🧮 Algorithm Demonstrations

  • examples/conjugate_gradient.cpp: Iterative linear system solver
  • examples/sherman_morrison.cpp: Efficient low-rank matrix updates
  • examples/hs1_gradient_descent.cpp: Bound-constrained optimization (Hock-Schittkowski problem)
  • examples/hs1_advanced.cpp: Advanced optimization with iteration callbacks

🎯 Trust Region & Nonlinear Optimization

  • examples/zakharov_example.cpp: Complete trust region method with truncated CG
  • examples/zakharov_rvf.cpp: RVF-native implementation
  • examples/zakharov_truncated_cg.cpp: Detailed truncated CG algorithm showcase
  • examples/zakharov_truncated_cg_simple.cpp: Simplified TruncatedCG usage

🏗️ Memory Management

  • examples/memory_arena_example.cpp: High-performance memory arena usage

💡 Complete Example: Trust Region Optimization

#include "rvf.hpp"
#include "operations/std_cpo_impl.hpp"

using namespace rvf;
using Vector = std::vector<double>;

int main() {
  // Define problem size and initial point
  const size_t n = 5;
  Vector x(n, 3.0);  // Start at x = (3, 3, 3, 3, 3)
  
  // Create Zakharov objective function
  Vector k(n);
  std::iota(k.begin(), k.end(), 1.0);  // k = (1, 2, 3, 4, 5)
  auto objective = make_zakharov_objective(k);
  
  // Set up TruncatedCG solver (efficient: clones only once)
  TruncatedCG<decltype(objective), Vector> tcg_solver(objective, x);
  
  // Trust region parameters
  double trust_radius = 1.0;
  typename decltype(tcg_solver)::Params tcg_params;
  tcg_params.abs_tol = 1e-8;
  tcg_params.rel_tol = 1e-2;
  tcg_params.max_iter = n;
  
  // Solve trust region subproblem
  Vector step(n, 0.0);
  auto result = tcg_solver.solve(x, step, trust_radius, t
View on GitHub
GitHub Stars5
CategoryDevelopment
Updated18d ago
Forks1

Languages

C++

Security Score

75/100

Audited on Mar 9, 2026

No findings