Simpy - Harjoitustehtävä 2
Simpy - Harjoitustehtävä 2: Satama
[muokkaa | muokkaa wikitekstiä]Tämä on hyvin klassinen simulointitehtävä. Kuvitellaan satama, jossa on kolmenlaisia laiturpaikkoja ja johon saapuu siten myös kolmentyyppisä aluksia, joilla on eri kantavuus. A-tyypin laituri voi ottaa vastaan kaikkia laivatyyppejä A,B ja C. B-tyypin laituriin voi tulla vain B-tyypin laivoja. C-laituriin voi tulla C-tyypin laivoja sekä B-tyypin laivoja, joiden kantavuus on korkeintaan 5000 tonnia.
Satamassa on yksi A-tyypin laituri, kaksi B-tyypin laituria ja 3 C-tyypin laituria. Laivoista 3/11 osaa on A-tyypin laivoja ja B- ja C-tyypin laivoja kumpiakin 4/11 osaa. A-laivatyypin kantavuus vaihtelee 2000-12000 tonnin välillä, B-laivatyypin 2000-80000 välillä ja C-laivatyypin 2000-5000 tonnin välillä. Purettavaa ja lastattavaa tavaraa on kussakin laivassa satunnaisesti kantavuuden rajoissa.
Jokaisella laiturityypillä on oma lastaus- ja purkunopeus:
Laiturityyppi | Purkunopeus tn/min | Lastausnoperus tn/min |
---|---|---|
A | 200 | 200 |
B | 100 | 75 |
C | 75 | 60 |
Satama avautuu kello 08:00 ja viimeinen laiva otetaan sisään viimeistään kello 20:00, jonka jälkeen satamasta vain lähtee laivoja. Jokainen saapuva laiva purkaa ja lastaa tavaraa oman kantavuuden rajoissa satunnaisia määriä. Laivoja saapuu satunnaisesti 10-30 minuutin väliajoin.
Satamatoimintoja ohjataan niin, että ensisijaisesti alus ohjataan oman tyyppinsä mukaiseen laituriin. Mikäli vapaata oman tyypin laituria ei ole saatavissa 5 minuutin kuluessa, voidaan kysyä vapaata paikkaa A-laiturista (B-ja C- tyypin alukset). Jos sitäkään ei löydy, jäädään kiltisti odottamaan oman tyypin laituripaikan vapautumista. Poikkeuksen tekee B-tyypin laiva, jonka kantavuus on alle 5000 tonnia: se voi A-tyypin laiturin lisäksi päästä myös vapaaseen C-laituriin.
Tee ohjelma, joka simuloi sataman toimintaa yhden työpäivän ajan, tulostaa satamatapahtumia, laskee eri laivatyyppien määrän, koko sataman puretun ja lastatun tavaran kokonaismäärän, sekä laivojen keskikmääräisen satamassaoloajan sekä keskimääräisen laituripaikan odotusajan.
Esimerkkiratkaisu
Tässä tehtävässä ei ole paljonkaan uutta oppia Simpystä, mutta se on hyvä esimerkki millaisia sovelluksia simuloinnilla voidaan toteuttaa.
Aloitamme laivasta. Jokainen saapuva laiva on ilmiselvä olio, joka luodaan sen saapuessa satamaan. Sillä on tunnetut piirteet: tunnistetieto, typppi, kantavuus (B-tyypin aluksilla merkittävä), purettavan ja lastattavan lastin määrä, saapumisaika, satamassa oloaika ja odostuaika. Näille tiedoille tarvitaan metodit niiden lukemiseksi ja osalle myös niiden asettamiseksi olion tultua luoduksi. Luokkamäärittely voisi olla siten seuraava:
class Laiva: def __init__(self, tunnus, kantavuus, tyyppi, purettavaa, lastattavaa, aika): self.__tunnus = tunnus self.__kantavuus = kantavuus self.__tyyppi = tyyppi self.__purettavaa = purettavaa self.__lastattavaa = lastattavaa self.__aika=aika #Luontiaika = saapumisaika satamaan self.__odotusaika = 0 self.__satama_aika = 0 #Satamassa käytetty koknaisaika def get_tunnus(self): return self.__tunnus def get_kantavuus(self): return self.__kantavuus def get_tyyppi(self): return self.__tyyppi def get_purettavaa(self): return self.__purettavaa def get_lastattavaa(self): return self.__lastattavaa def get_aika(self): return self.__aika def get_satama_aika(self): return self.__satama_aika def get_odotus(self): return self.__odotusaika def set_odotus(self, odotusaika): self.__odotusaika = odotusaika def set_satama_aika(self,satama_aika): self.__satama_aika = satama_aika
Vastaavasti voidaan todeta, että laituri on luokka, jossa on resursseja (Resource) laivojen varattavaksi (kts Tehtävä 2). Tarvitsemme kolmetyyppisiä laitureita erinäisen määrän. Laiturin luokkamääritys voisi siten olla:
class Laituri: def __init__(self,env, tyyppi, paikkoja): self.env = env self.tyyppi = tyyppi self.paikkoja = simpy.Resource(env, paikkoja)
Aikanaan pääohjelmassa luomme sitten nuo tehtäväasetannan mukaiset laiturit seuraavasti:
laituriA = Laituri(env, 'A', 1) laituriB = Laituri(env, 'B', 2) laituriC = Laituri(env, 'C', 3)
Laivojen generointi noudattaa jo oppimaamme käytäntöä. Tarvitsemme siis prosessin, joka generoi laivoja kaikille satamaan tuleviksi.
Laivatyyppejä A,B, ja C pitää generoida suhteessa 3/11,4/11 ja 4/11. Se käy kätevästi Pythonin random.choice([lista]] – funktiolla, joka valitsee satunnaisesti jonkun listan alkiosta. Tyyppien suhde menee oikein, kun listassa on oikea määrä kutakin typpiä:
tyyppi = random.choice(['A','A','A','B','B','B','B','B','C','C','C','C'])
Laivojen kantavuudella ei ole merkityistä muille kuin B-tyypin aluksille, koska alle 5000 tonnin B-tyypin alus voi käyttää myös C-tyypin laituria. Laivojen purettavan ja lastattavan lastin määrän voi generoida tasatonnein helposti random.randint – funktiolla. B-tyypin laivoilla lastin määrää ’arvottaessa’ pitää muistaa, ettei laivan kantavuutta kuitenkaan ylitetä.
Kun kaikki laivan perustiedot on ’arvoittu’ voidaan laiva-olio luoda:
laiva = Laiva(tunnus, kantavuus, tyyppi, purettavaa, lastattavaa, aika)
Sitten ei jääkään muuta tehtävää kuin generoida prosessi, jossa luotu laiva alkaa pyytämään laituripaikkaa
env.process(laituripyynto(env, laiva, laituriA, laituriB, laituriC))
ja sen jälkeen jäädä odottamaan sopiva ajanjakso ennen uuden laivan luomista. Vielä meidän tulee ottaa huomioon, että laivoja otetaan vastaan vain klo 20:00 saakka (= simpyaikana 1200)
def GenLaivoja(env,laituriA, laituriB, laituriC): tunnus = 0 while True: if env.time <= 1200: kantavuus = 0 aika=env.now tyyppi = random.choice(['A','A','A','B','B','B','B','B','C','C','C','C']) if tyyppi == 'A': purettavaa = 1000*random.randint(8,12) lastattavaa = 1000*random.randint(8,12) if tyyppi == 'B': kantavuus=random.randint(2,8) #B-tyypin aluksille pitää määrittää kantavuus purettavaa = 1000*random.randint(2,kantavuus) lastattavaa = 1000*random.randint(2,kantavuus) kantavuus=1000*kantavuus if tyyppi == 'C': purettavaa = 1000*random.randint(2,5) lastattavaa = 1000*random.randint(2,5) laiva = Laiva(tunnus, kantavuus, tyyppi, purettavaa, lastattavaa, aika) print(kello(env),'Laiva', tunnus, ',tyyppi;',tyyppi, ',kantavuus:', kantavuus, ',purettavaa:', purettavaa,' lastettavaa:', lastattavaa, 'saapuu') env.process(laituripyynto(env, laiva, laituriA, laituriB, laituriC)) yield env.timeout(random.randint(10,30)) tunnus=tunnus+1 else: '# Kello 20:00 laivojen vastaanotto lopetaan break
Laituripaikan pyyntöprosessissa joudumme käyttämään tehtävässä 4 käytettyä rinnakkaisten prosessien ’kilpailua’ sekä tarkastamaan resurssin jonotustilannetta. Jokaiselle laivatyypille joudumme tekemään oman päättelyprosessin tehtävänannon mukaisesti.
A-tyypin laivoille laituripaikan pyyntön on varsin yksinkertainen, koska se voi rantautua vai A-tyypin laituriin. Niinpä alku on helppo: laituripaikkaa pyydetään laituriA – oliolta jo tutulla tavalla:
with laituriA.paikkoja.request() as pyynto: yield pyynto
Kun laituripaikka joskus saadaan, voidaan aloittaa laituritoiminnotA – prosessi, joka purkaa ja lastaa laivan A-laiturille määritetyin nopeuksin (tonnia/min). Huom! Laituritoiminnot-prosessia pitää kutsua yield’illä, jotta se varmasti toteutuu, ennenkuin laiva pääsee lähtemään satamasta.
yield env.process(laituritoiminnotA(env, laiva))
def laituripyynto(env, laiva, laituriA, laituriB, laituriC): Apaikkoja=1 Bpaikkoja=2 Cpaikkoja=3 tyyppi = laiva.get_tyyppi() if tyyppi == 'A': with laituriA.paikkoja.request() as pyynto: yield pyynto print(kello(env),'Laiva', laiva.get_tunnus(),'pääsi A-laituriin') yield env.process(laituritoiminnotA(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta')
Tyypin C-laivoilla on seuraavaksi helpoin laituripyyntö: Mikäli jossakin kolmesta C-tyypin laituripaikassa on tilaa, mennään sinne jos 5 minuutin sisään päästään.
with laituriC.paikkoja.request() as pyynto tulos = yield pyynto | env.timeout(5)
Jos kaikki C-laiturit ovat varattuja, katsotaan, onko A-laiturissa tilaa ja mennään sinne. Muuten jäädä kiltisti odottamaan C-laituripaikan vapautumista.
Itse koodi on aika selvää, mutta kuinka tarkastetaan A-laiturin vapaana oleminen? Sen voi tehdä kysymällä kuinka pitkä A-laiturin jono on, metodilla:
jonoA = len(laituriA.paikkoja.queue)
Sittenpä voimmekin koodata C-tyypin pyyntötoiminnot:
if tyyppi == 'C': with laituriC.paikkoja.request() as pyynto: tulos = yield pyynto | env.timeout(5) if pyynto in tulos: print(kello(env),'Laiva', laiva.get_tunnus(),'pääsi C-laituriin') yield env.process(laituritoiminnotC(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta') else: print(kello(env),'C laituripaikkoja ei vapaana laivalle', laiva.get_tunnus()) jonoA = len(laituriA.paikkoja.queue) if jonoA < Apaikkoja: with laituriA.paikkoja.request() as pyynto: yield pyynto print(kello(env),'Laiva', laiva.get_tunnus(),'pääsi A-laituriin') yield env.process(laituritoiminnotA(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta') else: print(kello(env),'C Laivalle', laiva.get_tunnus(),' ei A-laituriakaan vapaanana. Jää odottamaan C-laituira') with laituriC.paikkoja.request() as pyynto: yield pyynto print(kello(env),'Laiva', laiva.get_tunnus(),'pääsi C-laituriin') yield env.process(laituritoiminnotC(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta')
B-tyypin laivojen laituroinnin joudumme jakamaan kahteen osaan, koska alle 5000 tonnin kantavan aluksilla on lisämahdollisuus käyttää C-laitureita.
B-tyypin yli 5000 tonnin kanatavuuden laivojen ohjelma on käytännössä sama kuin C-tyypin, kunhan vain ’C vaihdetaan B’ksi’.
if tyyppi == 'B' and laiva.get_kantavuus() > 5000: with laituriB.paikkoja.request() as pyynto: tulos = yield pyynto | env.timeout(5) if pyynto in tulos: print(kello(env),'Laiva', laiva.get_tunnus(),'pääsi B-laituriin') yield env.process(laituritoiminnotB(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta') else: print(kello(env), 'B laituripaikkoja ei vapaana laivalle', laiva.get_tunnus()) jonoA = len(laituriA.paikkoja.queue) if jonoA < Apaikkoja: with laituriA.paikkoja.request() as pyynto: yield pyynto print(kello(env),'Laiva', laiva.get_tunnus(),'pääsi A-laituriin') yield env.process(laituritoiminnotA(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta') else: print(kello(env),'B Laivalle', laiva.get_tunnus(),' ei A-laituriakaan vapaanana. Jää odottamaan B-laituira') with laituriC.paikkoja.request() as pyynto: yield pyynto print(kello(env),'Laiva', laiva.get_tunnus(),'pääsi C-laituriin') yield env.process(laituritoiminnotB(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta')
Pienenpien B-tyypin laivoille, pitää koodata lisätarkastus C-laiturien osalta. Se on vastaavanlainen kuin tarkastus A-laiturin käyttömahdollisuudesta.
if tyyppi == 'B'and laiva.get_kantavuus() <= 5000: with laituriB.paikkoja.request() as pyynto: tulos = yield pyynto | env.timeout(5) if pyynto in tulos: print(kello(env),'Laiva', laiva.get_tunnus(),'pääsi B-laituriin') yield env.process(laituritoiminnotB(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta') else: print(kello(env),'B laituripaikkoja ei vapaana laivalle', laiva.get_tunnus()) jonoA = len(laituriA.paikkoja.queue) if jonoA < Apaikkoja: with laituriA.paikkoja.request() as pyynto: yield pyynto print(kello(env),'Laiva', laiva.get_tunnus(),'pääsi A-laituriin') yield env.process(laituritoiminnotA(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta') jonoC = len(laituriC.paikkoja.queue) if jonoC < Cpaikkoja: with laituriC.paikkoja.request() as pyynto: yield pyynto print(kello(env),'Laiva', laiva.get_tunnus(), 'pääsi C-laituriin') yield env.process(laituritoiminnotC(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta') else: print(kello(env),'B Laivalle', laiva.get_tunnus(),' ei A/C-laituriakaan vapaanana. Jää odottamaan B-laituira') with laituriC.paikkoja.request() as pyynto: yield pyynto print(kello(env),'Laiva', laiva.get_tunnus(),'pääsi B-laituriin') yield env.process(laituritoiminnotB(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta')
Lopuksi meille ei jääkään muuta, kuin pitää huoli, että laivan tiedot tulee talteen otetuksi johonkin listamuuttujaan.
tiedot.append(laiva)
Muista määritellä listamuuttuja jossain välissä:
tiedot = []
Mutta ei olla vielä valmiita, sillä laituripaikkapyynto – prosessissa kutsumme laivojen lastin purkavia ja lastaavia prosesseja laituritoiminnoiksi. Laivan purku- ja lastaus on samanlaista kaikille laivoille, joten ohjelman voi koodata niin, että jokaiselle laiturityypille on oma prosessi tai sitten yksi ja sama prosessi hoitaa kaikkia laiturityyppejä ottaen huomioon kunkin laiturityypin eri nopeudet.
Tässä on malli ’yksilöllisestä’ laituriprosessista:
def laituritoiminnotA(env, laiva): odotusaika = env.now - laiva.get_aika() '#Laituripaikan odotusaika laiva.set_odotus(odotusaika) purkunopeus = 200 '#Laiturikohtaiset purku ja lastausnopeudet lastausnopeus = 200 purettavaa = laiva.get_purettavaa() lastattavaa = laiva.get_lastattavaa() purkuaika = round(purettavaa/purkunopeus,0) #Pyöristetään minuuteiksi lastausaika = round(lastattavaa/lastausnopeus,0) laituriaika = lastausaika + purkuaika '#Tämän ajan laiv'a vietää alaiturissa yield env.timeout(laituriaika) '#Ja sitten se aika vietetään satama_aika = odotusaika+laituriaika laiva.set_satama_aika(satama_aika) '#Pistetään satama-aika talteen print(kello(env),'Laiva', laiva.get_tunnus(),'odotusaika:',kello2(laiva.get_odotus()),'satama-aika', kello2(laiva.get_satama_aika()))
Vastaava prosessi pitää sitten koodata (copy/paste) B- ja C-laitureille niiden omilla purku- ja lastausnopeuksilla.
Kun laituritoiminnot on saatu koodattua, jää enää jäljellä pääohjelman ja tilastotietojen koodaaminen. Pääohjelmassa hyödynämme taas kelloajan asetusta Environment(init) – määrittelyssä (480 = klo 08:00 minuutteina)
env = simpy.Environment(480) laituriA = Laituri(env, 'A', 1) laituriB = Laituri(env, 'B', 2) laituriC = Laituri(env, 'C',3) env.process(GenLaivoja(env, laituriA, laituriB, laituriC)) env.run(until=1620) '# Aika 1800 = klo 06:00 johon mennessä laivat ovat poistuneet satamasta toivottavasti
Tilastotietojen käsittelyssä tarvitaan joukko summamuuttajia lastimäärien, odotusaikojen ja eri laivamäärien laskentaan.
purettavat = 0 lastattavat = 0 odotusajat=0 satama_aika=0 A_tyyppi=0 B_tyyppi=0 C_tyyppi=0
Sitten voidaankin käydä lista-muuttujan kimppuun ja ynnätä kunkin laivan tiedoista tarvittavat elementit summamuuttujiin ja lopuksi laskea ja tulostaa pyydetyt summan ja keskiarvot.
for i in range (0,len(tiedot)): laiva = tiedot[i] if laiva.get_tyyppi() =='A': A_tyyppi +=1 if laiva.get_tyyppi() =='B': B_tyyppi +=1 if laiva.get_tyyppi() =='C': C_tyyppi +=1 purettavat = purettavat + laiva.get_purettavaa() lastattavat = lastattavat + laiva.get_lastattavaa() odotusajat = odotusajat + laiva.get_odotus() satama_aika=satama_aika + laiva.get_satama_aika() summa = A_tyyppi+B_tyyppi+C_tyyppi print('Päivän tilasto:') print('Satamassa kävi A-tyypin laivoja', A_tyyppi, 'B-tyypin', B_tyyppi, 'ja C-tyypin',C_tyyppi,'kappaletta') print('Purettua lasti:', purettavat, 'ja lastattua:',lastattavat) print('Keskimääräinen satama-aika:', int(satama_aika/summa),'josta odotusaikaa:', int(odotusajat/summa))
Lopuksi vielä koko koodi yhtenä kokonaisuutena.
import simpy import random tiedot = [] class Laiva: def __init__(self, tunnus, kantavuus, tyyppi, purettavaa, lastattavaa, aika): self.__tunnus = tunnus self.__kantavuus = kantavuus self.__tyyppi = tyyppi self.__purettavaa = purettavaa self.__lastattavaa = lastattavaa self.__aika=aika self.__odotusaika = 0 self.__satama_aika = 0 def get_tunnus(self): return self.__tunnus def get_kantavuus(self): return self.__kantavuus def get_tyyppi(self): return self.__tyyppi def get_purettavaa(self): return self.__purettavaa def get_lastattavaa(self): return self.__lastattavaa def get_aika(self): return self.__aika def get_satama_aika(self): return self.__satama_aika def get_odotus(self): return self.__odotusaika def set_odotus(self, odotusaika): self.__odotusaika = odotusaika def set_satama_aika(self,satama_aika): self.__satama_aika = satama_aika lass Laituri: def __init__(self,env, tyyppi, paikkoja): self.env = env self.tyyppi = tyyppi self.paikkoja = simpy.Resource(env, paikkoja) def kello(env): aika = env.now tunnit = int(aika/60) minuutit = int(aika - tunnit*60) if tunnit >= 24: tunnit = tunnit - 24 if tunnit < 10: stunnit='0'+str(tunnit) else: stunnit = str(tunnit) if minuutit < 10: sminuutit = '0'+str(minuutit) else: sminuutit = str(minuutit) staika = stunnit+":"+sminuutit return staika def kello2(aika): tunnit = int(aika/60) minuutit = int(aika-tunnit*60) if tunnit >= 24: tunnit = tunnit - 24 if minuutit < 10: smin = '0'+str(minuutit) else: smin = str(minuutit) saika = str(tunnit)+':'+ smin return saika '# A-tyypin laituri ottaa kaikki laivoja '# B-tyypin laituri vain B tyypin laivoja '# C-tyypin laituri C-tyypin ja B-typin, kantavuus < 5000 def laituripyynto(env, laiva, laituriA, laituriB, laituriC): Apaikkoja=1 Bpaikkoja=2 Cpaikkoja=3 tyyppi = laiva.get_tyyppi() if tyyppi == 'A': with laituriA.paikkoja.request() as pyynto: yield pyynto print(kello(env),'Laiva', laiva.get_tunnus(),'pääsi A-laituriin') yield env.process(laituritoiminnotA(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta') if tyyppi == 'C': with laituriC.paikkoja.request() as pyynto: tulos = yield pyynto | env.timeout(5) if pyynto in tulos: print(kello(env),'Laiva', laiva.get_tunnus(),'pääsi C-laituriin') yield env.process(laituritoiminnotC(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta') else: print(kello(env),'C laituripaikkoja ei vapaana laivalle', laiva.get_tunnus()) jonoA = len(laituriA.paikkoja.queue) if jonoA < Apaikkoja: with laituriA.paikkoja.request() as pyynto: yield pyynto print(kello(env),'Laiva', laiva.get_tunnus(),'pääsi A-laituriin') yield env.process(laituritoiminnotA(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta') else: print(kello(env),'C Laivalle', laiva.get_tunnus(),' ei A-laituriakaan vapaanana. Jää odottamaan C-laituira') with laituriC.paikkoja.request() as pyynto: yield pyynto print(kello(env),'Laiva', laiva.get_tunnus(),'pääsi C-laituriin') yield env.process(laituritoiminnotC(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta') if tyyppi == 'B' and laiva.get_kantavuus() > 5000: with laituriB.paikkoja.request() as pyynto: tulos = yield pyynto | env.timeout(5) if pyynto in tulos: print(kello(env),'Laiva', laiva.get_tunnus(),'pääsi B-laituriin') yield env.process(laituritoiminnotB(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta') else: print(kello(env), 'B laituripaikkoja ei vapaana laivalle', laiva.get_tunnus()) jonoA = len(laituriA.paikkoja.queue) if jonoA < Apaikkoja: with laituriA.paikkoja.request() as pyynto: yield pyynto print(kello(env),'Laiva', laiva.get_tunnus(),'pääsi A-laituriin') yield env.process(laituritoiminnotA(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta') else: print(kello(env),'B Laivalle', laiva.get_tunnus(),' ei A-laituriakaan vapaanana. Jää odottamaan B-laituira') with laituriC.paikkoja.request() as pyynto: yield pyynto print(kello(env),'Laiva', laiva.get_tunnus(),'pääsi C-laituriin') yield env.process(laituritoiminnotB(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta') if tyyppi == 'B'and laiva.get_kantavuus() <= 5000: with laituriB.paikkoja.request() as pyynto: tulos = yield pyynto | env.timeout(5) if pyynto in tulos: print(kello(env),'Laiva', laiva.get_tunnus(),'pääsi B-laituriin') yield env.process(laituritoiminnotB(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta') else: print(kello(env),'B laituripaikkoja ei vapaana laivalle', laiva.get_tunnus()) jonoA = len(laituriA.paikkoja.queue) if jonoA < Apaikkoja: with laituriA.paikkoja.request() as pyynto: yield pyynto print(kello(env),'Laiva', laiva.get_tunnus(),'pääsi A-laituriin') yield env.process(laituritoiminnotA(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta') jonoC = len(laituriC.paikkoja.queue) if jonoC < Cpaikkoja: with laituriC.paikkoja.request() as pyynto: yield pyynto print(kello(env),'Laiva', laiva.get_tunnus(), 'pääsi C-laituriin') yield env.process(laituritoiminnotC(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta') else: print(kello(env),'B Laivalle', laiva.get_tunnus(),' ei A/C-laituriakaan vapaanana. Jää odottamaan B-laituira') with laituriC.paikkoja.request() as pyynto: yield pyynto print(kello(env),'Laiva', laiva.get_tunnus(),'pääsi B-laituriin') yield env.process(laituritoiminnotB(env, laiva)) print(kello(env),'Laiva',laiva.get_tunnus(),'lähti satamasta') tiedot.append(laiva) def laituritoiminnotA(env, laiva): odotusaika = env.now - laiva.get_aika() #print(laiva.get_aika()) laiva.set_odotus(odotusaika) purkunopeus = 200 lastausnopeus = 200 purettavaa = laiva.get_purettavaa() lastattavaa = laiva.get_lastattavaa() purkuaika = round(purettavaa/purkunopeus,0) lastausaika = round(lastattavaa/lastausnopeus,0) laituriaika = lastausaika + purkuaika yield env.timeout(laituriaika) satama_aika = odotusaika+laituriaika laiva.set_satama_aika(satama_aika) print(kello(env),'Laiva', laiva.get_tunnus(),'odotusaika:',kello2(laiva.get_odotus()),'satama-aika', kello2(laiva.get_satama_aika())) def laituritoiminnotB(env, laiva): odotusaika = env.now - laiva.get_aika() laiva.set_odotus(odotusaika) purkunopeus = 100 lastausnopeus = 75 purettavaa = laiva.get_purettavaa() lastattavaa = laiva.get_lastattavaa() purkuaika = round(purettavaa/purkunopeus,0) lastausaika = round(lastattavaa/lastausnopeus,0) laituriaika = lastausaika + purkuaika yield env.timeout(laituriaika) satama_aika = odotusaika+laituriaika laiva.set_satama_aika(satama_aika) print(kello(env), 'Laiva', laiva.get_tunnus(),'odotusaika:',kello2(laiva.get_odotus()),'satama-aika', kello2(laiva.get_satama_aika())) def laituritoiminnotC(env, laiva): odotusaika = env.now - laiva.get_aika() laiva.set_odotus(odotusaika) purkunopeus = 75 lastausnopeus = 60 purettavaa = laiva.get_purettavaa() lastattavaa = laiva.get_lastattavaa() purkuaika = round(purettavaa/purkunopeus,0) lastausaika = round(lastattavaa/lastausnopeus,0) laituriaika = lastausaika + purkuaika yield env.timeout(laituriaika) satama_aika = odotusaika+laituriaika laiva.set_satama_aika(satama_aika) print(kello(env),'Laiva', laiva.get_tunnus(),'odotusaika:',kello2(laiva.get_odotus()),'satama-aika', kello2(laiva.get_satama_aika())) def GenLaivoja(env,laituriA, laituriB, laituriC): tunnus = 0 while True: if env.now <= 1200: kantavuus = 0 aika=env.now tyyppi = random.choice(['A','A','A','B','B','B','B','B','C','C','C','C']) if tyyppi == 'A': purettavaa = 1000*random.randint(8,12) lastattavaa = 1000*random.randint(4,12) if tyyppi == 'B': kantavuus=random.randint(2,8) purettavaa = 1000*random.randint(2,kantavuus) lastattavaa = 1000*random.randint(2,kantavuus) kantavuus=1000*kantavuus if tyyppi == 'C': purettavaa = 1000*random.randint(2,5) lastattavaa = 1000*random.randint(2,5) laiva = Laiva(tunnus, kantavuus, tyyppi, purettavaa, lastattavaa, aika) print(kello(env),'Laiva', tunnus, ',tyyppi;',tyyppi, ',kantavuus:', kantavuus, ',purettavaa:', purettavaa, ',lastettavaa:', lastattavaa, 'saapuu') env.process(laituripyynto(env, laiva, laituriA, laituriB, laituriC)) yield env.timeout(random.randint(10,30)) tunnus=tunnus+1 else: break '#Pääohjelma env = simpy.Environment(480) laituriA = Laituri(env, 'A', 1) laituriB = Laituri(env, 'B', 2) laituriC = Laituri(env, 'C',3) env.process(GenLaivoja(env, laituriA, laituriB, laituriC)) env.run(until=1800) purettavat = 0 lastattavat = 0 odotusajat=0 satama_aika=0 A_tyyppi=0 B_tyyppi=0 C_tyyppi=0 for i in range (0,len(tiedot)): laiva = tiedot[i] if laiva.get_tyyppi() =='A': A_tyyppi +=1 if laiva.get_tyyppi() =='B': B_tyyppi +=1 if laiva.get_tyyppi() =='C': C_tyyppi +=1 purettavat = purettavat + laiva.get_purettavaa() lastattavat = lastattavat + laiva.get_lastattavaa() odotusajat = odotusajat + laiva.get_odotus() satama_aika=satama_aika + laiva.get_satama_aika() summa = A_tyyppi+B_tyyppi+C_tyyppi print('Päivän tilasto:') print('Satamassa kävi A-tyypin laivoja', A_tyyppi, 'B-tyypin', B_tyyppi, 'ja C-tyypin',C_tyyppi,'kappaletta') print('Purettua lasti:', purettavat, 'ja lastattua:',lastattavat) print('Keskimääräinen satama-aika:', int(satama_aika/summa),'josta odotusaikaa:', int(odotusajat/summa))