Simpy - Resource 2

Wikikirjastosta

Kappale 4 – Resurssista kilpailevat prosessit[muokkaa | muokkaa wikitekstiä]

(Resource)

Tehtävä

Tee ohjelma, joka simuloi pankkikonttorin toimintaan. Konttorissa on yksi palvelupiste, joka palvelee satunnaisesti (5-10 minuutin välein) tulevia asiakkaita. Jokaisella asiakkaalla on eri mittainen ’pinna’ (3-11 minuttiia) , eli kuinka kauan tämä jaksaa odottaa palvelua. Jos asiakas ei saa palvelua haluamassa ajassa, niin hän poistuu pankista. Asiakkaan palvelu kestää satunnaisesti 8-12 minuuttia.

Elävässä elämässä käy joskus niin, että jonkin odottaminen kestää vain liian pitkään, emmekä jaksa odottaa vuoroamme. Olisiko pankissa jonottaminen vaikka sellainen, kun paikalla on vain yksi pankkivirkailija ja asiakkaita odottamassa riittävästi?

Simpyssä tällainen tilanne tarkoittaa, että jokin resurssi on niin pitkään varattuna toiselle prosessille, että odottava prosessi ei jää tietyn ajan jälkeen enää odottamaan sitä. Kuinkas tämä hoidetaan? Käytetään tuota pankkivirkailijaa esimerkkinä.

Tutut aloitukset:

import simpy
import random

Luodaan aluksi prosessi, joka generoi asiakkaita eli asiakkaiden palvelupyyntöjä. Tämä on jo tuttua meille. Tuodaan prosessiin parametreina tietysti env-ympäristö sekä sitten pankkivirkailija, joka myöhemmin kuvataan tietysi resurssina (Resource).

Annetaan satunnaisin aikavälein saapuville asiakkaille pitkämielisyysaika, eli se aika, jonka asiakas jaksaa odottaa palvelua. Otetaan talteen myös asiakkaan saapumisaika, jotta voidaan myöhemmin laskea, kuinka kauan hän on odottanut. Sitten vain luodaan jokaiselle asiakkaalle oma palvelupyyntö – prosessi ja, koska jokainen asiakas toimii itsenäisesti, luominen tapahtuu env.process() ’illa (ei siis yield’iä)

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

Palvelu-prosessissa pankkivirkailija yrittää parhaansa mukaan palvella asiakasta (palveluhan on taas vain ajankulua). Palvelua pyydetään tietysti varaamalla pankkivirkailija-resurssi

with pankkivirkailija.request() as nimi 

– menetelmällä, mutta koska palvelun saamiseen liittyy nyt rinnakkainen tapahtuma eli odottaminen (ja sen seuraukset), meidän tulee saada tämä kytkettyä jollain tavalla pyyntöön. Se tapahtuu niin ,että palveluvaatimus yield nimi – osoitetaan muuttujalle ja pitkämielisyyden odottaminen toisena vaihtoehtona | env.timeout(aika). Esimerkimme tapauksessa siis:

with pankkivirkailija.request() as palvelu:
onnistuu = yield palvelu | env.timeout(pitkamielisyys)

(Tuota | -merkkiä kutsutaan joskus ’putkeksi’, ja sen löytäminen näppäimistöstä saattaa olla hankaa. Se löytyy yleensä AltGr – merkin ja jonkin toisen merkin yhteispainalluksella)

Nyt voimme testata kumpiko noista vaihtoehdoista toteutui käyttämällä onnistuu – muutujaa Pythonin lauserakenteella: if palvelu in onnistuu:

Jos pankkivirkailija vapautuu pitkämielisyys ajan kuluessa, asiakas saa palvelua, muussa tapauksessa (else: -vaihtoehto), asiakas tekee omat johtopäätöksensä. Palvelu-prosessin koodi voisi siis olla seuraava:

def palvelu(env, pankkivirkailija,i, saapumisaika, pitkamielisyys):
   with pankkivirkailija.request() as palvelu:
       onnistuu = yield palvelu | env.timeout(pitkamielisyys)
       if  palvelu in onnistuu:
           palveluaika = random.randint(8,12)
           print('Asiakas', i,' sai palvelua. Palveluaika:', palveluaika)
           yield env.timeout(palveluaika)
       else:
           odotusaika = env.now-saapumisaika 
           print('Asiakas',i,' kyllästyi odottamaan. Odotusaika oli:', odotusaika)

Loppukoodi on sitten tavanomaista.

env = simpy.Environment()
pankkivirkailija = simpy.Resource(env,capacity=1)
env.process(palvelupyynto(env, pankkivirkailija))
env.run(until=100)

Koko koodi on sitten tässä:

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)
       print('Uusi asiakas',i,'saapuu pankkiin',env.now,'jakssa odottaa',pitkamielisyys)
       saapumisaika = env.now
       env.process(palvelu(env, pankkivirkailija,i, saapumisaika, pitkamielisyys))
       i=i+1
def palvelu(env, pankkivirkailija,i, saapumisaika, pitkamielisyys):
   with pankkivirkailija.request() as palvelu:
       onnistuu = yield palvelu | env.timeout(pitkamielisyys)
       if  palvelu in onnistuu:
           palveluaika = random.randint(8,12)
           print('Asiakas', i,' sai palvelua. Palveluaika:', palveluaika)
           yield env.timeout(palveluaika)
       else:
           odotusaika = env.now-saapumisaika
           print('Asiakas',i,' kyllästyi odottamaan. Odotusaika oli:', odotusaika)
env = simpy.Environment()
pankkivirkailija = simpy.Resource(env,capacity=1)
env.process(palvelupyynto(env, pankkivirkailija))
env.run(until=100)

Ja tuloksena syntyy seuraavaa:

Type "copyright", "credits" or "license()" for more information.
>>> 
===== RESTART: C:\Users\jussi\Documents\Similointi\pankkiviirkailija.py =====
Uusi asiakas 0 saapuu pankkiin ajassa 9 jaksaa odottaa 5
Asiakas 0  sai palvelua. Palveluaika: 11
Uusi asiakas 1 saapuu pankkiin ajassa 18 jaksaa odottaa 5
Asiakas 1  sai palvelua. Palveluaika: 12
Uusi asiakas 2 saapuu pankkiin ajassa 26 jaksaa odottaa 3
Asiakas 2  kyllästyi odottamaan. Odotusaika oli: 3
Uusi asiakas 3 saapuu pankkiin ajassa 35 jaksaa odottaa 3
Asiakas 3  sai palvelua. Palveluaika: 11
Uusi asiakas 4 saapuu pankkiin ajassa 43 jaksaa odottaa 9
Asiakas 4  sai palvelua. Palveluaika: 8
Uusi asiakas 5 saapuu pankkiin ajassa 48 jaksaa odottaa 9
Asiakas 5  sai palvelua. Palveluaika: 10
Uusi asiakas 6 saapuu pankkiin ajassa 55 jaksaa odottaa 9
Uusi asiakas 7 saapuu pankkiin ajassa 61 jaksaa odottaa 8
Asiakas 6  kyllästyi odottamaan. Odotusaika oli: 9
Asiakas 7  sai palvelua. Palveluaika: 10
Uusi asiakas 8 saapuu pankkiin ajassa 66 jaksaa odottaa 4
Asiakas 8  kyllästyi odottamaan. Odotusaika oli: 4
Uusi asiakas 9 saapuu pankkiin ajassa 76 jaksaa odottaa 11
Asiakas 9  sai palvelua. Palveluaika: 12
Uusi asiakas 10 saapuu pankkiin ajassa 83 jaksaa odottaa 3
Asiakas 10  kyllästyi odottamaan. Odotusaika oli: 3
Uusi asiakas 11 saapuu pankkiin ajassa 91 jaksaa odottaa 9
Asiakas 11  sai palvelua. Palveluaika: 8
>>>