Библиотека генетических алгоритмов - часть 4

ОГЛАВЛЕНИЕ

Данная статья является завершающей частью из серии статей о библиотеке генетических алгоритмов и в ней мы приведем примеры использования библиотеки

• Скачать исходный код библиотеки - 279 Кб
• Скачать исходный код демонстрационных приложений - 85.81 Кб
• Скачать демонстрационные приложения - 138.83 Кб
• Скачать документацию библиотеки - 1.03 Мб
• Последние версии библиотеки

По следующим ссылкам вы сможете найти предыдущие части данной серии:

- часть первая
- часть вторая
- часть третья

Примеры

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

Пример 1: Нахождение минимума f(x, y) = 5*x*sin(x) + 1.1*y*sin(y); x, y на интервале (0, 10)

Важно: перед использованием библиотеки генетических алгоритмов надо вызвать GaInitialize. Перед выходом из приложения надо вызвать GaFinalize.

Проще всего выбрать представление хромосомы с множеством значений, поддерживающее арифметические операции [класс Chromosome::Representation::GaMVArithmeticChromosome<double>].
После выбора представления хромосомы пользователь должен определить операцию пригодности.

class fFitness : public GaFitnessOperation
{
public:

    virtual float GACALL operator() (const GaChromosome*
        chromosome) const
    {
        const vector<double>& vals=
            dynamic_cast<const GaMVArithmeticChromosome<double>*>
            (chromosome)->GetCode();

        return 5*vals[0]*sin(vals[0])+1.1*vals[1]*sin(vals[1]);
    }

    virtual GaParameters* GACALL MakeParameters() const { return NULL; }

    virtual bool GACALL CheckParameters(const GaParameters&
        parameters) const { return true; }
};

Класс fFitness наследует класс GaFitnessOperation и переопределяет operator(), вычисляющий значение пригодности хромосомы путем оценки фактической математической функции.

На следующем шаге строится блок конфигурации хромосомы (CCB), содержащий:
1.    указатель на параметры хромосом
2.    указатель на функторы генетических операций [операции кроссовера, мутации, пригодности и сравнитель пригодности]
3.    указатель на набор значений, определяющий домен переменных x и y

Класс Chromosome::Representation::GaValueInterval<T> используется в качестве набора значений хромосомы, потому что домен переменных x и y является непрерывным интервалом (0, 10). GaIntervalValueSet требует 4 границы [нижняя и верхняя границы – для задания интервала оригинальных значений, и нижняя и верхняя границы – для задания интервала инвертированных значений] и генератор случайных значений.

GaValueIntervalBound<double /> valueInt(0,10);
GaValueIntervalBound<double /> invValueInt(0,10);
GaValueInterval<double /> valueSet(valueInt,invValueInt,
    GaGlobalRandomDoubleGenerator,false);

CCB должен быть:

fFitness fitnessOperation;
GaChromosomeDomainBlock<double> configBlock(&valueSet,
    GaCrossoverCatalogue::Instance().GetEntryData(
    "GaMultiValueCrossover"),
    GaMutationCatalogue::Instance().GetEntryData("GaFlipMutation"),
    &fitnessOperation,
    GaFitnessComparatorCatalogue::Instance().GetEntryData(
    "GaMinFitnessComparator"),
    &chromosomeParams);

Определяется CCB для использования операций GaMultiValuesCrossover и GaFlipMutation. Задается GaMinFitnessComparator, поскольку задача алгоритма – найти минимум функции.
Когда CCB определен, пользователь может построить прототипную хромосому:

GaMVArithmeticChromosome<double> prototype(2,&configBlock);

Кроме прототипной хромосомы, пользователь должен определить параметры популяции перед созданием объекта популяции:
1.    размер популяции: 30
2.    популяция с изменяемым размером: нет [используется инкрементный алгоритм, не требующий популяцию с изменяемым размером]
3.    популяция отсортирована: да
4.    масштабированная пригодность используется для сортировки: нет
5.    отслеживание лучших хромосом: 0 [популяция уже отсортирована]
6.    отслеживание худших хромосом: 0 [популяция уже отсортирована]

