Experiment: strata materiálu

Cieľom je merať stratu materiálu pri použití rôznych metód selekcie. Ide o to, že selekčná metóda vyvíja určitý špecifický selekčný tlak, meniteľný parametrami selekčnej metódy. Následkom toho niektoré jedince sú preferované na úkor iných jedincov - niektoré jedince sa nedostanú do skupiny rodičov zatiaľ čo iné jedince sa stanú rodičmi aj viacnásobne. Keďže každý jedinec je nositeľom určitého stavebného materiálu, z ktorého je možné vytvárať nových jedincov, tak nevybratie nejakého jedinca znamená ignoráciu materiálu neseného daným nevybratým jedincom.

V konečnom dôsledku dochádza k redukcii dostupného materiálu - nie všetok materiál, reprezentovaný pôvodnými jedincami, je dostupný v selektovanej skupine jedincov.

Podstata experimentu

Je daná skupina jedincov, pričom každý z nich má pridelenú náhodne vybratú hodnotu vhodnosti. Na základe tejto vhodnosti a použitej vzorkovacej metódy je možné pre každého jedinca určiť očakávanú pravdepodobnosť vzorkovania a následne pravdepodobnosť toho, že daný jedinec nebude vybratý a teda ním reprezentovaný materál bude ignorovaný.

Realizuje sa selekčný proces (keďže sa jedná o stochastický proces, tak sa viackrát opakuje pre získanie spoľahlivejšej vzorky dát). Pre každého jedinca sa zaznamená, koľkokrát bol počas jednotlivých opakovaní selekcie vyberaný za rodiča. Z týchto dát je možné pre každého jedinca určiť skutočnú hodnotu pravdepodobnosti, s ktorou bol daný jedinec výberom ignorovaný.

Určené pravdepodobnosti ignorovania jedincov sa použijú pre výpočet priemernej pravdepodobnosti ignorácie, ktorá reprezentuje stratu materiálu.

Príprava

Pre prípravu experimentu je potrebné doplniť (nahradiť) kód v bunke venovanej metódam premapovania vhodnosti a v bunke venovanej selekčnej metóde. Aktuálne je v nich imlementované premapovanie identitou (nemeniace hodnoty vhodnosti jedincov) a vzorkovanie SSwR (teda základná ruleta). Je možné meniť kód pre:

  1. premapovanie vhodnosti (okrem doplnenia kódu príslušnej metódy nezabudnúť vhodne nastaviť aj premennú Φmap)
  2. určenie pravdepodobnosti selekcie (aktuálne proporcionálna selekcia)
  3. vzorkovanie jedného rodiča v prípade použitia opakovanej selekcie (aktuálne SSwR) alebo vzorkovanie všetkých rodičov naraz v prípade jednorazovej selekcie (aktuálne neimplementované). Nezabudnúť vhodne (od/za)komentovať volania v tele funkcií selekcia a selekcia_opakovana.

Taktiež je potrebné vhodne (od/za)komentovať volania pre výpočet hodnôt strata_ocak a strata_skut v závislosti na použitom type selekčnej metódy (opakovanej alebo jednorazovej).

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
jedince = [(i,random.random()) for i in range(μ)]
In [3]:
# Premapovanie vhodnosti jedincov

def Φmap_identity(jedince):    # identita
    map_fun = lambda x: x
    premap_Φ = [(i,map_fun(x)) for (i,x) in jedince]
    return premap_Φ

def Φmap_lin(jedince):    # lineárne zotriedenie - TBD
    neimplementovane

def Φmap_exp(jedince):    # exponenciálne zotriedenie - TBD
    neimplementovane

def Φmap_qtur(jedince):   # q-turnaj premapovanie - TBD
    neimplementovane

def Φmap_orez(jedince):   # orezavacie zotriedenie - TBD
    neimplementovane

# zvolená metóda premapovania vhodnosti
Φmap = Φmap_identity  
#Φmap = Φmap_lin
#Φmap = Φmap_exp
#Φmap = Φmap_qtur
#Φmap = Φmap_orez

