我正在使用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;
答案 0 :(得分:0)
这种API很常见。 f
和der
对任何可调用的几乎总是可行,而不仅仅是静态函数。也就是说,您可以将带有operator()的自定义类对象传递给它。
例如
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
。)作为副本或(const)引用相同的状态。
修改:更完整的示例:
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;
};
对结构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