Simpy - Resource 2
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 >>>