Виртуальная функция с неизвестным параметром типа вектора - PullRequest
1 голос
/ 14 октября 2019

Я пытаюсь создать библиотеку оптимизации в C ++ для оптимизации параметров.

Проблема и тип параметров могут различаться, например, если проблема заключается в минимизации функции Экли , тогда у нас есть vector<double> размера 2 (индекс 0 для хи индекс 1 для у). Однако у нас могут возникнуть проблемы, когда параметры являются целыми числами или даже строками.

Для такого типа оптимизации существует множество алгоритмов, таких как генетический алгоритм, дифференциальная эволюция и т. Д. В большинстве из них, когда мы изменяем параметрыосновываясь на их стратегии оптимизации, мы должны вызвать функцию оценки, которая получает параметры, и с учетом целевой функции возвращает значение (пригодность).

Мой вопрос состоит в том, как я могу реализовать абстрактный класс Problem в C ++ такой, что он содержит virtual double evaluate функцию, в которой получает в качестве ссылки вектор общего типа связанной проблемы? Например, проблема пользователя должна наследовать Problem, и ему нужно указать тип T, в этом случае функция оценки должна быть похожа на virtual double evaluate(const vector<T> &parameters){}.

Если стратегия, о которой я говорил выше, не подходит для C ++. Пожалуйста, предложите альтернативные стратегии.

Ответы [ 2 ]

0 голосов
/ 15 октября 2019

Исходя из комментариев @Quentin и ваших данных, я бы сказал, что вы можете сначала объявить задачу как шаблон класса

#include <vector>
#include <typeinfo>
#include <iostream>

using namespace std;

template<class T>
class Problem
{
public:
    Problem() {
        if(typeid(T) == typeid(double)){
            cout << "The problem is of type double" << endl;
        }
    }

    virtual double evaluate(const vector<T> &decisionVariables) = 0;
};

Затем вы можете наследовать ее и переопределить функцию оценки в соответствии с вашими потребностями. Поскольку вы упомянули функцию Ackley, я реализовал функцию AckleyFunction, которая наследуется от задачи с типом double

#include "problem.h"
#include "math.h"

using namespace std;

class AckleyFunction : public Problem<double>
{
public:
    AckleyFunction() {}

    double evaluate(const vector<double> &decisionVariables) override {
        const double x = decisionVariables[0];
        const double y = decisionVariables[1];
        return -20 * exp(-0.2 * sqrt(0.5 * (pow(x, 2) + pow(y, 2)))) - exp(0.5 * (cos(2 * M_PI * x) + cos(2 * M_PI * y))) + exp(1) + 20;
    }
};

Глобальный минимум для функции Ackley равен x = 0 и y = 0. Вы можете видеть это ниже вmain.cpp

#include <ackleyfunction.h>
#include <memory>

using namespace std;

int main(int argc, char *argv[])
{
    shared_ptr<Problem<double>> prob(new AckleyFunction());
    vector<double> decisionVariables = {5.1, 3.3};
    cout << "Value at coordinates (5.1, 3.3): " << prob->evaluate(decisionVariables) << endl;

    decisionVariables = {0., 0.};
    cout << "Value at coordinates (0.0, 0.0): "  << prob->evaluate(decisionVariables) << endl;
}

Вывод:

The problem is of type double
Value at coordinates (5.1, 3.3): 12.9631
Value at coordinates (0.0, 0.0): 0
0 голосов
/ 14 октября 2019

Хотелось бы что-нибудь подобное сделать?

#include <memory>
#include <iostream>
#include <vector>

class Problem {
public:
    virtual double evaluate() = 0;
};

class MyProblem : public Problem {
public:
    MyProblem(const std::vector<float>& parameters) : mParameters(parameters) {}
    double evaluate() override {
        // Do evaluation based on mParameters
        return 47.11;
    }

private:
    const std::vector<float>& mParameters;
};


int main() {
    std::vector<float> v = {1.0f, 2.0f};

    std::unique_ptr<Problem> p{new MyProblem(v)};
    std::cout << p->evaluate() << '\n';  // Calls MyProblem::evaluate()

    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...