转换仿函数结构以采用不同的参数
Transform functor struct to take a different argument
我从 Eigen 库中得到了以下(无约束二次方 objective)定义的借用矩阵和向量:
#ifndef QP_UNCON_HPP
#define QP_UNCON_HPP
#include "EigenDataTypes.hpp"
template <int Nx>
struct objective
{
private:
const spMat Q;
const Vec<Nx> c;
public:
objective(spMat Q_, Vec<Nx> c_) : Q(Q_), c(c_) {}
inline scalar operator()(const Vec<Nx> &x)
{
return (.5 * x.transpose() * Q * x + c.transpose() * x);
}
inline Vec<Nx> Eval_grad(const Vec<Nx> &x)
{
return Q.transpose() * x;
}
inline Mat<Nx, Nx> Eval_hessian(const Vec<Nx> &x)
{
return Q;
}
};
这使得在不同状态 x:
下评估 objective 成为可能
objective<2> f(Q, c);
Vec<2> x {0,1};
#Objective-value
f(x);
#gradient:
f.Eval_grad(x);
#hessian:
f.Eval_hessian(x);
我想创建一个新的 struct Phi
(用于行搜索),其中 scalar
用作输入参数,如下所示:
p_objective<2> Phi(f, x0, p);
double alpha = 0.9;
#Objective-value
Phi(alpha);
#gradient:
Phi.Eval_grad(alpha);
#hessian:
Phi.Eval_hessian(alpha);
对应的是:
#Objective-value
f(x + alpha*p);
#gradient:
f.Eval_grad(x + alpha*p);
#hessian:
f.Eval_hessian(x + alpha*p);
这对于使用 lambda 函数的单个函数来说很简单,但是 'lambdifying' 仿函数结构有平滑的方法吗?
EigenDataTypes.hpp
#ifndef EIGENDATATYPES_H
#define EIGENDATATYPES_H
#include <Eigen/Dense>
#include <Eigen/SparseCore>
#ifdef CSOLVER_USE_SINGLE
typedef float real_t;
#else
typedef double real_t;
#endif
using scalar = Eigen::Matrix<double, 1, 1>;
template <int Rows>
using Vec = Eigen::Matrix<double, Rows, 1>;
template <int Rows, int Cols>
using Mat = Eigen::Matrix<double, Rows, Cols>;
using spVec = Eigen::SparseVector<double>;
using spMat = Eigen::SparseMatrix<double>;
using Triplet = Eigen::Triplet<double>;
#endif
没有特征库的一维示例:
struct objective_1D
{
private:
const double Q;
const double c;
public:
objective_1D(double Q_, double c_) : Q(Q_), c(c_) {}
double operator()(const double &x)
{
return (.5 * x * Q * x + c* x);
}
double Eval_grad(const double &x)
{
return Q * x;
}
double Eval_hessian(const double &x)
{
return Q;
}
};
TLDR;
我想创建一个仿函数结构 p_objective
用作 struct objective:
的 lambda
p_objective = [&x, &p] (double alpha) (return objective-methods at (x + alpha*p))
I want to create a functor struct p_objective
that works as a lambda
for struct objective.
如果你已经写了objective
,你也可以同样写一个p_objective
。下面是一个例子。
这里是 (demo)
template <int Nx> class p_objective
{
objective<Nx> f;
const spMat x;
const Vec<Nx> p;
public:
explicit p_objective(const objective<Nx>& ob, spMat const& Q_, const Vec<Nx>& c_)
: f{ ob }
, x{ Q_ }
, p{ c_ }
{}
scalar operator()(const double alpha)
{
return f(x + (alpha*p));
}
Vec<Nx> Eval_grad(const double alpha)
{
return f.Eval_grad(x + alpha * p);
}
Mat<Nx, Nx> Eval_hessian(const double alpha)
{
return f.Eval_hessian(x + alpha * p);
}
};
由于objective
和p_objective
都有成员函数,(即Eval_grad
和Eval_hessian
),当它们正常时,它会更具可读性类,而不是 lambda 函数。
我从 Eigen 库中得到了以下(无约束二次方 objective)定义的借用矩阵和向量:
#ifndef QP_UNCON_HPP
#define QP_UNCON_HPP
#include "EigenDataTypes.hpp"
template <int Nx>
struct objective
{
private:
const spMat Q;
const Vec<Nx> c;
public:
objective(spMat Q_, Vec<Nx> c_) : Q(Q_), c(c_) {}
inline scalar operator()(const Vec<Nx> &x)
{
return (.5 * x.transpose() * Q * x + c.transpose() * x);
}
inline Vec<Nx> Eval_grad(const Vec<Nx> &x)
{
return Q.transpose() * x;
}
inline Mat<Nx, Nx> Eval_hessian(const Vec<Nx> &x)
{
return Q;
}
};
这使得在不同状态 x:
下评估 objective 成为可能objective<2> f(Q, c);
Vec<2> x {0,1};
#Objective-value
f(x);
#gradient:
f.Eval_grad(x);
#hessian:
f.Eval_hessian(x);
我想创建一个新的 struct Phi
(用于行搜索),其中 scalar
用作输入参数,如下所示:
p_objective<2> Phi(f, x0, p);
double alpha = 0.9;
#Objective-value
Phi(alpha);
#gradient:
Phi.Eval_grad(alpha);
#hessian:
Phi.Eval_hessian(alpha);
对应的是:
#Objective-value
f(x + alpha*p);
#gradient:
f.Eval_grad(x + alpha*p);
#hessian:
f.Eval_hessian(x + alpha*p);
这对于使用 lambda 函数的单个函数来说很简单,但是 'lambdifying' 仿函数结构有平滑的方法吗?
EigenDataTypes.hpp
#ifndef EIGENDATATYPES_H
#define EIGENDATATYPES_H
#include <Eigen/Dense>
#include <Eigen/SparseCore>
#ifdef CSOLVER_USE_SINGLE
typedef float real_t;
#else
typedef double real_t;
#endif
using scalar = Eigen::Matrix<double, 1, 1>;
template <int Rows>
using Vec = Eigen::Matrix<double, Rows, 1>;
template <int Rows, int Cols>
using Mat = Eigen::Matrix<double, Rows, Cols>;
using spVec = Eigen::SparseVector<double>;
using spMat = Eigen::SparseMatrix<double>;
using Triplet = Eigen::Triplet<double>;
#endif
没有特征库的一维示例:
struct objective_1D
{
private:
const double Q;
const double c;
public:
objective_1D(double Q_, double c_) : Q(Q_), c(c_) {}
double operator()(const double &x)
{
return (.5 * x * Q * x + c* x);
}
double Eval_grad(const double &x)
{
return Q * x;
}
double Eval_hessian(const double &x)
{
return Q;
}
};
TLDR;
我想创建一个仿函数结构 p_objective
用作 struct objective:
p_objective = [&x, &p] (double alpha) (return objective-methods at (x + alpha*p))
I want to create a functor struct
p_objective
that works as a lambda for struct objective.
如果你已经写了objective
,你也可以同样写一个p_objective
。下面是一个例子。
这里是 (demo)
template <int Nx> class p_objective
{
objective<Nx> f;
const spMat x;
const Vec<Nx> p;
public:
explicit p_objective(const objective<Nx>& ob, spMat const& Q_, const Vec<Nx>& c_)
: f{ ob }
, x{ Q_ }
, p{ c_ }
{}
scalar operator()(const double alpha)
{
return f(x + (alpha*p));
}
Vec<Nx> Eval_grad(const double alpha)
{
return f.Eval_grad(x + alpha * p);
}
Mat<Nx, Nx> Eval_hessian(const double alpha)
{
return f.Eval_hessian(x + alpha * p);
}
};
由于objective
和p_objective
都有成员函数,(即Eval_grad
和Eval_hessian
),当它们正常时,它会更具可读性类,而不是 lambda 函数。