Experiment: drift

Cieľom je merať drift rôznych metód selekcie. Ide o to, že aj v prípade, že jedince v populácii majú rovnakú vhodnosť, selekčná metóda môže uprednostňovať niektoré jedince na úkor iných jedincov. Teda aj napriek rovnakej vhodnosti niektoré jedince môžu z populácie vypadávať zatiaľ čo iné jedince môžu zvyšovať svoje zastúpenie v populácii.

Podstata experimentu

Sú dané dve skupiny jedincov, pričom každá z nich obsahuje jedince s rovnakou pridelenou vhodnosťou. Obe skupiny jedincov sú rovnako veľké.

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 vopred stanovený počet vykonaných selekcií. Môže nastať prípad, že na konci série selekcií:

  1. obe skupiny jedincov budú približne rovnako veľké,
  2. jedna skupina jedincov bude signifikantne väčšia ako druhá skupina,
  3. v populácii sa vyskytuje iba jedna zo skupín jedincov.

Keďže sa jedná o stochastický proces, tak pre získanie priemerného chovania musí byť viackrát opakovaný pre získanie spoľahlivej vzorky dát. Avšak v tomto experimente nie je ani tak zaujímavé priemerné chovanie, pretože spriemernením dvoch extrémnych chovaní (vytlačenie raz jedného a raz druhého typu jedincov z populácie) vedie na priemerné chovanie (priemerne rovnaké počty jedincov oboch typov), ktoré môže byť výrazne odlišné od skutočného priemerného chovania.

Príprava

Pre prípravu experimentu je potrebné doplniť (nahradiť) kód v 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:

  1. premapovanie vhodnosti (aktuálne identita t.j. žiadne)
  2. určenie pravdepodobnosti selekcie (aktuálne proporcionálna selekcia)
  3. vzorkovanie jedného rodiča (aktuálne SSwR)
  4. selekciu rodičov (aktuálne opakovaná selekcia po jednom rodičovi)
In [1]:
import random
from functools import reduce
from operator import add
import matplotlib.pyplot as plt
In [2]:
# Generovanie populácie

μ = 100  # veľkosť populácie - parne cislo
jedince = [1 for i in range(μ//2)] + [0 for i in range(μ-μ//2)]  # dva typy jedincov
#jedince
In [3]:
# Určenie vhodnosti jedincov

FIT = 0.2  # vhodnosť kazdeho jedinca bez ohladu na jeho typ

def Φ(jedinec):
    return FIT

populacia = [(i, Φ(i)) for i in jedince]
#populacia
In [4]:
# Určenie distribúcie jedincov

def distribucia(populacia):
    dist = reduce(add, map(lambda x: x[0], populacia))
    return μ-dist, dist

distribucia(populacia)
Out[4]:
(50, 50)
In [5]:
# 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

distribucia(selekcia(populacia))
Out[5]:
(48, 52)
In [6]:
# Experiment - jeden beh

POC_SELEKCII = 300

def seria_selekcii(populacia):
    pocet_jedincov_0 = [distribucia(populacia)[0]]  # pocet jedincov 0 v populacii pred seriou selekcii
    vyber_z_populacie = populacia
    for i in range(POC_SELEKCII):
        zdrojova_populacia = vyber_z_populacie
        vyber_z_populacie = selekcia(zdrojova_populacia)
        pocet_jedincov_0.append(distribucia(vyber_z_populacie)[0])
    return pocet_jedincov_0
In [7]:
# Experiment - opakovane sekvencie selekcii

OPAKOVANIA = 1   # 1 vs 100

vysledky = [0 for _ in range(POC_SELEKCII+1)]
for _ in range(OPAKOVANIA):
    seria = seria_selekcii(populacia)
    vysledky = map(add, vysledky, seria)
vysledky = [x / OPAKOVANIA for x in vysledky]


plt.suptitle("Distribúcia typov jedincov")
plt.xlabel("selekcia")
plt.ylabel("pomer typov jedincov")
plt.ylim([-2,102])
plt.plot(vysledky)

plt.show()