GaPopulationParameters populationParams(30,false,true,false,0,0);

Объект популяции использует стандартную конфигурацию, не считая того, что он меняет сравнитель сортировки:
1.    операции селекции: GaSelectRouletteWheel
2.    число выбираемых хромосом: 2
3.    операция спаривания: GaInverseCoupling
4.    вырабатывается потомков: 2
5.    операция замены: GaReplaceWorst
6.    заменяется хромосом: 2
7.    операция масштабирования: нет
8.    сравнитель сортировки: GaMaxFitnessComparator [стандартный] изменен на GaMinFitnessComparator

Теперь все готово для создания объекта популяции:

GaPopulationConfiguration populationConfig;
populationConfig.SetParameters(populationParams);
populationConfig.SetSortComparator(
    &configBlock.GetFitnessComparator());

GaPopulation population( &prototype, &populationConfig );

Этот пример использует инкрементный генетический алгоритм [класс GaIncrementalAlgorithm]. Создание объекта алгоритма:

GaMultithreadingAlgorithmParams algorithmParams(1);
GaIncrementalAlgorithm algorithm(&population,algorithmParams);

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

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

GaGenerationCriteriaParams criteriaParams(100000);

algorithm.SetStopCriteria(
    GaStopCriteriaCatalogue::Instance().GetEntryData(
    "GaGenerationCriteria"),&criteriaParams);

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

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

class fObserver : public GaObserverAdapter
{
    virtual void GACALL NewBestChromosome(const GaChromosome&
        newChromosome,const GaAlgorithm& algorithm)
    {
        const vector<double>& vals=
            dynamic_cast<const GaMVArithmeticChromosome<double>&>
            (newChromosome).GetCode();
        cout << "New chromosome found:\n";
        cout << "Fitness: " << newChromosome.GetFitness() << endl;
        cout << "x: " << vals[0] << " y: " << vals[1] << endl;
    }

    virtual void GACALL EvolutionStateChanged(GaAlgorithmState
        newState,const GaAlgorithm& algorithm)
    {
        if(newState==GAS_RUNNING)
            cout << "start\n";
        else if(newState==GAS_CRITERIA_STOPPED)
            cout << "end";
    }
};

Регистрация наблюдателя:

fObserver observer;
algorithm.SubscribeObserver(&observer);

Запуск алгоритма:

algorithm.StartSolving(false);

Параметр StartSolving определяет, должен ли алгоритм продолжить ранее приостановленный процесс эволюции [true] или же запустить совершенно новый процесс [false].


Пример 2: Сравнение с образцом

 

Снимок экрана – приложение проверки образца

Этот пример реализует генетический алгоритм, пытающийся угадать последовательность символов. Пример определяет следующую последовательность символов:

const char pattern[] =
"        GGGGGGGGGGGGG               AAA               LLLLLLLLLLL             "
"     GGG::::::::::::G              A:::A              L:::::::::L             "
"   GG:::::::::::::::G             A:::::A             L:::::::::L             "
"  G:::::GGGGGGGG::::G            A:::::::A            LL:::::::LL             "
" G:::::G       GGGGGG           A:::::::::A             L:::::L               "
"G:::::G                        A:::::A:::::A            L:::::L               "
"G:::::G                       A:::::A A:::::A           L:::::L               "
"G:::::G    GGGGGGGGGG        A:::::A   A:::::A          L:::::L               "
"G:::::G    G::::::::G       A:::::A     A:::::A         L:::::L               "
"G:::::G    GGGGG::::G      A:::::AAAAAAAAA:::::A        L:::::L               "
"G:::::G        G::::G     A:::::::::::::::::::::A       L:::::L               "
" G:::::G       G::::G    A:::::AAAAAAAAAAAAA:::::A      L:::::L         LLLLLL"
"  G:::::GGGGGGGG::::G   A:::::A             A:::::A   LL:::::::LLLLLLLLL:::::L"
"   GG:::::::::::::::G  A:::::A               A:::::A  L::::::::::::::::::::::L"
"     GGG::::::GGG:::G A:::::A                 A:::::A L::::::::::::::::::::::L"
"        GGGGGG   GGGGAAAAAAA                   AAAAAAALLLLLLLLLLLLLLLLLLLLLLLL";
const int patternSize=sizeof(pattern)-1;

