变换函子结构以采用不同的参数

Posted

技术标签:

【中文标题】变换函子结构以采用不同的参数【英文标题】:Transform functor struct to take a different argument 【发布时间】:2021-11-12 05:24:25 【问题描述】:

我从 Eigen 库中获得了以下(无约束二次目标)定义的借用矩阵和向量:

#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<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 用作结构目标的 lambda:

p_objective = [&x, &p] (double alpha) (return objective-methods at (x + alpha*p))

【问题讨论】:

既然你问了lambdafication,这里是an example 【参考方案1】:

我想创建一个函子结构p_objective 用作 lambda 用于结构目标。

如果你已经写了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);
    
;

由于objectivep_objective 都有成员函数(即Eval_gradEval_hessian),所以当它们是普通类时,它比lambda 函数更具可读性。

【讨论】:

视频、课程和演示都很有用,但我正在尝试找到一种避免重复并易于验证转换是否正确的解决方案。首先制作方法结构的方法是为了隐藏实现,所以视频中的 lambda-struct 打破了这种抽象。

以上是关于变换函子结构以采用不同的参数的主要内容,如果未能解决你的问题,请参考以下文章

2009年大学生电子大赛

中文分词结构化感知器SP

c语言中结构体变量做函数参数的问题

变频电源的系统结构及其作用

[Paper Weekly]CNN采样方法:空间变换网络(STN)与可变形卷积网络(DCN)

C#004.索引器事件等结构