Библиотека генетических алгоритмов - часть 4 - Пример 2: Сравнение с образцом
ОГЛАВЛЕНИЕ
Пример 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<char>*>
(chromosome)->GetCode();
int score=0;
for(int i=0;i<patternSize;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);