В нее входят следующие символы: G,A,L,: и пробел.

Генетический алгоритм использует представление хромосомы Chromosome::Representation::GaMVArithmeticChromosome<double> с определенным доменом значений посредством класса Chromosome::Representation::GaMultiValueSet<char>.

GaMultiValueSet<char> valueSet(false);
valueSet.Add("GAL: ","     ",5);

Операция пригодности вычисляет процент совпадающих символов и возвращает это число в качестве значения пригодности хромосомы:

class pFitness : public GaFitnessOperation
{
public:

    virtual float GACALL operator()(const GaChromosome*
        chromosome) const
    {
        const vector<char>& v=
            dynamic_cast<const GaMultiValueChromosome&ltchar>*>
            (chromosome)->GetCode();

        int score=0;
        for(int i=0;i&ltpatternSize;i++)
        {
            if(v[i]==pattern[i])
            score++;
        }

        return (float)score/patternSize*100;
    }

    virtual GaParameters* GACALL MakeParameters() const
        { return NULL; }

    virtual bool GACALL CheckParameters(const GaParameters&
        parameters) const { return true; }
};

CCB походит на CCB в предыдущем примере, не считая того , что он использует новую операцию пригодности и другой сравнитель пригодности, потому что его цель – максимизировать пригодность:

pFitness fitnessOperation;
GaChromosomeDomainBlock<char /> configBlock(&valueSet,
    GaCrossoverCatalogue::Instance().GetEntryData(
    "GaMultiValueCrossover"),
    GaMutationCatalogue::Instance().GetEntryData("GaFlipMutation"),
    &fitnessOperation,
    GaFitnessComparatorCatalogue::Instance().GetEntryData(
    "GaMaxFitnessComparator"),
    &chromosomeParams);

Прототипная хромосома:

GaMultiValueChromosome<char> prototype( patternSize, &configBlock );</char>

Этот пример использует генетический алгоритм с неперекрывающимися популяциями, вырабатывающий целую популяцию. Чтобы увеличить разнообразие выработанных хромосом, увеличивается число выбранных хромосом. Такой тип алгоритм требуют популяцию с изменяемым размером. Объект популяции и его конфигурация:

GaPopulationParameters populationParams(30,true,true,false,0,0);

GaPopulationConfiguration populationConfig;
populationConfig.SetParameters(populationParams);
populationConfig.SetSortComparator(
    &configBlock.GetFitnessComparator());
populationConfig.Selection().GetParameters().SetSelectionSize(6);

GaPopulation population(&prototype, &populationConfig);

Как сказано, этот пример использует класс Algorithm::SimpleAlgorithms::GaSimpleAlgorithm для генетического алгоритма.

GaSimpleAlgorithmParams algorithmParams(10,2);
GaSimpleAlgorithm algorithm(&population,algorithmParams);

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

В данном примере известно точное условие окончания: когда алгоритм находит хромосому со значением пригодности 100 [100% совпадение]. Правильный критерий остановки Algorithm::StopCriterias::GaFitnessCriteria:

GaFitnessCriteriaParams criteriaParams(100,GFC_EQUALS_TO,
    GSV_BEST_FITNESS);
algorithm.SetStopCriteria(
    GaStopCriteriaCatalogue::Instance().GetEntryData(
    "GaFitnessCriteria"),
    &criteriaParams);

Наблюдатель алгоритма отображает лучшие хромосомы по мере их нахождения:

