Где должны быть пользовательские параметры каркаса?

Я новичок и создаю основу для развития объектов в C ++ с помощью эволюционного алгоритма.
Эволюционный алгоритм развивает объекты и тестирует их, чтобы получить лучшее решение (например, развить нейронную сеть весов и протестировать ее на выборочных данных, чтобы в итоге вы получили сеть с хорошей точностью, не обучив ее).

Моя проблема в том, что для алгоритма есть много параметров (тип выбора / пересечения / мутации, вероятности для каждого из них …), и, поскольку он является структурой, пользователь должен иметь возможность легко получить доступ и изменить их.

ТЕКУЩЕЕ РЕШЕНИЕ

На данный момент я создал заголовочный файл parameters.h этой формы:

// DON'T CHANGE THESE PARAMETERS
//mutation type
#define FLIP 1
#define ADD_CONNECTION 2
#define RM_CONNECTION 3

// USER DEFINED
static const int TYPE_OF_MUTATION = FLIP;

Пользователь изменяет статические переменные TYPE_OF_MUTATION, а затем моя функция мутации проверяет, каково значение TYPE_OF_MUTATION, и вызывает правильную функцию мутации.

Это хорошо работает, но имеет несколько недостатков:

  • Когда я изменяю параметр в этом заголовке и затем вызываю «make», никакие изменения не принимаются во внимание, я должен вызывать «make clean», а затем «make». Из того, что я увидел, это не проблема в make-файле, а как работает сборка. Даже если он будет перестроен при изменении параметра, это будет означать перекомпиляцию всего проекта, так как эти параметры используются везде; это определенно не эффективно.
  • если вы хотите запустить генетический алгоритм несколько раз с разными параметрами, вы должны запустить его в первый раз, затем сохранить результаты, изменить параметры, затем запустить его во второй раз и т. д.

ДРУГИЕ ВОЗМОЖНОСТИ

Я думал о том, чтобы взять эти параметры в качестве аргументов функции верхнего уровня. Проблема в том, что функция будет принимать около 20 аргументов или около того, она не кажется читаемой …

Что я имею в виду в отношении функции верхнего уровня, так это то, что на данный момент эволюционный алгоритм запускается просто следующим образом:

  PopulationManager myPop;
myPop.evolveIt();

Если бы я определил параметры как аргументы, у нас было бы что-то вроде:

  PopulationManager myPop;
myPop.evolveIt(20,10,5,FLIP,9,8,2,3,TOURNAMENT,0,23,4);

Вы можете видеть, насколько адским всегда может быть определение параметров в правильном порядке!

ЗАКЛЮЧЕНИЕ

Известные мне фреймворки заставляют вас самим строить свой алгоритм из предопределенных функций, но пользователю не нужно проходить весь код, чтобы изменять параметры один за другим.

Может быть полезно указать, что эта структура будет использоваться внутри для определенного набора проектов.

Любые отзывы о наилучшем способе определения этих параметров приветствуются!

0

Решение

Если параметры не меняются, я обычно использую структуру для этого:

 enum class MutationType {
Flip,
AddConnection,
RemoveConnection
};

struct Options {
// Documentation for mutation_type.
MutationType mutation_type = MutationType::Flip;

// Documentation for integer option.
int integer_option = 10;
};

А затем предоставьте конструктор, который принимает эти параметры.

Options options;
options.mutation_type = MutationType::AddConnection;
PopulationManager population(options);

C ++ 11 делает это действительно простым, потому что он позволяет указывать значения по умолчанию для параметров, поэтому пользователю нужно только установить параметры, которые должны отличаться от значений по умолчанию.

Также обратите внимание, что я использовал перечисление для опций, это гарантирует, что пользователь может использовать только правильные значения.

0

Другие решения

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

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

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

Если вы хотите увидеть реальный пример того, как «алгоритмическая мутация» может работать, посмотрите на evolve.cpp в моем Итерированная динамика хранилище на github. Это код C, преобразованный в C ++, поэтому он не использует шаблоны и не использует виртуальные функции. Вместо этого он использует указатели функций и константу включения, чтобы выбрать соответствующий код. Однако идея та же самая.

Я бы посоветовал посмотреть, сможете ли вы сначала использовать статический полиморфизм (шаблоны). Из вашего первоначального описания вы все равно исправляли мутацию во время компиляции, так что вы ничего не оставляете.

Если это был только этап создания прототипа, и вы намеревались поддерживать переключение алгоритмов мутации во время выполнения, тогда посмотрите на виртуальные функции. Как другой ответ рекомендуется, пожалуйста, избегайте C-стиля кодирования, как #define константы и вместо этого использовать правильные перечисления.

Чтобы решить «запах длинного списка параметров», идея упаковки всех параметров в структуру является хорошей. Вы можете добиться большей читаемости, используя образец строителя построить структуру параметров в более удобочитаемом виде, чем просто присвоение набора значений в структуре. В этом Сообщение блога, Я применил шаблон компоновщика к структурам описания ресурсов в Direct3D. Это позволило мне более прямо выразить эти «пакеты данных» с разумными значениями по умолчанию и напрямую раскрыть мое намерение переопределить или заменить значения по умолчанию специальными значениями, когда это необходимо.

0

По вопросам рекламы [email protected]