2015-11-08 6 views
1

Я использую библиотеку оптимизации dlib для C++ в частности, следующие функции:Передача дополнительных данных в функцию

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 и дер предназначены взять вектор параметров данных модифицируется, чтобы получить максимум значение моей функции. Однако моя максимизированная функция имеет четыре параметра (один из них - мой набор данных, а другой фиксирован мной). Однако я не могу передать их в качестве вкладов в мои функции 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

Фактический код функции find_max (...) в его файле заголовка показывает только 1 параметр. – salisboss

ответ

0

Этот вид 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; 
}; 

Используйте тот же шаблон для структуры 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

+0

Не могли бы вы привести краткий пример того, что вы имеете в виду? – salisboss

+0

Да. Если вы приводите примерные аргументы, которые вы используете для вызова max(), это сделает его более полным. –

+0

Функция вызова добавлена ​​к вопросу – salisboss

Смежные вопросы