class pObserver : public GaObserverAdapter
{
public:
    virtual void GACALL NewBestChromosome(const GaChromosome&
        newChromosome,const GaAlgorithm& algorithm)
    {
        const vector<char>& v=
        dynamic_cast<const GaMultiValueChromosome<char>&>
            (newChromosome).GetCode();

        cout<<"Generatiron: "<<
            algorithm.GetAlgorithmStatistics().GetCurrentGeneration()
            <<endl;
        cout<<"Fitness: "<<newChromosome.GetFitness();
        cout<<"\n-------------------------\n";

        for(int i=0;i<v.size();i++)
        {
            if(!(i%78))
                cout<<endl;

            cout<<v[i];
        }
        cout<<"\n-------------------------\n";
    }

    virtual void GACALL EvolutionStateChanged(GaAlgorithmState
        newState,const GaAlgorithm& algorithm)
    {
        if(newState==GAS_CRITERIA_STOPPED)
            cout<<"end.";
    }
};

Подписка наблюдателя такая же, как в предыдущем примере:

pObserver observer;
algorithm.SubscribeObserver( &observer );
Запуск эволюции:

algorithm.StartSolving(false);

Пример 3: Задача коммивояжера

 

Снимок экрана – приложение TSP

Хромосома является массивом городов [указателей на объекты класса TspCity] в порядке их посещения. Ее реализует класс TspChromosome. Класс наследует GaMultiValueChromosome, чтобы реализовать пользовательскую инициализацию хромосомы путем переопределения метода MakeFromPrototype. Этот метод копирует города в код хромосом и затем меняет их местами. Этот класс также переопределяет метод MakeCopy и определяет копирующий конструктор.

class TspChromosome : public GaMultiValueChromosome<const TspCity*>
{
public:
    TspChromosome(GaChromosomeDomainBlock<const TspCity*>* configBlock) :
        GaMultiValueChromosome(configBlock) { }

    TspChromosome(const TspChromosome& chromosome,
        bool setupOnly) :
        GaMultiValueChromosome<const TspCity*>(chromosome, setupOnly) { }

    virtual GaChromosomePtr GACALL MakeCopy(bool setupOnly) const
        { return new TspChromosome( *this, setupOnly ); }

    virtual GaChromosomePtr GACALL MakeNewFromPrototype() const;

    int GACALL GetCityPosition(const TspCity* city) const;
};

Использование простой одноточечной или многоточечной операции кроссовера генерирует много неверных решений, что ухудшает производительность и результаты алгоритма. Во избежание генерации неверных решений алгоритм использует пользовательскую операцию кроссовера. Операция берет случайный город из одного родителя и копирует его в хромосому потомка. Затем она ищет города, соединенные с выбранным городом [в обоих родителях] и берет ближайший город [и копирует его в хромосому потомка], если он еще не взят. Он берется, если операция выбирает другой присоединенный город. Если взяты все присоединенные города, операция случайно выбирает не взятый город. Далее кроссовер использует этот город для такого же продления пути. Процесс повторяется, чтобы выбрать все города. Класс TspCrossover реализует эту операцию кроссовера:

class TspCrossover : public GaCrossoverOperation
{
public:
    virtual GaChromosomePtr GACALL operator ()(
        const GaChromosome* parent1,
        const GaChromosome* parent2) const;

    virtual GaParameters* GACALL MakeParameters() const { return NULL; }

    virtual bool GACALL CheckParameters(
        const GaParameters& parameters) const { return true; }

private:
    inline void SelectNextCity(const TspCity* previousCity,
        const TspCity** currentBestNextCity,
        const TspCity* nextCity) const;
};

Алгоритм использует встроенную операцию GaSwapMutation. Значение пригодности равняется длине пути. Класс TspFitnessOperation реализует операцию пригодности:

class TspFitness : public GaFitnessOperation
{
public:
    virtual float GACALL operator ()(
        const GaChromosome* chromosome) const;