populacia = Φmap(jedince)
In [4]:
# Pravdepodobnosť selekcie pri proporcionálnej selekcii

Φsum = reduce(lambda x, y: x + y[1], populacia, 0)
ps = [(i,Φi / Φsum) for (i, Φi) in populacia]
In [5]:
# Teoretická strata materiálu

def strata_opakovany_vyber(x):
    return pow(1-x,μ)

def strata_jednorazovy_vyber(x):
    return max(1-x*μ,0)
In [6]:
# Selekčná metóda - vyberá sa toľko rodičov, koľko je jedincov v populácii

def vyber_rodica_SSwR(ps, jedince):       # SSwR vzorkovanie - nepresne (maximalne rozpatie)
    jazycek = μ * random.random()

    index = 0
    sum_η = ps[index][1] * μ
    while(sum_η < jazycek):
        index += 1
        sum_η += ps[index][1] * μ

    return jedince[index]

def vyber_rodica_RSSwoR(ps, jedince):       # RSSwoR vzorkovanie - TBD
    neimplementovane

def vyber_rodica_qturnaj(ps, jedince):      # q-turnaj vzorkovanie - TBD
    neimplementovane

def vyber_rodica_orezanie(ps, jedince):     # Orezávacie vzorkovanie - TBD
    neimplementovane

def selekcia_opakovana(jedince):    # opakovaná ruleta, turnaj, orezanie
    rodicia = []
    for _ in range(μ):
        rodicia.append(vyber_rodica_SSwR(ps, jedince))
        #rodicia.append(vyber_rodica_RSSwoR(ps, jedince))
        #rodicia.append(vyber_rodica_qturnaj(ps, jedince))
        #rodicia.append(vyber_rodica_orezanie(ps, jedince))
    return rodicia

def selekcia_jednorazova(jedince):  # SUS ruleta - TBD
    neimplementovane
    
def selekcia(jedince):
    rodicia = selekcia_opakovana(populacia)
    #rodicia = selekcia_jednorazova(populacia)
    return rodicia
In [7]:
# Experiment - opakované selekcie

OPAKOVANIA = 1000

vyber_poc = [0] * μ  # kumulovanie počty vyberov jedincov

for _ in range(OPAKOVANIA):
    vybery = [0] * μ
    for rodic in selekcia(populacia):
        vybery[rodic[0]] += 1
        
    for jedinec, vyber in enumerate(vybery):
        vyber_poc[jedinec] += vyber
In [8]:
# Strata materiálu po jedincoch

## teoretická strata jedinca
strata_ocak = [ps for (_,ps) in sorted(ps, key=lambda x: x[1])]

strata_ocak = list(map(strata_opakovany_vyber,strata_ocak))     # vybrat podľa použitého vzorkovania
#strata_ocak = list(map(strata_jednorazovy_vyber,strata_ocak))  # vybrat podľa použitého vzorkovania

# skutocná strata materiálu
strata_skut = [vyber_poc[i] / (OPAKOVANIA * μ) for (i,_) in sorted(ps, key=lambda x: x[1])]

strata_skut = list(map(strata_opakovany_vyber,strata_skut))     # vybrat podľa použitého vzorkovania
#strata_skut = list(map(strata_jednorazovy_vyber,strata_skut))  # vybrat podľa použitého vzorkovania

plt.suptitle("Očakávaná a realizovaná strata materiálu")
plt.xlabel("jedince")
plt.ylabel("pravdepodobnosť nevýberu")
plt.ylim([0.05,1.05])
plt.plot(strata_ocak,"b-", label="očakávaná")
plt.plot(strata_skut,"r-", label="realizovaná")
plt.legend(loc="upper right")

plt.show()
In [9]:
# Strata materiálu celkovo

ocak = reduce(add, strata_ocak) / μ
skut = reduce(add, strata_skut) / μ

print(
    f"Celková strata materiálu"
    f"\n    teoretická  : {ocak}"
    f"\n    realizovaná : {skut}"
)
Celková strata materiálu
    teoretická  : 0.4318215869667549
    realizovaná : 0.43190069842783657