Какие стратегии программирования я могу использовать для простого изменения параметров алгоритма?

17

Разработка научных алгоритмов - это очень итеративный процесс, часто включающий в себя изменение множества параметров, которые я хочу изменить либо как часть моего экспериментального проекта, либо как часть производительности алгоритма настройки. Какие стратегии я могу использовать для структурирования этих параметров, чтобы я мог легко менять их между итерациями и чтобы я мог легко добавлять новые?

Скотти Т
источник

Ответы:

14

Для пользователя неудобно указывать каждый аспект алгоритма. Если алгоритм допускает вложенные компоненты, то конечного числа опций будет недостаточно. Поэтому очень важно, чтобы опции не обязательно «всплыли» на верхний уровень, как в случае явных аргументов или параметров шаблона. Это иногда называют "проблемой конфигурации" в разработке программного обеспечения. Я считаю, что PETSc обладает уникально мощной системой управления конфигурациями. Это похоже на шаблон Service Locator в эссе Мартина Фаулера об инверсии управления .

Система конфигурации PETSc работает через комбинацию заданной пользователем конфигурации, управляемой объектами решателя (с запросами get и set) и базой данных параметров. Любой компонент симуляции может объявить опцию конфигурации, значение по умолчанию и место для размещения результата. Вложенные объекты имеют префиксы, которые можно составлять, так что каждый объект, который нуждается в настройке, может быть адресован независимо. Сами параметры можно прочитать из командной строки, среды, файлов конфигурации или из кода. Когда опция объявлена, указывается строка справки и справочная страница, чтобы -helpопция была понятной и чтобы можно было написать правильно связанный графический интерфейс.

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

Типичная конфигурация, вызываемая через

PetscObjectOptionsBegin(object); /* object has prefix and descriptive string */
PetscOptionsReal("-ts_atol",                                      /* options database key */
                 "Absolute tolerance for local truncation error", /* long description */
                 "TSSetTolerances",                               /* function and man page on topic */
                  ts->atol,                                       /* current/default value *?
                  &ts->atol,                                      /* place to store value */
                  &option_set);                                   /* TRUE if the option was set */
PetscOptionsList("-ts_type","Time stepping method","TSSetType",TSList,
                 defaultType,typeName,sizeof typeName,&option_set);
TSAdaptSetFromOptions(ts->adapt);                                 /* configures adaptive controller method */
/* ... many others */
/* ... the following is only called from implicit implementations */
SNESSetFromOptions(ts->snes);                                     /* configure nonlinear solver. */
PetscOptionsEnd();

Примечания:

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

Я сталкивался с этой проблемой несколько раз при разработке собственных кодов симуляции с нуля: какие параметры должны быть помещены во входной файл, какие данные должны быть взяты из командной строки и т. Д. После некоторых экспериментов следующее оказалось эффективным. (Он не такой продвинутый, как PETSc.)

Вместо того, чтобы писать экспериментальную «программу» симуляции, я больше склонен писать пакет Python, который содержит все функции и классы, необходимые для запуска симуляции. Затем традиционный входной файл заменяется небольшим скриптом Python с 5-10 строками кода. Некоторые строки обычно связаны с загрузкой файлов данных и указанием вывода. Другие инструкции для фактического вычисления. Хорошие значения по умолчанию для необязательных аргументов в пакете Python позволяют начинающим использовать библиотеку для простого моделирования, в то время как опытный пользователь по-прежнему имеет доступ ко всем функциям.

Несколько примеров:

Мультяшка верстрален
источник
Это здорово, но я думаю, что это ортогонально к проблеме конфигурации. Если вам нужно указать иерархический или вложенный алгоритм, то у вас есть опции, которые нужно указать для многих внутренних объектов. Код, вызывающий их, не должен даже знать об их существовании, потому что число уровней и типы вложенности могут изменяться. Это проблема всех этих выборов "пузыриться". С вашим высокоуровневым кодом Python вы можете легко определить эти опции, но вам все равно придется указывать их в коде. Я думаю, что это вообще не очень хорошая вещь.
Джед Браун
xmonad использует этот метод для настройки своего оконного менеджера для X.
rcollyer
2

Во-первых, я хотел бы сделать алгоритм и программное обеспечение как можно более общим. Я научился этому трудному пути.

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

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

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

В начале, вы можете и начать интегрировать по простым геометриям и объявить параметры в начале как константы. Со временем, если вы хотите изменить геометрию, вы можете сделать это легко. Если бы вы сделали предположения в начале, вам бы пришлось каждый раз менять весь код.

jbcolmenares
источник