    virtual GaParameters* GACALL MakeParameters() const { return NULL; }

    virtual bool GACALL CheckParameters(
        const GaParameters& parameters) const { return true; }
};

Параметры хромосом:
1.    вероятность мутации: 3%
2.    размер мутации: 2
3.    исключительно улучшающие мутации: нет
4.    вероятность кроссовера: 80%
5.    число точек кроссовера: 1 [игнорируется]

CCB:
1.    TspCrossover
2.    TspSwapMutation
3.    TspFitnessOperation
4.    TspMinFitnessComparator
5.    Набор значений не определен

Параметры популяции:
1.    размер популяции: 100
2.    популяция с изменяемым размером: нет [используется инкрементный алгоритм, не требующий популяции с изменяемым размером]
3.    популяция отсортирована: да
4.    масштабированная пригодность используется для сортировки: нет
5.    отслеживание лучших хромосом: 0 [популяция уже отсортирована]
6.    отслеживание худших хромосом: 0 [популяция уже отсортирована]

Конфигурация популяции:
1.    Селекция GaSelectRandomBest, выбирающая 8 хромосом
2.    GaSimpleCoupling, вырабатывающая 8 хромосом потомства
3.    GaRandomReplaces, заменяющая 8 хромосом в каждой генерации, с размером элитизма в 10 хромосом
4.    Нет операции масштабирования

Алгоритм использует GaFitnessProgressCriteria, потому что не известно точное условие окончания. Условие остановит алгоритм, если не сможет улучшить значение пригодности больше чем на 1 за 50000 генераций. Генетический алгоритм инкрементный.

Класс TSP является контейнером для объекта алгоритма. Класс TspCity представляет и хранит информацию о городе [например, его координаты и название]. Он имеет метод GetDistance, вычисляющий расстояния между городами. TspCities управляет коллекцией городов, введенной пользователем.


Пример 4: Расписание занятий

 

Снимок экрана – приложение расписания занятий

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

Класс Schedule определяет представление хромосомы. Он наследует GaMultiValueChromosome.

class Schedule : public GaMultiValueChromosome<list<CourseClass*> >
{
    friend class ScheduleCrossover;
    friend class ScheduleMutation;
    friend class ScheduleFitness;
    friend class ScheduleObserver;

private:
    CourseClassHashMap _classes;

    CourseClassHashMap _backupClasses;

    // Флаги удовлетворения требований занятий
    mutable vector<bool> _criteria;

public:
    Schedule(GaChromosomeDomainBlock<list<CourseClass*> >* configBlock);

    Schedule(const Schedule& c, bool setupOnly);

    virtual ~Schedule() { }

    virtual GaChromosomePtr GACALL MakeCopy(bool setupOnly) const
        { return new Schedule( *this, setupOnly ); }

    virtual GaChromosomePtr GACALL MakeNewFromPrototype() const;

    virtual void GACALL PreapareForMutation();

    virtual void GACALL AcceptMutation();

    virtual void GACALL RejectMutation();

    // Возвращает ссылку на таблицу занятий
    inline const hash_map<courseclass*, />& GetClasses() const
        { return _classes; }

    // Возвращает массив флагов удовлетворения требований занятий
    inline const vector<bool>& GetCriteria() const
        { return _criteria; }

    // Возвращает ссылку на массив интервалов времени
    inline const vector<list<CourseClass*>>& GetSlots() const
        { return _values; }
};

Затем определяются операции кроссовера, мутации и пригодности:

class ScheduleCrossover : public GaCrossoverOperation
{
public:
    virtual GaChromosomePtr GACALL operator ()(
        const GaChromosome* parent1,
        const GaChromosome* parent2) const;

    virtual GaParameters* GACALL MakeParameters() const
        { return NULL; }

    virtual bool GACALL CheckParameters(
        const GaParameters& parameters) const { return true; }

};

class ScheduleMutation : public GaMutationOperation
{
public:

