Cieľom je merať selekčný tlak rôznych metód selekcie. Ide o to, ako veľmi jednotlivé selekčné metódy uprednostňujú jedincov s vyššou vhodnosťou oproti jedincom s vhodnosťou nižšou.
Selekčný tlak bude meraný nepriamo pomocou určenia doby prevzatia (takeover time), čo je doba ktorú potrebuje jedinec s najväčšou vhodnosťou na to, aby sa stal dominantným v populácii (aby vyplnil celú populáciu svojimi kópiami). Čím je doba prevzatia menšia, tým silnejšie musel byť najlepší jedinec preferovaný voči ostatným jedincom a teda tým je vyvinutý selekčný tlak väčší.
Je daná skupina jedincov, pričom každý z nich má pridelenú vhodnosť. Existuje jeden jedinec s najväčšou vhodnosťou (trebárs Φ(best)=1.0), zatiaľ čo ostatné jedince majú vhodnosť menšiu (môžu mať navzájom rôzne vhodnosti ale nie je to nutné).
Realizuje sa selekčný proces ako séria selekcií tvaru P -> P' -> P'' -> ... -> P''''''', pričom každá selekcia robí výber zo skupiny jedincov, ktorá vznikla ako výsledok predchádzajúcej selekcie. Toto reťazenie pokračuje dovtedy, kým nenastane jedna zo situácií:
Keďže sa jedná o stochastický proces, tak musí byť viackrát opakovaný pre získanie spoľahlivej vzorky dát. Ak v rámci tohto opakovania sa viackrát stalo, že najlepší jedinec dominoval v populácii, tak sa určí priemerný počet selekcií, ktorý je potrebným pre dosiahnutie tejto dominancie.
Pre prípravu experimentu je potrebné doplniť (nahradiť) kód bunke venovanej selekčnej metóde. Aktuálne je v nej imlementované vzorkovanie SSwR (teda základná ruleta). Je možné meniť metódu pre:
import random
from functools import reduce
from operator import add
# Generovanie populácie
μ = 100 # veľkosť populácie
jedince = [1] + [0 for i in range(μ-1)]
#jedince
# Určenie vhodnosti jedincov
MIN = 0.2 # minimalna mozna vhodnosť jedincov (okrem najlepsieho)
MAX = 0.5 # maximalna mozna vhodnosť jedincov (okrem najlepsieho)
def Φ(jedinec):
if jedinec == 1:
return 1.0
else:
return random.uniform(MIN, MAX)
populacia = [(i, Φ(i)) for i in jedince]
#populacia
# Selekčná metóda - vyberá sa toľko rodičov, koľko je jedincov v populácii
def premapovanie_vhodnosti(jedince): # identita
map_fun = lambda x: x
premap_Φ = [map_fun(x) for (_,x) in jedince]
return premap_Φ
def urcenie_pravdepodobnosti_selekcie(premap_Φ, jedince): # proporcionalna selekcia
sum_Φ = reduce(add, premap_Φ)
ps = [Φ/sum_Φ for Φ in premap_Φ]
return ps
def vyber_rodica(ps, jedince): # SSwR vzorkovanie - nepresne (maximalne rozpatie)
jazycek = μ * random.random()
index = 0
sum_η = ps[index] * μ
while(sum_η < jazycek):
index += 1
sum_η += ps[index] * μ
return jedince[index]
def selekcia(jedince):
premap_Φ = premapovanie_vhodnosti(jedince)
ps = urcenie_pravdepodobnosti_selekcie(premap_Φ, jedince)
rodicia = []
for _ in range(μ):
rodicia.append(vyber_rodica(ps, jedince))
return rodicia
# Experiment - jeden beh
MAXPOC_SELEKCII = 2 * μ
def seria_selekcii(populacia):
vyber_z_populacie = populacia
for i in range(MAXPOC_SELEKCII):
zdrojova_populacia = vyber_z_populacie
vyber_z_populacie = selekcia(zdrojova_populacia)
poc_kopii_najlepsieho = reduce(add, map(lambda x: x[0], vyber_z_populacie))
if poc_kopii_najlepsieho == μ:
return 'vyplnenie', i
if poc_kopii_najlepsieho == 0:
return 'strata', i+1
return 'vyskyt', i+1
# Experiment - opakovane sekvencie selekcii
OPAKOVANIA = 1000
vysledky = [seria_selekcii(populacia) for _ in range(OPAKOVANIA)]
print(
f"Pocet behov "
f"\n so stratou najlepsieho : {len(list(filter(lambda x: x[0] == 'strata', vysledky)))}"
f"\n s dominanciou najlepsieho : {len(list(filter(lambda x: x[0] == 'vyplnenie', vysledky)))}"
f"\n s vyskytom najlepsieho : {len(list(filter(lambda x: x[0] == 'vyskyt', vysledky)))}"
)
vyplnenia = list(map(lambda x: x[1], (filter(lambda x: x[0] == 'vyplnenie', vysledky))))
if vyplnenia != []:
print(f"Pri dominancii najlepsi dominoval priemerne v {reduce(add,vyplnenia)/len(vyplnenia)}. iteracii")