Algorytm genetyczny pomoc

0

Mam na zadanie taki program i utknąłem w martwym punkcie.
Napisać program symulujący ewolucję populacji osobników. Populacja może liczyć dowolną liczbę osobników. Każdy osobnik zawiera chromosom, który jest ciągiem liczb naturalnych. Chromosomy mogą być różnej długości. W każdym pokoleniu wylosowywanych jest k par osobników, które się następnie krzyżują. Krzyżowanie polega na tym, że u każdego osobnika dochodzi do pęknięcia chromosomu w dowolnym miejscu. Część początkowa chromosomu jednego osobnika łączy się z częścią końcową drugiego. Inaczej mówiąc: osobniki wymieniają się fragmentami swoich chromosomów. Jeden osobnik może być wylosowany do kilku krzyżowań. Po dokonaniu wszystkich krzyżowań w pokoleniu sprawdzane jest przystosowanie osobników do warunków środowiska. W tym celu dla każdego osobnika wyznaczana jest wartość f ∈ [0, 1] funkcji dopasowania.
Plik wejściowy ma następującą postać: Każda linia zawiera jednego osobnika. Osobnik charakteryzowany jest chromosomem, który jest przedstawiony jako ciąg liczb naturalnych rozdzielonych białymi znakami. Przykładowy plik wejściowy zawierający populację złożoną z czterech osobników:
8 2 56 9 8 6 25 45
6 92 43 7 98
2 4 34 5
23 66 22 8 34 6 1 6 8 7 88

Jedynie co mam to wypisywanie plików. Dalej nie mam pomysłu na losowanie i dzielenie.

#include <iostream>
#include <vector>
#include <string>
#include<sstream>
#include <fstream>
using namespace std;
struct osoba
{
	vector<int> frag;

};
int main()
{
	odczyt();

}
void odczyt()
{
	fstream plikw;
	plikw.open("Plik txt chrom.txt");
	if (plikw.good() == false) cout << "Plki jest w zlym folderze, lub nie istnieje";
	vector<osoba> chromosom;
	for (string line; getline(plikw, line); cout << endl)
	{
		stringstream stem(line);
		chromosom.emplace_back();
		for (int temp; stem >> temp; cout << temp << ' ') chromosom.back().frag.push_back(temp);
	}
	plikw.close();
}
void mieszanie()
{
 ???????
}

Prosiłbym o pomoc i wyjaśnienie.
Ma to działać na vektorach i strukturze osoba.

2
  1. Fajnie, ale w treści zadania nie ma funkcji celu (którą trzeba zoptymalizować).
    Jest o tyle dobrze, że jest wspomniana jako "funkcja dopasowania".
    Bez tego nic nie "wylosujesz" bo nie masz danych do tego potrzebnych.
  2. nie ma nic o mutacjach
  3. "osoba" != "osobnik"
  4. zamiast void mieszanie() napisz Osobnik krzyzuj(const Osobnik&a, const Osobnik& b). Swoją drogą to problem jest postawiony na głowie, bo zwykle funkcję krzyżowania się samemu dobiera, gdy znana jest funkcja dopasowania (funkcja krzyżowania ma być mało szkodliwa dla wyniku dopasowania).
  5. reszta rad, po tym jak ponaprawiasz 1-4.
0

funkcji dopasowania. Osobniki, dla których wartość f < w (gdzie w jest progiem wymierania), są usuwane z populacji. Osobniki, dla których f > r (gdzie r jest progiem rozmnażania) są klonowane. A osobniki, dla których w <= f <= r pozostają w populacji, ale się nie rozmnażają.

#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include<sstream>
#include<time.h>
struct osobnik
{
std::vector<int> allel;

};
void wczytywanie()
{
std::fstream plik;
plik.open("Chromosom.txt");
if (plik.good() == false) std::cout << "Plki jest umieszczony w zlym folderze, lub nie istnieje";
std::vector<osobnik> chromosom;
std::cout << "Wszytkie osobniki : \n\n";
for (std::string line; getline(plik, line); std::cout << std::endl)
{
std::stringstream ss(line);
chromosom.emplace_back();
for (int temp; ss >> temp; std::cout << temp << ' ') chromosom.back().allel.push_back(temp);
}
std::cout << "\n\nilosc elementow vektora : " << chromosom.size();
plik.close();
}

osobnik krzyzuj(const osobnik& a, const osobnik& b)
{

}

int main()
{
wczytywanie();

}

0
Alphaaa napisał(a):