    virtual void GACALL operator ()(
        GaChromosome* chromosome) const;

    virtual GaParameters* GACALL MakeParameters() const
        { return NULL; }

    virtual bool GACALL CheckParameters(
        const GaParameters& parameters) const { return true; }

};

class ScheduleFitness : public GaFitnessOperation
{
public:

    virtual float GACALL operator ()(
        const GaChromosome* chromosome) const;

    virtual GaParameters* GACALL MakeParameters() const
        { return NULL; }

    virtual bool GACALL CheckParameters(
        const GaParameters& parameters) const { return true; }
};

Дополнительную информацию о представлении хромосом и упомянутых операциях смотрите в этой статье.
Класс ScheduleTest является контейнером для объектов генетического алгоритма.

ScheduleTest::ScheduleTest()
{
  // инициализировать внутренние структуры библиотеки генетических алгоритмов
  GaInitialize();

  // создать параметры хромосомы
  // вероятность кроссовера: 80%
  // точки кроссовера: 2
  // нет "исключительно улучшающих мутаций"
  // вероятность мутации: 3%
  // число перемещенных занятий за мутацию: 2
  _chromosomeParams = new GaChromosomeParams(
    0.03F, 2, false, 0.8F, 2 );

  // создать CCB со следующими настройками:
  // нет набора значений
  // с генетическими операциями ScheduleCrossover, ScheduleMutation и
  // ScheduleFitness
  // установить сравнитель пригодности для максимизации значения пригодности
  // использовать ранее определенные параметры хромосомы
  _ccb = new GaChromosomeDomainBlock<list<courseclass* /> >(
    NULL, &_crossoverOperation, &_mutationOperation,
    &_fitnessOperation,
    GaFitnessComparatorCatalogue::Instance().GetEntryData(
    "GaMaxFitnessComparator" ),
    _chromosomeParams );

  // создать прототип хромосомы
  _prototype = new Schedule( _ccb );

  // создать параметры популяции
  // число хромосом в популяции: 100
  // популяция всегда имеет фиксированное число хромосом
  // популяция не отсортирована
  // используются непреобразованные(немасштабированные) значения пригодности
  // для сортировки и отслеживания хромосом
  // популяция отслеживает 5 лучших и 5 худших хромосомы
  GaPopulationParameters populationParams(
    100, false, true, false, 2, 0 );

  // создать параметры для операции селекции
  // селекция будет выбирать 16 хромосом,
  // но лишь 8 лучших из них будут сохраняться в набор результатов селекции
  // в наборе результатов не будет дубликатов хромосом
  GaSelectRandomBestParams selParam( 10, false, 16 );

  // создать параметры для операции замены
  // заменить 8 хромосом,
  // но оставить 5 лучших хромосом в популяции
  GaReplaceElitismParams repParam( 10, 2 );

  // создать параметры для операции спаривания
  // операция спаривания будет вырабатывать 8 новых хромосом
  // из выбранных родителей
  GaCouplingParams coupParam( 10 );

  // создать конфигурацию популяции
  // использовать определенные параметры популяции
  // использовать для сортировки такой же сравнитель, как и используемый хромосомами сравнитель
  // использовать операцию селекции, случайно выбирающую хромосомы
  // использовать операцию замены, случайно выбирающую подлежащие замене
  // хромосомы из популяции,
  // но оставляющую лучшие хромосомы
  // использовать простое спаривание
  // отключить масштабирование
  _populationConfig = new GaPopulationConfiguration( populationParams,
    &_ccb->GetFitnessComparator(),
    GaSelectionCatalogue::Instance().GetEntryData(
    "GaSelectRandom" ), &selParam,
    GaReplacementCatalogue::Instance().GetEntryData(
    "GaReplaceRandom" ), &repParam,
    GaCouplingCatalogue::Instance().GetEntryData(
    "GaSimpleCoupling" ), &coupParam,
    NULL, NULL );

  // создать популяцию
  // с ранее определенным прототипом хромосом
  // и конфигурацией популяции
  _population = new GaPopulation( _prototype, _populationConfig );

  // создать параметры для генетических алгоритмов
  // алгоритм будет использовать два рабочих процесса
  GaMultithreadingAlgorithmParams algorithmParams( 2 );
  // создать инкрементный алгоритм с ранее определенной популяцией
  // и параметрами
  _algorithm = new GaIncrementalAlgorithm(
    _population, algorithmParams );

  // создать параметры для условия остановки на основе значения пригодности
  // остановиться, когда лучшая хромосома достигнет значения пригодности 1
  GaFitnessCriteriaParams criteriaParams(
    1, GFC_EQUALS_TO, GSV_BEST_FITNESS );

  // установить условие остановки алгоритма (основанное на значении пригодности)
  // и его параметры
  _algorithm->SetStopCriteria(
    GaStopCriteriaCatalogue::Instance().GetEntryData(
    "GaFitnessCriteria" ), &criteriaParams );

  // подписать наблюдателя
  _algorithm->SubscribeObserver( &_observer );
}

