Как уже может указывать заголовок, мне трудно описать мою архитектурную проблему, и по той же причине поиск был безрезультатным. Я пишу приложение командной строки, целью которого является получение двумерных данных, к которым физическая модель может быть приспособлена с помощью подгонки по методу наименьших квадратов. Я уже реализовал подпрограмму Nelder-Mead и Levenberg-Marquardt, которая работает должным образом, то есть, учитывая набор данных, модель и функцию стоимости, они оптимизируют массив подгоночных параметров.
Для этой цели я хочу написать класс, который облегчает абстрактную функциональность оптимизации, независимо от фактической модели и функции стоимости, которая будет использоваться.
class Fit
{
public:
Fit();
~Fit();
run();
private:
std::vector<std::vector<double>> m_data;
std::vector<double> m_parameters;
std::vector<double> m_evaluated;
}
Фактический метод оптимизации run()
будет выглядеть примерно так:
void run()
{
// Set initial guess for parameters
m_parameters = {...};
while(condition) {
double cost_value;
// Evaluate model function for current parameters
(*model)(&m_evaluated, m_data, m_parameters);
(*cost)(&cost_value, m_data, m_evaluated);
if (cost_value < threshold_value)
break;
else
update_parameters(&m_parameters);
}
}
Вот тут и приходят мои вопросы. Fit::run()
метод должен вызвать model
а также cost
функции, но заранее не известно, как они будут выглядеть или какие аргументы функции им требуются. Аргументы, которые они принимают в моем примере, являются минимально необходимыми аргументами, как видно из процедуры подгонки, но могут быть дополнительные обязательные аргументы.
Конкретные функции стоимости и модель будут определены в другом месте, но я понятия не имею, как Fit
класс знает, какие функции ему нужно вызывать. Приходящий из c
Я думал о функциональных указателях, но понятия не имею, как это лучше всего сделать в c++
, Должен Fit
иметь указатель на член функции m_model
что должно быть установлено после его создания? Я просто плевок здесь. Как мне лучше всего подойти к этому и как называется эта проблема, чтобы я мог искать дополнительные подходы?
Изменить: чтобы лучше понять, что я пытаюсь выполнить псевдокод.
// Imagine multiple available functions that all work differently but take some array of parameters
// which is then used to evaluate some function for a set of data values
void model_a(std::vector<double>* y, std::vector<std::vector<double>> data, std::vector<double> p) {
for (int i; i < data[0].size(); ++i)
(*y)[i] = parameters[0] + parameters[1]*data[0][i];
};
void model_b(std::vector<double>* y, std::vector<std::vector<double>> data, std::vector<double> p) {
for (int i; i < data[0].size(); ++i)
(*y)[i] = parameters[0] - pow(data[0][i], parameters[1]);
};
// Assume we have some data
std::vector<std::vector<double>> data = {};
Fit fit = Fit();
fit->set_data(data)
fit->set_model(model_a); // This is what the question is about
fit->run();
// Now we can extract and display the optimized parameter array
std::vector<double> p = fit.parameters();
for (int i; i < p.size(); ++i)
std::cout << p[i] << std::endl;
Для меня это звучит так, как будто вы хотите либо интерфейсный класс, который предоставляет интерфейс, либо просто создаете иерархию классов, где данные хранятся в базовом классе, а производный класс знает, как рассчитать стоимость и т. Д.
Есть несколько способов, которыми вы можете на самом деле реализовать это — если вы хотите, чтобы данные сохранялись в классе, вы могли бы передать их либо на этапе строительства, либо позже, в случае модели затрат.
К сожалению, я должен спешить сейчас, но вернусь позже, чтобы проверить комментарии и т. Д.