Kappale 9: Lisää kilpailevista prosesseista

muokkaa

Kappaleessa 4 tutustuimme menetelmään, jossa kaksi prosessi ”kilpaili”, kumpi toteutuu: toinen oli resurssipyyntö pankkipalveluun, toinen oli asiakkaan pitkämielisyys eli env.timetout. Entäpä, jos meillä olisi vielä yksi vaihtoehtoinen ”kílpailija”, vaikka pysäköintiaika, joka saataisi loppua ennen palvelunsaantia tai pinnan palamista. Kuinka sellainen toteutetaan?

Tehtävä

Muuta kappaleen 4 tehtävään niin, että asiakkaan saataa joutua poistumaan pankista myös päättyvän parkkiajan vuoksi – eli palvelupyynnön voi keskeyttää jompikumpi kahdesta aikarajoitteesta: pitkämielisyyden loppuminen tai parkkiajan loppuminen. Sovitaan, että asiakkaalla on pankkiin tullessa 4-10 minuuttia parkkiaikaa jäljellä.

Alkuperäisessä ratkaisussa meillä oli palvelupyynto-prosessi, joka generoi palvelypyyntöjä pankkivirkailijaa kohtaan. Lisätään ohjelmakoodiin uusi parkkiaikaa kuvaava muuttuja, parkkiaika ja sille satunnaisesti arvo 4-10 minuutin väliltä ja välitetään se paramterina itse palvelu – prosessiin.

def palvelupyynto(env, pankkivirkailija):
   i=0
   while True:
       saapumisvali = random.randint(5,10)
       yield env.timeout(saapumisvali)
       pitkamielisyys = random.randint(3,11)
       parkkiaika = random.randint(4,10)
       print('Uusi asiakas',i,'saapuu pankkiin ajassa',env.now,'jaksaa odottaa',pitkamielisyys)
       saapumisaika = env.now
       env.process(palvelu(env, pankkivirkailija,i, saapumisaika, pitkamielisyys, parkkiaika))
       i=i+1

Palvelu-prosessissa joudumme sitten ohjelmoimaan menettelyn, jossa saamme resurssipyyntöön:

with pankkivirkailija.request() as palvelu:

liitettyä kaksi vaihtoehtoista ”aikakatkaisua”. Otamme käyttöön tutun env.timeout – ajankuluttajan hieman uudessa muodossa:

nimi = env.timetout(aika,value=”arvo”)

Kuten aikaisemissakin tehtävissä, voimme osoittaa Simpyn funktion jollekin muuttujalle, nimi. Lisäksi voimme antaa env.timeout’ille palautusarvon value=”arvo”, jonka funktio palauttaa, mikäli se suoritetaan.

Useampi vaihtoehtoinen toiminta saadaan toimimaan, kun rerussinpyynnön yield’issä kaikki vaihtoethoiset toiminnat yhdistetään | - toiminolla. Esimerkiksi:

def palvelu(env, pankkivirkailija,i, saapumisaika, pitkamielisyys, parkkiaika):
   p = env.timeout(pitkamielisyys,value="p")
   r = env.timeout(parkkiaika, value="r")
   with pankkivirkailija.request() as palvelu:
       onnistuu = yield palvelu | p | r

Yield palauttaa onnistuu – muuttujaan ns. ConditionValue’n, jonka muoto riippuu siitä, mikä vaihtoehto toteutui. Mikäli palvelu request() onnistui, stä voidaan testaata kuten alkuperäisessä tehtävässä (if palvelu in onnistuu). Sen sijaan jos jompikumpi env.timeout – vaihtoehtoista toteutuu, niin ConditionValue on yhden alkion mittainen Dictionary-muuttuja, jota voidaan testa if-lausella:

yield nimi == {timeout-muuttuja:”arvo”}
 

Pävitetyssä ohjelmakoodissamme tämä voisi tapahtua esimerkiksi seuraavasti:

if  palvelu in onnistuu:
    palveluaika = random.randint(8,12)
    print('Asiakas', i,' sai palvelua. Palveluaika:', palveluaika)
    yield env.timeout(palveluaika)