Переносимость, компиляция и подключение библиотеки генетических алгоритмов

Библиотека генетических алгоритмов поддерживает следующие компиляторы и платформы:

 

Microsoft C++

Intel C++

GCC G++

Borland C++

Sun Studio C++

Windows

12

12

~

6

~

Linux

~

34

34

~

~

Mac OS X

~

34

34

~

~

*BSD

~

~

345

~

~

Solaris

~

~

5

~

8

- Компилятор поддерживается.

~

- Компилятор не поддерживается.

1

- Доступно в виде проекта Visual Studio.

2

- Компилируется в виде статической или динамической библиотеки (DLL).

3

- Доступен сборочный файл.

4

- Компилируется только как статическая библиотека.

5

- команда gmake используется для компоновки библиотеки.

6

- компилятор надо настроить на использование библиотеки STLport.

7

- команда dmake используется для компоновки библиотеки.

Библиотека содержит набор директив препроцессора, управляющих процессом компиляции в соответствии с обнаруженным компилятором и целевой операционной системой.


Платформа Windows

Библиотека генетических алгоритмов доступна в двух версиях проектов Visual Studio 2005. Первый настроен на использование компилятора Microsoft C/C++, а второй использует компилятор Intel C++. Проекты расположены в каталоге /vs.

Чтобы добавить функционал библиотеки генетических алгоритмов в приложение, библиотеку надо подключить к нему. В Visual Studio 2005 это делается двумя способами:

•    Способ 1
Добавление проекта библиотеки генетических алгоритмов в решение приложения и установка ссылки на проект библиотеки генетических алгоритмов.

•    Способ 2
1.    Добавление GeneticAlgorithm.lib в Свойства проекта->Линкер->Дополнительные зависимости.
2.    Установка правильных каталогов, чтобы Visual Studio могла найти библиотеку и ее заголовки. Это можно сделать локально или глобально.
     a.    Локально
         I.    Добавление GeneticLibrary.lib в:

         Свойства проекта->Линкер->Общие->Каталоги дополнительных библиотек
         Project Properties->Linker->General->Additional Library Directories

         II.    Добавление каталога исходного кода библиотеки генетических алгоритмов (/source) в поиски препроцессора:

         Свойства проекта->C/C++->Общие ->Дополнительные каталоги включения
         Project Properties->C/C++->General->Additional Include Directories

     b.    Глобально путем добавления каталогов в соответствующие места (включаемые файлы и файлы библиотеки)

         Инструменты->Опции->Проекты и решения->Каталоги VC++
         Tools->Options->Projects and Solutions->VC++ Directories

Процедуры одинаковы для обеих версий проекта.

Библиотеку можно скомпилировать как статическую или динамическую [DLL] библиотеку. По умолчанию она компилируется как DLL; если она компилируется и используется как статическая библиотека, GENETICLIBRARY_STATIC должен быть определен.

