Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // GA.cpp : Этот файл содержит функцию "main". Здесь начинается и заканчивается выполнение программы.
- //
- #include <iostream>
- #include <random>
- #include <vector>
- #include <ctime>
- #include <cmath>
- using namespace std;
- using Genome = vector<bool>; //геном
- std::default_random_engine generator(time(0));
- int nGenome = 10; //первые 4 бита - под целое число, 6 битов под дробную часть
- //чтобы закодировать числа [1, 10], достаточно 4-х бит
- int nPoplulation = 100;
- double f(double x) { //вычисляемая функция
- if (x < 1 || x>10) return 0;
- return 3 * x * x * x - 2 * x + 5;
- }
- Genome DecimalToBinary(Genome genome, int num) {
- int i = 0;
- while (num != 1) {
- genome[i]=(num % 2);
- num /= 2;
- i++;
- }
- genome[i] = 1;
- return genome;
- }
- double BinaryToDecimal(Genome genome) {
- double num=0;
- for (int i = 0; i < genome.size(); i++) {
- num += genome[i] * pow(2, i);
- }
- num /= pow(2, 6);
- return num;
- }
- Genome Shotgun(Genome genome) { //стратегия "дробовика"
- for (int i = 0; i < genome.size(); i++)
- genome[i] = rand() % 2;
- return genome;
- }
- Genome Focus(Genome genome, double x1, double x2) { //стратегия фокусировки
- std::default_random_engine generator (time(0));
- std::uniform_real_distribution<double> distributionDouble(x1, x2);
- double num = distributionDouble(generator);
- num *= pow(2, 6);
- num = round(num);
- genome = DecimalToBinary(genome, num);
- return genome;
- }
- void CreateStartPopulation(vector<Genome>& population, int choice) { //создание начальной популяции
- switch (choice) {
- case 1: {
- for (int i = 0; i < population.size(); i++) {
- Genome genome(nGenome, 0);
- population[i] = Shotgun(genome);
- }
- break;
- }
- case 2: {
- int x1; int x2;
- cout << "\nInput the range (from/to)\n";
- cin >> x1; cin >> x2;
- for (int i = 0; i < population.size(); i++) {
- Genome genome(nGenome, 0);
- population[i] = Focus(genome, x1, x2);
- }
- break;
- }
- default:
- break;
- }
- }
- pair<int, int> IndexGeneration(vector<double>& ProbabilisticSeries) { //ищет подходящие индексы в массиве частичных сумм
- pair<int, int> PairIndexes; double index1, index2;
- std::uniform_real_distribution<double> distributionDouble(0, 1);
- index1 = distributionDouble(generator);
- for (int i = 0; i < nPoplulation; i++)
- if (index1 < ProbabilisticSeries[i]) {
- index1 = i;
- break;
- }
- index2 = distributionDouble(generator);
- for (int i = 0; i < nPoplulation; i++)
- if (index2 < ProbabilisticSeries[i]) {
- index2 = i;
- break;
- }
- PairIndexes.first = index1;
- PairIndexes.second = index2;
- return PairIndexes;
- }
- vector<pair<int, int>> RandomSelection(vector<Genome> population) {
- double sumF = 0;
- vector<double>GenomeDecimalValue;
- for (int i = 0; i < nPoplulation; i++) {
- GenomeDecimalValue.push_back(f(BinaryToDecimal(population[i]))); //перевод каждого генома в десятичное число
- // и взятие ЦФ от полученного десятичного числа
- sumF += GenomeDecimalValue.back(); //сумма всех значений ЦФ
- }
- for (int i = 0; i < nPoplulation; i++)
- GenomeDecimalValue[i] = GenomeDecimalValue[i] / sumF; //доля каждого генома в общей массе
- vector<double>ProbabilisticSeries; // массив с частичными суммами
- for (int i = 0; i < nPoplulation; i++) {
- sumF = 0;
- for (int j = 0; j <= i; j++)
- sumF += GenomeDecimalValue[j];
- ProbabilisticSeries.push_back(sumF);
- }
- vector<pair<int, int>> PairsIndexes;
- for (int i = 0; i < nPoplulation; i++) {
- PairsIndexes.emplace_back(IndexGeneration(ProbabilisticSeries));
- }
- return PairsIndexes;
- }
- pair<Genome,Genome> SinglePointCrossover(Genome mama, Genome papa) {
- int point = rand() % (nGenome-1) + 1;
- Genome daughter; Genome son;
- daughter = mama;
- son = papa;
- for (int i = point; i < nGenome; i++) swap(daughter[i], son[i]);
- pair<Genome, Genome> kids;
- kids.first = daughter; kids.second = son;
- return kids;
- }
- pair<Genome, Genome> TwoPointCrossover(Genome mama, Genome papa) {
- int point1, point2;
- point1 = rand() % (nGenome - 1) + 1;
- point2 = rand() % (nGenome - 1) + 1;
- while(point1==point2) point2 = rand() % (nGenome - 1) + 1;
- if (point1 > point2) swap(point1, point2);
- Genome daughter; Genome son;
- daughter = mama;
- son = papa;
- for (int i = point1; i < point2; i++)
- swap(daughter[i], son[i]);
- pair<Genome, Genome> kids;
- kids.first = daughter; kids.second = son;
- return kids;
- }
- vector<Genome> Offsprings(vector<pair<int, int>> RandomSelection, vector<Genome>& population) {
- int choice;
- cin >> choice;
- vector<Genome> offsprings; pair<Genome, Genome> kids;
- switch (choice) {
- case 1: {
- for (int i = 0; i < population.size(); i++) {
- kids = SinglePointCrossover(population[RandomSelection[i].first], population[RandomSelection[i].second]);
- offsprings.push_back(kids.first);
- offsprings.push_back(kids.second);
- }
- }
- case 2: {
- for (int i = 0; i < population.size(); i++) {
- kids = TwoPointCrossover(population[RandomSelection[i].first], population[RandomSelection[i].second]);
- offsprings.push_back(kids.first);
- offsprings.push_back(kids.second);
- }
- }
- }
- return offsprings;
- }
- void OutputGenome(Genome genome) {
- for (int i = 0; i < nGenome; i++)
- cout << genome[i];
- cout << endl;
- }
- int main()
- {
- vector<Genome> population (nPoplulation);
- srand(time(0));
- CreateStartPopulation(population, 1);
- vector<pair<int, int>> temp = RandomSelection(population);
- for (int i = 0; i < nPoplulation; i++)
- {
- cout << temp[i].first << "\t" << temp[i].second << "\n";
- OutputGenome(population[temp[i].first]);
- cout << endl;
- OutputGenome(population[temp[i].second]);
- cout << endl;
- }
- cout << endl;
- vector<Genome> offsprings(2 * nPoplulation);
- offsprings = Offsprings(temp, population);
- for (int i = 0; i < 2 * nPoplulation; i++)
- {
- cout << i << ": ";
- OutputGenome(offsprings[i]);
- }
- }
Add Comment
Please, Sign In to add comment