else:
    if onnistuu == {p:"p"}:
       odotusaika = env.now-saapumisaika
       print('Asiakas',i,' kyllästyi odottamaan. Odotusaika oli:', odotusaika)
     if onnistuu == {r:"r"}:
       odotusaika = env.now - saapumisaika
       print('Asiakkaan',i,'parkki-aika loppui, poistui pankista. Odotti turhaan', odotusaika)
      

Koodi kokonaisuudessaan on seuraava:

import simpy
import random
def palvelupyynto(env, pankkivirkailija):
   i=0
   while True:
       saapumisvali = random.randint(5,10)
       yield env.timeout(saapumisvali)
       pitkamielisyys = random.randint(3,11)
       parkkiaika = random.randint(4,10)
       print('Uusi asiakas',i,'saapuu pankkiin ajassa',env.now,'jaksaa odottaa',pitkamielisyys)
       saapumisaika = env.now
       env.process(palvelu(env, pankkivirkailija,i, saapumisaika, pitkamielisyys, parkkiaika))
       i=i+1
def palvelu(env, pankkivirkailija,i, saapumisaika, pitkamielisyys, parkkiaika):
   p = env.timeout(pitkamielisyys,value="p")
   r = env.timeout(parkkiaika, value="r")
   with pankkivirkailija.request() as palvelu:
       onnistuu = yield palvelu | p | r
       if  palvelu in onnistuu:
           palveluaika = random.randint(8,12)
           print('Asiakas', i,' sai palvelua. Palveluaika:', palveluaika)
           yield env.timeout(palveluaika)
       else:
           if onnistuu == {p:"p"}:
               odotusaika = env.now-saapumisaika
               print('Asiakas',i,' kyllästyi odottamaan. Odotusaika oli:', odotusaika)
           if onnistuu == {r:"r"}:
               odotusaika = env.now - saapumisaika
               print('Asiakkaan',i,'parkki-aika loppui, poistui pankista. Odotti turhaan', odotusaika)
env = simpy.Environment()
pankkivirkailija = simpy.Resource(env,capacity=1)
env.process(palvelupyynto(env, pankkivirkailija))
env.run(until=100)

Tulostus saataa sitten olla seuraavanlaista:

==== RESTART: C:\Users\Simulointi\pankkiviirkailija-2.py ====
Uusi asiakas 0 saapuu pankkiin ajassa 6 jaksaa odottaa 3
Asiakas 0  sai palvelua. Palveluaika: 8
Uusi asiakas 1 saapuu pankkiin ajassa 11 jaksaa odottaa 7
Asiakas 1  sai palvelua. Palveluaika: 8
Uusi asiakas 2 saapuu pankkiin ajassa 19 jaksaa odottaa 11
Asiakas 2  sai palvelua. Palveluaika: 10
Uusi asiakas 3 saapuu pankkiin ajassa 28 jaksaa odottaa 3
Asiakas 3  kyllästyi odottamaan. Odotusaika oli: 3
Uusi asiakas 4 saapuu pankkiin ajassa 35 jaksaa odottaa 5
Asiakas 4  sai palvelua. Palveluaika: 9
Uusi asiakas 5 saapuu pankkiin ajassa 42 jaksaa odottaa 6
Asiakas 5  sai palvelua. Palveluaika: 12
Uusi asiakas 6 saapuu pankkiin ajassa 48 jaksaa odottaa 9
Uusi asiakas 7 saapuu pankkiin ajassa 53 jaksaa odottaa 7
Asiakkaan 6 parkki-aika loppui, poistui pankista. Odotti turhaan 6
Asiakas 7  sai palvelua. Palveluaika: 11
Uusi asiakas 8 saapuu pankkiin ajassa 62 jaksaa odottaa 5
Asiakas 8  sai palvelua. Palveluaika: 9
Uusi asiakas 9 saapuu pankkiin ajassa 70 jaksaa odottaa 9
Asiakas 9  sai palvelua. Palveluaika: 12
Uusi asiakas 10 saapuu pankkiin ajassa 80 jaksaa odottaa 8
Asiakkaan 10 parkki-aika loppui, poistui pankista. Odotti turhaan 6
Uusi asiakas 11 saapuu pankkiin ajassa 87 jaksaa odottaa 3
Asiakas 11  sai palvelua. Palveluaika: 9
Uusi asiakas 12 saapuu pankkiin ajassa 93 jaksaa odottaa 10
Asiakas 12  sai palvelua. Palveluaika: 12
>>>