Выходными файлами являются GeneticLibrary.dll и GeneticLibrary.lib, если библиотека компилируется как DLL, или только GeneticLibrary.lib, если она компилируется как статическая библиотека. Эти файлы расположены в каталоге /build/%configuration%/%compiler%, где %configuration% является debug(отладка) or release(выпуск), и %compiler% является msvc для компилятора Microsoft C/C++ или icc_win для компилятора Intel C++. Файл GeneticLibrary.dll надо скопировать в тот же каталог, где находится исполняемый файл приложения.

По умолчанию библиотека генетических алгоритмов подключена к динамической версии стандартных библиотек времени выполнения [CRT]. Если библиотека подключена к динамической версии CRT, приложение может не запуститься на машинах, на которых не установлен свободно распространяемый пакет Microsoft Visual C++ 2005. Важно отметить, что приложение, использующее библиотеку генетических алгоритмов, должно быть подключено к такой же версии CRT как библиотека.

Платформы Linux, Mac OS X, Solaris и *BSD

Библиотека компилируется из консоли путем вызова make с соответствующим сборочным файлом. В операционной системе Solaris gmake применяется для компиляции библиотеки с помощью GCC G++, а dmake – для компиляции с помощью Sun Studio C++. В системах *BSD используется сборщик GNU [gmake] вместо сборщика BSD [make].

make -f %compiler%_%platform%_%configuration% all

где %compiler% является:
•    gcc – для компилятора GCC G++.
•    icc - для компилятора Intel C++.
•    scc - для компилятора Sun Studio C++.

%platform%s являются следующими:
•    linux – для семейства операционных систем Linux.
•    macos – для операционной системы Mac OS X.
•    solaris - для операционной системы Solaris.
•    bsd - для семейства операционных систем BSD.

а конфигурация является одной из следующих:
•    debug(отладка) – компилирует библиотеку с отладочной информацией и без оптимизации.
•    release(выпуск) - компилирует библиотеку с генерацией оптимизированного кода и удаляет отладочную информацию.

Сборочные файлы находятся в каталоге /makefiles.

make -f icc_linux_debug all

Пример: компиляция в режиме отладки на Linux с помощью Intel C++

gmake -f gcc_bsd_release all

Пример – компиляция в режиме выпуска на FreeBSD с помощью GCC G++

Выходной файл является статической библиотекой по имени libGeneticLibrary.a и расположен в каталоге /build/%configuration%/%compiler%_%platform%.

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

g++ -Wl,-L"%path_to_library%/build/%configuration%/%compiler%_%platform%"
     -lGeneticLibrary -o "application_executable" [список объектных файлов]

Для компилятора Intel C++ пользователь должен использовать команду icpc вместо g++, а для компилятора Sun Studio C++ - команду cc.

%path_to_library% - путь к каталогу, где расположена библиотека. На некоторых платформах есть дополнительные требования для подключения приложения к библиотеке генетических алгоритмов. В Linux в линкере надо задать ключ -lrt. Линкер Sun Studio требует ключей -library=stlport4 и -lrt, а линкер GNU в системе *BSD требует ключей -march=i486 и -lpthread.

Переносимость

Чтобы перенести данную библиотеку на другие платформы без существенных изменений ядра библиотеки, целевая платформа должна поддерживать:
•    Многопоточность – если целевая платформа поддерживает потоки POSIX, перенос упрощается, так как библиотека генетических алгоритмов уже использует Pthreads для многопоточности в UNIX-подобных системах.
•    Элементарные операции инкремента и декремента, а также элементарные команды сравнения и обмена или элементарные операции обмена.
•    STL - библиотека генетических алгоритмов в некоторых частях опирается на STL и некоторые нестандартные расширения STL, такие как hash_map.
•    Стандарт IEEE754 для чисел с плавающей точкой – некоторые части библиотеки, такие как генератор случайных чисел, предполагает, что архитектура целевого процессора поддерживает данный стандарт.