funkcji dopasowania. Osobniki, dla których wartość f < w (gdzie w jest progiem wymierania), są usuwane z populacji. Osobniki, dla których f > r (gdzie r jest progiem rozmnażania) są klonowane. A osobniki, dla których w <= f <= r pozostają w populacji, ale się nie rozmnażają.

To nie jest definicja funkcji dopasowania! Ale jakaś kulawa wersja jak taka funkcja może być wykorzystana (kulawa wersja algorytmu genetycznego).
Funkcja dopasowania w kodzie ma taki prototyp:

double jakDobrzeSobieRadziOsobnik(const osobnik& o)
{
      return ....;
}

Np może to być długość jaką pokona sprzedawca odwiedzający wszystkie miasta (problem komiwojażera).
Jeśli nie masz definicji f (jaka wartość f jest obliczona dla osobnika), to jedynie co możesz zrobić to napisać abstrakcję algorytmu genetycznego (wzorzec strategia), ale w tej chwili (i przez najbkliższe X lat) jest to poza twoim zasięgiem. Zadanie wygląda na coś konkretnego, ergo musisz gdzieś mieć definicję f.

Tak jak już wspomniałem f jest najważniejszym elementem algorytmu genetycznego. To on stanowi definicję problemu do rozwiązania.
To do f dobiera się wszystko inne, od opisu osobnika (chromosomu), przez operator krzyżowania, po operator mutacji.
Bez f (funkcji dopasowania) nie ma szans byś rozwiązał zadanie.
Jeśli autor zadania opisał wszystko poza funkcją dopasowania, to znaczy, że sam nie rozumie co robi algorytm genetyczny. Ja stawiam na to, że masz dziurę w notatkach.

1

Jaki jest cel Twojego tego algorytmu? Co chcesz osiągnąć?
Po co oni się mają krzyżować jakie są pożądane cechy "osobnika" docelowego?
Innymi słowy jakie cechy ma spełniać ciąg liczb naturalnych osobnika, który jest najlepszy?

0

@MarekR22: a to nie jest tak, ze dopasowanie to wartosc osobnika (liczona funkcja celu) wzgledem populacji?

1

Algorytm genetyczny stosuje się do problemów, gdzie masz funkcję celu i szukasz minimum tej funkcji.
To jest miękka metoda szukania minimum jakiejś funkcji i stosuje się ją w momencie, gdzie klasyczne metody (jak metoda Newtona) jest zbyt skomplikowana lub nieefektywna (bo np liczba zmiennych jest za duża).

Daną wejściową zawsze jest funkcja którą chcemy minimalizować.
Wyjściem ma być argument, dla którego ta funkcja daje wartość minimalną.

Klasyczne przykłady:

  • szukanie najkrótszej drogi w problemie komiwojażera - funkcja celu opisuję drogę jaką pokonuje sprzedawca
  • problem minimalnego rozkroju - funkcja celu to ilość odpadów
  • skręcanie białek - funkcja celu to energia potencjalna molekuły

Nie mając funkcji celu/dopasowania/długości drogi czy jakikolwiek to nazwać, nie ma problemu do rozwiązania.

Ergo treść tego zadania, wygląda jak lista podpowiedzi do implementacji algorytmu, a nie opis samego problemu.

0

@MarekR22: albo moze inaczej to powiem

def SGA[A](
  crossoverOperator: (DenseVector[A], DenseVector[A]) => (DenseVector[A], DenseVector[A]),
  mutationOperator: DenseVector[A] => DenseVector[A],
  objectiveFunction: DenseVector[A] => Double,
  initialPopulation: DenseMatrix[A],
  populationSize: Int = 500,
  numberOfOffspring: Int = 500,
  crossoverProbability: Double = 0.95,
  mutationProbability: Double = 0.25,
  iterations: Int = 500,
  log: Boolean = true
)

Tutaj jest sygnatura jakiejs mojej implementacji SGA.
Funkcja celu, operator mutacji itd. to tylko parametry. Nie sa one krytyczne do implementacji samego SGA.

EDIT: oczywiscie do testowania juz sa potrzebne

0

Dobrze, czyli chodzi o jakiegoś osobnika docelowego, czyli np. const std::string cel = "2 4 24 2 8 65 43"; ale dalej nie wiem jak dzielić elementy vektora w losowych miejscach.

1

Tylko ze Ty masz problem z podstawami programowania a nie z SGA.

Trzeba wylosowac miejsce ciecia i przekopiowac od jednego rodzica i od drugiego.

1 użytkowników online, w tym zalogowanych: 0, gości: 1