将额外的数据传递给函数

萨利博斯

我正在为C ++使用dlib优化库,特别是以下功能:

template <
    typename search_strategy_type,
    typename stop_strategy_type,
    typename funct, 
    typename funct_der, 
    typename T
    >
double find_max (
    search_strategy_type search_strategy,
    stop_strategy_type stop_strategy,
    const funct& f, 
    const funct_der& der, 
    T& x, 
    double max_f
);

函数f和der被设计为获取要修改的数据参数的向量,以获得函数的最大值。但是,被最大化的函数有四个参数(一个是我的数据集,另一个是我固定的)。但是,由于它们应该具有的格式,我无法将它们作为输入传递给f和der函数。如何将这些数据输入到函数中?我目前正在尝试以下操作(我对变量c进行了硬设置,但是对于矢量xgrequ,每次处理该函数时,我都会从文件中读取数据。

//Function to be minimized
double mleGPD(const column_vector& p)
{
    std::ifstream infile("Xm-EVT.csv");
    long double swapRet;
    std::string closeStr;
    std::vector<double> histRet;

    //Read in historical swap data file
    if (infile.is_open())
    {
        while (!infile.eof())
        {
            infile >> swapRet;
            histRet.push_back(swapRet);
        }
    }
    sort(histRet.begin(), histRet.end());
    std::vector<double> negRet;
    //separate out losses
    for (unsigned c = 0; c < histRet.size(); c++)
    {
        if (histRet[c] < 0)
        {
            negRet.push_back(histRet[c]);
        }
    }
    std::vector<double> absValRet;
    //make all losses positive to fit with EVT convention
    for (unsigned s = 0; s < negRet.size(); s++)
    {
        absValRet.push_back(abs(negRet[s]));
    }
    std::vector<double> xminusu, xmu, xgrequ;
    int count = absValRet.size();
    double uPercent = .9;
    int uValIndex = ceil((1 - uPercent)*count);
    int countAbove = count - uValIndex;
    double c = (double)absValRet[uValIndex - 1];
    //looking at returns above u
    for (unsigned o = 0; o < uValIndex; ++o)
    {
        xmu.push_back(absValRet[o] - c);
        if (xmu[o] >= 0)
        {
            xgrequ.push_back(absValRet[o]);
            xminusu.push_back(xmu[o]);
        }
    }
    double nu = xgrequ.size();
    double sum = 0.0;
    double a = p(0);
    double b = p(1);

    for (unsigned h = 0; h < nu; ++h)
    {
        sum += log((1 / b)*pow(1 - a*((xgrequ[h] - c) / b), -1 + (1 / a)));
    }
    return sum;
}
//Derivative of function to be minimized
const column_vector mleGPDDer(const column_vector& p)
{
    std::ifstream infile("Xm-EVT.csv");
    long double swapRet;
    std::string closeStr;
    std::vector<double> histRet;

    //Read in historical swap data file
    if (infile.is_open())
    {
        while (!infile.eof())
        {
            infile >> swapRet;
            histRet.push_back(swapRet);
        }
    }
    sort(histRet.begin(), histRet.end());
    std::vector<double> negRet;
    //separate out losses
    for (unsigned c = 0; c < histRet.size(); c++)
    {
        if (histRet[c] < 0)
        {
            negRet.push_back(histRet[c]);
        }
    }
    std::vector<double> absValRet;
    //make all losses positive to fit with EVT convention
    for (unsigned s = 0; s < negRet.size(); s++)
    {
        absValRet.push_back(abs(negRet[s]));
    }
    std::vector<double> xminusu, xmu, xgrequ;
    int count = absValRet.size();
    double uPercent = .9;
    int uValIndex = ceil((1 - uPercent)*count);
    int countAbove = count - uValIndex;
    double c = (double)absValRet[uValIndex - 1];
    //looking at returns above u
    for (unsigned o = 0; o < uValIndex; ++o)
    {
        xmu.push_back(absValRet[o] - c);
        if (xmu[o] >= 0)
        {
            xgrequ.push_back(absValRet[o]);
            xminusu.push_back(xmu[o]);
        }
    }
    column_vector res(2);
    const double a = p(0);
    const double b = p(1);
    double nu = xgrequ.size();
    double sum1 = 0.0;
    double sum2 = 0.0;
    for (unsigned h = 0; h < nu; ++h)
    {
        sum1 += ((xgrequ[h]-c)/b)/(1-a*((xgrequ[h]-c)/b));
        sum2 += log(1 - a*((xgrequ[h] - c) / b));
    }
    res(0) = sum1;//df/da
    res(1) = sum2;//df/db
    return res;
}

这是我实际的函数调用的样子:

//Dlib max finding
    column_vector start(2);
    start = .1, .1; //starting point for a and b
    find_max(bfgs_search_strategy(), objective_delta_stop_strategy(1e-6), mleGPD, mleGPDDer, start,100);
    std::cout << "solution" << start << std::endl;
约翰·伦德伯格

这种API非常常见。几乎总是可以实现f调用der任何可调用函数,而不仅仅是静态函数。也就是说,您可以将带有运算符()的自定义类对象传递给它。

例如

struct MyF {
  //int m_state; 
  //   or other state variables, such as 
  std::vector<double> m_histRet;
  // (default constructors will do)

  double operator()(const column_vector& p) const {
    return some_function_of(p, m_state);
  }
};

int main(){
  . . . 
  MyF myf{42};
  // or
  MyF myf{someVectorContainingHistRet};

  // then use myf as you would have used mleGPD
}

您需要以相同的状态启动MyF和MyDer(std::vector<double> histRet我认为是)。作为副本或对相同状态的(常量)引用。

编辑:更完整的示例:

struct MLGDPG_State {
  std::vector<double> xgrequ;
  // . . . and more you need in f or fder
}

MLGDPG_State makeMLGDPG_State(const std::string& filename){
    std::ifstream infile(filename);
    std::ifstream infile("Xm-EVT.csv");
    long double swapRet;
    std::string closeStr;
    std::vector<double> histRet;

    //Read in historical swap data file
    if (infile.is_open())
    {
        while (!infile.eof())
        {
            infile >> swapRet;
            histRet.push_back(swapRet);
        }
    }
    sort(histRet.begin(), histRet.end());
    std::vector<double> negRet;
    //separate out losses
    for (unsigned c = 0; c < histRet.size(); c++)
    {
        if (histRet[c] < 0)
        {
            negRet.push_back(histRet[c]);
        }
    }
    std::vector<double> absValRet;
    //make all losses positive to fit with EVT convention
    for (unsigned s = 0; s < negRet.size(); s++)
    {
        absValRet.push_back(abs(negRet[s]));
    }
    std::vector<double> xminusu, xmu, xgrequ;
    int count = absValRet.size();
    double uPercent = .9;
    int uValIndex = ceil((1 - uPercent)*count);
    int countAbove = count - uValIndex;
    double c = (double)absValRet[uValIndex - 1];
    //looking at returns above u
    for (unsigned o = 0; o < uValIndex; ++o)
    {
        xmu.push_back(absValRet[o] - c);
        if (xmu[o] >= 0)
        {
            xgrequ.push_back(absValRet[o]);
            xminusu.push_back(xmu[o]);
        }
    }
    return {std::move(xgrequ)}; 
    // Or just 'return MleGPD(xgrequ)' if you are scared of {} and move
}

//Functor Class, for ion to be minimized
struct MleGPD{
  MLGDPG_State state;  
  double operator()(const column_vector& p) const {   
    auto mu = state.xgrequ.size();
    double sum = 0.0;
    double a = p(0);
    double b = p(1);
    for (unsigned h = 0; h < nu; ++h)
    {
        sum += log((1 / b)*pow(1 - a*((xgrequ[h] - c) / b), -1 + (1 / a)));
    }
    return sum;
};

对struct使用相同的模式MleGPD_Derivative

用法:

const auto state = makeMLGDPG_State("Xm-EVT.csv");
const auto f = MleGPD{state};
const auto der = MleGPD_Derivative{state};

start = .1, .1; //starting point for a and b
find_max(bfgs_search_strategy(), objective_delta_stop_strategy(1e-6), f, der, start,100);
std::cout << "solution" << start << std::endl;

请注意,对于像这样的简单结构,通常可以使用默认构造函数,复制构造函数等。也请注意http://en.cppreference.com/w/cpp/language/aggregate_initialization

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

无法将数据传递给方法

来自分类Dev

Hayageek jQuery文件上传插件将额外数据传递给PHP

来自分类Dev

无法将数据传递给函数(jQuery)

来自分类Dev

JavaScript-将数据传递给匿名函数

来自分类Dev

将额外的数据传递给yii上传器

来自分类Dev

将数据传递给Laravel事件

来自分类Dev

将openpyxl数据传递给熊猫

来自分类Dev

将变量数据传递给ValidationAttribute

来自分类Dev

将额外的道具数据传递给react-native-draggable-flatlist中的renderItem

来自分类Dev

将数据传递给lodash map()函数-功能组件

来自分类Dev

将数据传递给createApp(vue)

来自分类Dev

Flutter:将数据传递给状态

来自分类Dev

将多个表单数据传递给jquery函数

来自分类Dev

OpenCV:无法正确将数据传递给函数

来自分类Dev

坚持如何将数据传递给函数

来自分类Dev

Titanium将数据传递给createHTTPClient

来自分类Dev

将数据传递给AsynTask

来自分类Dev

将文件数据传递给函数

来自分类Dev

将已解析的重复数据传递给函数

来自分类Dev

将数据传递给服务-Android?

来自分类Dev

如何将Firebase数据传递给函数

来自分类Dev

将数据传递给javascript图表

来自分类Dev

将数据传递给支持的节点

来自分类Dev

将数据传递给 taghelper

来自分类Dev

将数据传递给 WebAssembly

来自分类Dev

将数据传递给父组件

来自分类Dev

将数据传递给模态/WebView

来自分类Dev

将数据传递给列表

来自分类Dev

将数据传递给反应映射函数