WOJSKOWA AKADEMIA TECHNICZNA
Im. Jarosława Dąbrowskiego w Warszawie
SPRAWOZDANIE
Projekt laboratoryjny
Z przedmiotu Podstawy Symulacji
Wykonał: Dariusz Feliga
Grupa szkoleniowa: I9M1S1
Prowadzący zajęcia: dr inż. Jarosław Rulka
Treść zadania laboratoryjnego:
Napisać program symulujący działanie sieci SMO jak na rysunku:
Przy realizacji zadania należy przyjąć następujące dane z listy przedstawionej poniżej:
rozkład zmiennych Tj: (nrDz + i) mod 6 + 1;
rozkład zmiennych Oi: (nrDz + i + 1) mod 6 + 1;
Li: (nrDz + i) mod 2 + 1;
ALi: (nrDz + i + 2) mod 3 + 1;
Rj = (nrDz + i + 5) mod 3 + 1;
Mi = (nrDz + i + 2) mod 4 + 1;
Blokowanie zgłoszeń 1. SMO;
Klienci niecierpliwi w SMOi : Ni = (nrDz + i) mod 4 (ograniczony czas oczekiwania na rozpoczęcie obsługi);
gdzie:
i – numer SMO;
j – numer strumienia;
Tj – zmienna losowa oznaczająca czas pomiędzy kolejnymi napływami zgłoszeń do systemu;
Oi – zmienna losowa oznaczająca czas obsługi pojedynczego zgłoszenia w gnieździe;
Ni – zmienna losowa oznaczająca czas niecierpliwości zgłoszenia (gdy i = 0 => zgłoszenia cierpliwe);
Rj – zmienna losowa oznaczająca wielkość paczki zgłoszeń (wchodzących w tej samej chwili) j-tego strumienia;
pk – prawdopodobieństwa przemieszczenia się zgłoszenia po danym łuku;
Li – długość kolejki i-tego SMO;
AL.i – algorytmy kolejek (w przypadku istnienia kolejki z priorytetami należy przyjąć, że zgłoszenia posiadają priorytety);
Rozkłady zmiennych losowych:
Wykładniczy
Erlanga
Normalny
Jednostajny
Trójkątny
Weibulla
Długości kolejek pojedynczych SMO
ograniczone (możliwe straty)
nieograniczone
Algorytm kolejek:
FIFO
LIFO
Z priorytetami
Liczba stanowisk obsługi w gniazdach (1-M)
Ilość zgłoszeń jednocześnie napływających do systemu (1-R)
Pozostałe dane należy określać na początku symulacji. Dane wejściowe i wyniki odczytywane/zapisywane z/do pliku.
Program powinien działać w trybie z i bez komunikatów ekranowych.
Otrzymane wartości danych dla nrDz = 2.
Tj – zmienna losowa oznaczająca czas pomiędzy kolejnymi napływami zgłoszeń do systemu;
T1 = 3mod6 + 1 = 4
Oi – zmienna losowa oznaczająca czas obsługi pojedynczego zgłoszenia w gnieździe;
O1 = 4mod6 + 1 = 5
O2 = 5mod6 + 1 = 6
O3 = 6mod6 + 1 = 1
Ni – zmienna losowa oznaczająca czas niecierpliwości zgłoszenia (gdy i = 0 => zgłoszenia cierpliwe);
N1 = 3mod4 = 3
N2 = 4mod4 = 0
N3 = 5mod4 = 1
Rj – zmienna losowa oznaczająca wielkość paczki zgłoszeń (wchodzących w tej samej chwili) j-tego strumienia;
R1 = 8mod3 + 1 = 3
Li – długość kolejki i-tego SMO;
L1 = 3mod2 + 1 = 2
L2 = 4mod2 + 1 = 1
L3 = 5mod2 + 1 = 2
Mi – liczba stanowisk w gniazdach;
M1 = 5mod4 + 1 = 2
M2 = 6mod4 + 1 = 3
M3 = 7mod4 + 1 = 4
AL.i – algorytmy kolejek (w przypadku istnienia kolejki z priorytetami należy przyjąć, że zgłoszenia posiadają
AL1 = 5mod3 + 1 = 3
AL2 = 6mod3 + 1 = 1
AL3 = 7mod3 + 1 = 2
Otrzymane algorytmy/wyniki:
T1 => rozkład jednostajny.
O1 => rozkład trójkątny.
O2 => rozkład Weibulla.
O3 => rozkład wykładniczy.
L1 => długość kolejki – nieograniczona.
L2 => długość kolejki – ograniczona (możliwe straty).
L3 => długość kolejki – nieograniczona.
AL1 => kolejka z priorytetami.
AL2 => kolejka FIFO.
AL3 => kolejka LIFO.
N1 => rozkład normalny.
N2 => zgłoszenie cierpliwe.
N3 => rozkład wykładniczy.
Opis rozwiązania zadania.
Generowanie klientów następuje w obiekcie Generator. Kolejni klienci generowanie są w odstępach czasu określonym poprzez czas trwania rozkładu jednostajnego. Ze względu na istnienie tylko jednego generatora (wejścia), klienci wchodzą najpierw do kolejki priorytetowej z dwoma stanowiskami obsługi oraz gnieździe o rozkładzie trójkątnym. W tej kolejce przyjmujemy, że zgłoszenia posiadają priorytety. Priorytet klienta ustalany jest w metodzie Rank. Określany jest tez czas wejścia klienta do systemu poprzez zmienną czasWejscia zainicjowana w obiekcie Klient. Każdemu wchodzącemu do systemu klientowi ustalany jest czas cierpliwości. Jest to czas po jakim klient opuści system, jeśli nie zostanie w tym czasie obsłużony. W przypadku gdy klient zostanie obsłużony, ma do wyboru przejścia do dwóch kolejnych kolejek: FIFO oraz LIFO. Przejście do danych kolejek określone jest wartością prawdopodobieństwa p1 oraz 1 - p1. Wartość prawdopodobieństwa dla danego klienta wyznaczana jest za pomocą generowanej zmiennej losowej z przedziału (0,1). W przypadku wejścia klienta do kolejki 2 (FIFO) z trzema stanowiskami obsługi oraz gnieździe o rozkładzie Weibulla, klient po zakończonej obsłudze ma możliwość wyjścia z systemu, bądź ponownego wejścia do kolejki/SMO nr 2. Opcja wybrana przez klienta również jest sterowana poprzez generowaną zmienna losową z przedziału (0,1). W przypadku przejścia klienta z SMO1 do kolejki nr 3 (LIFO) z czterema stanowiskami obsługi oraz SMO o rozkładzie Wykładniczym, klient po zakończonej obsłudze ma możliwość wyjścia z systemu, bądź powrotu do kolejki nr 1.
Parametry rozkładu oraz liczba wygenerowanych klientów określona jest w pliku wejściowym dane.txt.
Otrzymane wyniki symulacji zapisywane są w pliku tekstowym wyniki.txt.
Użyte rozkłady w programie.
Rozkład jednostajny:
Rozkład jednostajny to ciągły rozkład prawdopodobieństwa, dla którego gęstość prawdopodobieństwa w przedziale od a do b jest stała i różna od zera, a poza nim równa zeru. Istnieje też wersja dyskretna tego rozkładu oraz uogólnienie na dowolne nośniki.
Parametry rozkładu:
Gęstość prawdopodobieństwa:
Dystrybuanta:
Średnia wartość oczekiwana:
Wariancja:
Rozkład trójkątny.
Rozkład trójkątny to ciągły rozkład prawdopodobieństwa zmiennej losowej .
Parametry rozkładu:
a : a ϵ (−∞;∞) - min
b : b > a - mean
c : a ≤ c ≤ b -max
Gęstość prawdopodobieństwa:
Dystrybuanta:
Średnia wartość oczekiwana:
Wariancja:
Rozkład Weibulla
Rozkład Weibulla – ciągły rozkład prawdopodobieństwa często stosowany w analizie przeżycia do modelowania sytuacji, gdy prawdopodobieństwo śmierci/awarii zmienia się w czasie.
Parametry rozkładu:
parametr skali (liczba rzeczywista)
parametr kształtu (liczba rzeczywista)
Gęstość prawdopodobieństwa:
Dystrybuanta:
Średnia wartość oczekiwana:
Wariancja:
Rozkład wykładniczy.
Rozkład wykładniczy to rozkład zmiennej losowej opisujący sytuację, w której obiekt może przyjmować stany X i Y, przy czym obiekt w stanie X może ze stałym prawdopodobieństwem przejść w stan Y w jednostce czasu. Prawdopodobieństwo wyznaczane przez ten rozkład to prawdopodobieństwo przejścia ze stanu X w stan Y w czasie δt.
Parametr rozkładu:
odwrotność parametru skali (liczba rzeczywista)
Gęstość prawdopodobieństwa:
Dystrybuanta:
Średnia wartość oczekiwana:
Wariancja:
Kod programu.
MAIN MODULE Dar;
FROM RandMod IMPORT RandomObj, Random;
FROM IOMod IMPORT ReadKey;
FROM GrpMod IMPORT QueueObj, StackObj, RankedObj;
FROM SimMod IMPORT SimTime, StartSimulation;
FROM StatMod IMPORT SREAL, RStatObj, ITimedStatObj, TSINTEGER;
FROM IOMod IMPORT StreamObj, ALL FileUseType;
TYPE
Generator = OBJECT; FORWARD; {Obiekt generatora}
Kol1Prior = OBJECT; FORWARD; {Obiekt kolejki priorytetowej}
Kol2Fifo = OBJECT; FORWARD; {Obiekt kolejki FIFO}
Kol3Lifo = OBJECT; FORWARD; {Obiekt kolejki LIFO}
SMO1Prior = OBJECT; FORWARD; {Obiekt gniazda pierwszego}
SMO2Fifo = OBJECT; FORWARD; {Obiekt gniazda drugiego}
SMO3Lifo = OBJECT; FORWARD; {Obiekt gniazda trzeciego}
Klient = OBJECT; FORWARD;
Generator = OBJECT(RandomObj); {Obiekt generatora}
low: REAL; {pierwszy parametr rozkladu}
high: REAL; {drugi parametr rozkladu}
kolejka1: Kol1Prior;
ileOsob: INTEGER;
komunikaty: BOOLEAN;
plik: StreamObj;
TELL METHOD Generuj();
ASK METHOD Init(IN lo: REAL; IN hi: REAL; IN kol: Kol1Prior; IN liczbaOsob: INTEGER; IN komun: BOOLEAN; IN plikKom: StreamObj);
END OBJECT;
Kol1Prior = OBJECT(RankedObj);
dlugosc: TSINTEGER;
przyjete: TSINTEGER;
odrzucone: INTEGER;
sumka: TSINTEGER;
gniazdo: SMO1Prior;
komunikaty: BOOLEAN;
wej: SREAL;
plik: StreamObj;
ASK METHOD Wstaw(IN klient: Klient);
ASK METHOD Usun(): Klient;
ASK METHOD Init(IN gzd: SMO1Prior; IN komun: BOOLEAN; IN plikKom: StreamObj);
OVERRIDE ASK METHOD Rank(IN a,b: ANYOBJ): INTEGER;
END OBJECT;
Kol2Fifo = OBJECT(QueueObj);
maxDlugosc: INTEGER;
dlugosc: TSINTEGER;
przyjete: TSINTEGER;
odrzucone: INTEGER;
sumka: TSINTEGER;
gniazdo: SMO2Fifo;
wej: SREAL;
komunikaty: BOOLEAN;
plik: StreamObj;
ASK METHOD Wstaw(IN klient: Klient);
ASK METHOD Usun(): Klient;
ASK METHOD Init(IN gzd: SMO2Fifo; IN maxDl: INTEGER; IN komun: BOOLEAN; IN plikKom: StreamObj);
END OBJECT;
Kol3Lifo = OBJECT(StackObj);
dlugosc: TSINTEGER;
przyjete: TSINTEGER;
odrzucone: INTEGER;
sumka: TSINTEGER;
gniazdo: SMO3Lifo;
wej: SREAL;
komunikaty: BOOLEAN;
plik: StreamObj;
ASK METHOD Wstaw(IN klient: Klient);
ASK METHOD Usun(): Klient;
ASK METHOD Init(IN gzd: SMO3Lifo; IN komun: BOOLEAN; IN plikKom: StreamObj);
END OBJECT;
SMO1Prior = OBJECT(RandomObj);
parA: REAL; {pierwszy parametr rozkladu}
parB: REAL; {drugi parametr rozkladu}
parC: REAL; {trzeci parametr rozkladu}
czasPrzebywania: SREAL;
stanowiska: TSINTEGER;
ileStanowisk: INTEGER;
czasCierp: REAL;
kolejka1: Kol1Prior;
kolejka2: Kol2Fifo;
kolejka3: Kol3Lifo;
prawdopodobienstwo: REAL;
komunikaty: BOOLEAN;
plik: StreamObj;
TELL METHOD Obsluguj();
ASK METHOD Init(IN a: REAL; IN b: REAL; IN c: REAL; IN kol1: Kol1Prior; IN kol2: Kol2Fifo; IN kol3: Kol3Lifo; IN ileSt: INTEGER; IN prawd: REAL; IN komun: BOOLEAN; IN plikKom: StreamObj);
END OBJECT;
SMO2Fifo = OBJECT(RandomObj);
skala: REAL; {pierwszy parametr rozkladu}
ksztalt: REAL; {drugi parametr rozkladu}
czasPrzebywania: SREAL;
kolejka2: Kol2Fifo;
prawdopodobienstwo: REAL;
komunikaty: BOOLEAN;
stanowiska: TSINTEGER;
ileStanowisk: INTEGER;
plik: StreamObj;
TELL METHOD Obsluguj();
ASK METHOD Init(IN skal: REAL; IN kszt: REAL; IN kol2: Kol2Fifo; IN ileSt: INTEGER; IN prawd: REAL; IN komun: BOOLEAN; IN plikKom: StreamObj);
END OBJECT;
SMO3Lifo = OBJECT(RandomObj);
lambda1: REAL; {parametr rozkladu}
czasPrzebywania: SREAL;
stanowiska: TSINTEGER;
ileStanowisk: INTEGER;
czasCierp: REAL;
kolejka1: Kol1Prior;
kolejka3: Kol3Lifo;
prawdopodobienstwo: REAL;
komunikaty:BOOLEAN;
plik: StreamObj;
TELL METHOD Obsluguj();
ASK METHOD Init(IN lamb: REAL; IN kol1: Kol1Prior; IN kol3: Kol3Lifo; IN ileSt: INTEGER; IN prawd: REAL; IN komun: BOOLEAN; IN plikKom: StreamObj);
END OBJECT;
Klient = OBJECT;
nr: INTEGER;
priorytet: REAL;
czasWejscia: SREAL;
czasCzek: INTEGER;
kolejka1: Kol1Prior;
komunikaty: BOOLEAN;
ASK METHOD UstawCzas();
ASK METHOD Init(IN n: INTEGER; IN kol1: Kol1Prior; IN prior: REAL; IN komun: BOOLEAN);
END OBJECT;
OBJECT Generator;
{metoda inicjalizujaca dzialanie generatora}
ASK METHOD Init(IN lo: REAL; IN hi: REAL; IN kol: Kol1Prior; IN liczbaOsob: INTEGER; IN komun: BOOLEAN; IN plikKom: StreamObj);
BEGIN
low := lo;
high := hi;
kolejka1 := kol;
ileOsob := liczbaOsob;
komunikaty:=komun;
plik := plikKom;
END METHOD;
{metoda generujaca klientow}
TELL METHOD Generuj();
VAR
i,j,k: INTEGER;
kl: Klient;
los: RandomObj;
zmlos: REAL;
paczka: INTEGER;
BEGIN
i:=0;
WHILE i < ileOsob
paczka:= ASK SELF TO UniformInt (1,3); {zmienna z przedzialu (1;3) oznaczajaca wielkosc paczki}
WAIT DURATION UniformReal(low,high); {Rozklad jednostajny}
END WAIT;
k:=i;
FOR j:=1 TO paczka
IF j <= ileOsob - k
NEW(kl); {powstanie nowego obiektu klienta}
k:=j;
zmlos := ASK SELF TO UniformReal(0.0,1.0); {generowany priorytet klienta}
INC(i);
{wywolanie inicjalizacji obiektu klienta}
ASK kl TO Init(i,kolejka1,zmlos,komunikaty);
IF komunikaty
OUTPUT(SimTime," Powstal nowy klient nr: ",kl.nr);
END IF;
{dodanie klienta do kolejki pierwszej}
ASK kolejka1 TO Wstaw(kl);
END IF;
END FOR;
IF komunikaty
OUTPUT("WIELKOSC PACZKI ZGLOSZEN: ",k );
END IF;
END WHILE;
END METHOD;
END OBJECT;
OBJECT Kol1Prior;
ASK METHOD Init(IN gzd: SMO1Prior; IN komun: BOOLEAN; IN plikKom: StreamObj);
BEGIN
gniazdo:=gzd;
komunikaty:=komun;
plik:=plikKom;
dlugosc:=0;
END METHOD;
{metoda wstawiajaca kleinta do kolejki priorytetowej}
ASK METHOD Wstaw(IN klient: Klient);
BEGIN
dlugosc:=numberIn;
wej:=SimTime;
Add(klient);
IF komunikaty
OUTPUT(SimTime," Klienta nr ",klient.nr," dodano do kolejki nr 1");
END IF;
IF gniazdo.stanowiska < gniazdo.ileStanowisk
INC(przyjete);
TELL gniazdo TO Obsluguj;
ELSE
INC(odrzucone);
IF komunikaty
OUTPUT(SimTime, " Klienta nr: ",klient.nr," odrzucono w powodu braku miejsc w SMO1");
END IF;
END IF;
END METHOD;
{metoda ustalajaca klienta z wyzszym priorytetem}
ASK METHOD Rank(IN a, b : ANYOBJ) : INTEGER;
VAR
klient1:Klient;
klient2:Klient;
BEGIN
klient1:=a;
klient2:=b;
IF klient1.priorytet < klient2.priorytet
RETURN(1);
ELSIF klient1.priorytet = klient2.priorytet
RETURN(0);
ELSE
RETURN(-1);
END IF;
END METHOD;
{metoda usuwajaca klienta z kolejki}
ASK METHOD Usun(): Klient;
VAR
wyn: Klient;
BEGIN
wyn := Remove();
dlugosc:=numberIn;
sumka:=przyjete + odrzucone;
RETURN wyn;
END METHOD;
END OBJECT;
OBJECT Kol2Fifo;
{metoda inicjalizujaca obiekt kolejki FIFO}
ASK METHOD Init(IN gzd: SMO2Fifo; IN maxDl: INTEGER; IN komun: BOOLEAN; IN plikKom: StreamObj);
BEGIN
gniazdo := gzd;
maxDlugosc := maxDl;
komunikaty:=komun;
plik := plikKom;
dlugosc:=0;
END METHOD;
{metoda wstawiajaca kleinta do kolejki FIFO}
ASK METHOD Wstaw(IN klient: Klient);
BEGIN
IF numberIn < maxDlugosc
wej:=SimTime; {czas wejscia klienta do kolejki}
Add(klient); {dodanie klienta do kolejki}
IF komunikaty {zmienna odpowiadajaca za wyswietlanie komuniaktow}
OUTPUT(SimTime," Klienta nr: ",klient.nr," dodano do kolejki nr 2");
END IF;
{sprawdzenie czy sa wolne stanowiska obslugi w gniezdzie 2}
IF gniazdo.stanowiska < gniazdo.ileStanowisk
INC(przyjete); {zmienna ustalajaca ilosc przyjetych klientow}
{wywolanie metody 'Obsluguj' powoduje rozpoczecie obslugi klienta w gniezdzie drugim}
TELL gniazdo TO Obsluguj;
ELSE
INC(odrzucone); {zmienna ustalajaca ilosc klientow muszących czekac w kolejce}
IF komunikaty
OUTPUT(SimTime, " Klienta nr: ",klient.nr," odrzucono w powodu braku miejsc w SMO2");
END IF;
END IF;
ELSE
IF komunikaty
OUTPUT(SimTime," Brak miejsc w kolejce nr 2 dla, klienta nr: ", klient.nr);
END IF;
{usuniecie klienta}
DISPOSE(klient);
END IF;
END METHOD;
{metoda usuwajaca klienta z kolejki}
ASK METHOD Usun(): Klient;
VAR
wyn: Klient;
BEGIN
wyn := Remove();
dlugosc:=numberIn;
sumka:=przyjete + odrzucone; {zmienna ustalacja sume kleintow przyjetych i muszacych czekac(odrzuconych)}
RETURN wyn;
END METHOD;
END OBJECT;
OBJECT Kol3Lifo;
{metoda inicjalizujaca kolejke LIFO}
ASK METHOD Init(IN gzd: SMO3Lifo; IN komun: BOOLEAN; IN plikKom: StreamObj);
BEGIN
gniazdo := gzd;
komunikaty:=komun;
plik := plikKom;
dlugosc:=0;
END METHOD;
{metoda wstawiajaca kleinta do kolejki LIFO}
ASK METHOD Wstaw(IN klient: Klient);
BEGIN
dlugosc:=numberIn;
wej:=SimTime;
Add(klient);
IF komunikaty
OUTPUT(SimTime," Klienta nr ",klient.nr," dodano do kolejki nr 3");
END IF;
IF gniazdo.stanowiska < gniazdo.ileStanowisk
INC(przyjete);
TELL gniazdo TO Obsluguj;
ELSE
INC(odrzucone);
IF komunikaty
OUTPUT(SimTime, " Klienta nr: ",klient.nr," odrzucono w powodu braku miejsc w SMO3");
END IF;
END IF;
END METHOD;
{metoda usuwajaca klienta z kolejki}
ASK METHOD Usun(): Klient;
VAR
wyn: Klient;
BEGIN
wyn := Remove();
dlugosc:=numberIn;
sumka:=przyjete + odrzucone;
RETURN wyn;
END METHOD;
END OBJECT;
OBJECT SMO1Prior;
{metoda inicjalizujaca obiekt gniazda pierwszego}
ASK METHOD Init(IN a: REAL; IN b: REAL; IN c: REAL; IN kol1: Kol1Prior; IN kol2: Kol2Fifo; IN kol3: Kol3Lifo; IN ileSt: INTEGER; IN prawd: REAL; IN komun: BOOLEAN; IN plikKom: StreamObj);
BEGIN
parA:=a;
parB:=b;
parC:=c;
kolejka1:=kol1;
kolejka2:=kol2;
kolejka3:=kol3;
prawdopodobienstwo:=prawd;
komunikaty:=komun;
plik:=plikKom;
stanowiska:=0;
ileStanowisk:=ileSt;
END METHOD;
{metoda obslugi klienta w gniezdzie pierwszym}
TELL METHOD Obsluguj();
VAR
kl: Klient;
zmlos: REAL;
tmp1: REAL;
tmp2: REAL;
BEGIN
WHILE kolejka1.numberIn > 0
kl := ASK kolejka1 TO Usun();
tmp1:= ASK SELF TO UniformReal(30.0, 45.0);
tmp2:= ASK SELF TO UniformReal(45.0, 65.0);
czasCierp:=ASK SELF TO Normal(tmp1,tmp2); {czas cierpliwosci ustalany rozkladem normalnym}
IF stanowiska <= ileStanowisk
IF (SimTime - kolejka1.wej) < czasCierp
INC(stanowiska);
{kl:=ASK kolejka1 TO Usun();}
IF komunikaty
OUTPUT(SimTime, " Gniazdo 1 rozpoczyna obsluge klienta nr: ", kl.nr," liczba zajetych stanowisk: ", stanowiska);
END IF;
WAIT DURATION Triangular(parA,parB,parC); {rozklad trojkatny}
ON INTERRUPT;
END WAIT;
IF komunikaty
OUTPUT(SimTime, " Klient nr: ", kl.nr, " zostal obsluzony w gniezdzie 1");
END IF;
zmlos:=ASK SELF TO UniformReal(0.0, 1.0);
IF zmlos > prawdopodobienstwo
IF komunikaty
OUTPUT(SimTime, " Klient nr: ", kl.nr," zostaje przekierowany do do kolejki 2");
END IF;
DEC(stanowiska);
ASK kolejka2 TO Wstaw(kl);
ELSE
IF komunikaty
OUTPUT(SimTime, " Klient nr: ", kl.nr," zostaje przekierowany do do kolejki 3");
END IF;
DEC(stanowiska);
czasPrzebywania:=SimTime - kl.czasWejscia;
ASK kolejka3 TO Wstaw(kl);
END IF;
ELSE
IF komunikaty
OUTPUT(SimTime, " Klient nr: ", kl.nr, " stracil cierpliwosc, opuszcza system");
END IF;
czasPrzebywania:=SimTime - kl.czasWejscia;
DISPOSE(kl);
END IF;
ELSE
OUTPUT(SimTime, "Klienta nr: ", kl.nr ,"odrzucono z powodu braku miejsc w SMO1");
END IF;
END WHILE;
END METHOD;
END OBJECT;
OBJECT SMO2Fifo;
{metoda inicjalizujaca obiekt gniazda drugiego}
ASK METHOD Init(IN skal: REAL; IN kszt: REAL; IN kol2: Kol2Fifo; IN ileSt: INTEGER; IN prawd: REAL; IN komun: BOOLEAN; IN plikKom: StreamObj);
BEGIN
skala:=skal;
ksztalt:=kszt;
kolejka2:=kol2;
ileStanowisk:=ileSt; {zmienna okreslajaca liczbe stanowisk obslugi w gniezdzie}
prawdopodobienstwo:=prawd; {zmienna okreslajaca prawdopodobienstwo przekierowanie kleinta do gniazda 2}
komunikaty:=komun;
plik:=plikKom;
stanowiska:=0; {zmienna okreslajaca liczbe stanowisk w gniezdzie}
END METHOD;
{metoda obslugi klienta w gniezdzie drugim}
TELL METHOD Obsluguj();
VAR
kl: Klient;
zmlos: REAL; {zmienna okreslajaca wylosowane prawdopodobienstwo}
BEGIN
WHILE kolejka2.numberIn > 0
kl := ASK kolejka2 TO Usun(); {usuniecie klienta z kolejki FIFO}
IF stanowiska <= ileStanowisk {sprawdzenie czy sa wolne stanowiska w gniezdzie}
INC(stanowiska); {inkrementacja liczby wolnych stanowisk}
IF komunikaty
OUTPUT(SimTime, " Gniazdo 2 rozpoczyna obsluge klienta nr: ", kl.nr," liczba zajetych stanowisk: ",stanowiska);
END IF;
WAIT DURATION Weibull(ksztalt,skala); {rozklad Weibulla}
ON INTERRUPT
END WAIT;
IF komunikaty
OUTPUT(SimTime, " Klient nr: ", kl.nr, " zostal obsluzony w gniezdzie 2");
END IF;
zmlos:=ASK SELF TO UniformReal(0.0, 1.0); {zmienna losowa okreslajaca prawdopodobienstwo wyboru dalszej drogi klienta w systemie}
IF zmlos > prawdopodobienstwo {w przypadku 'TRUE' klient przekierowany zostaje do kolejki FIFO(2)}
IF komunikaty
OUTPUT(SimTime, " Klient nr: ", kl.nr," zostaje przekierowany do do kolejki 2");
END IF;
DEC(stanowiska); {deinkrementacja liczby wolnych stanowisk}
ASK kolejka2 TO Wstaw(kl); {wstawienie klienta do kolejki FIFO(2)}
ELSE {w przypadku 'FALSE' klient opuszcza system}
IF komunikaty
OUTPUT(SimTime, " Klient nr ", kl.nr, " zostal ostatecznie obsluzony i opuscil system");
END IF;
czasPrzebywania:=SimTime - kl.czasWejscia; {zmienna okreslajaca czas przebywania klienta w systemie}
DEC(stanowiska); {deinkrementacja liczby stanowisk}
DISPOSE(kl); {usuniecie obiektu danego klienta}
END IF;
ELSE
IF komunikaty
OUTPUT(SimTime, " Klient nr: ", kl.nr, " stracil cierpliwosc, opuszcza system");
END IF;
czasPrzebywania:=SimTime - kl.czasWejscia; {zmienna okreslajaca czas przebywania klienta w systemie}
DISPOSE(kl); {usuniecie obiektu danego klienta}
END IF;
END WHILE;
END METHOD;
END OBJECT;
OBJECT SMO3Lifo;
{metoda inicjalizujaca obiekt gniazda trzeciego}
ASK METHOD Init(IN lamb: REAL; IN kol1: Kol1Prior; IN kol3: Kol3Lifo; IN ileSt: INTEGER; IN prawd: REAL; IN komun: BOOLEAN; IN plikKom: StreamObj);
BEGIN
lambda1:=lamb;
kolejka1:=kol1;
kolejka3:=kol3;
ileStanowisk:=ileSt;
prawdopodobienstwo:=prawd;
komunikaty:=komun;
plik:=plikKom;
stanowiska:=0;
END METHOD;
{metoda obslugi klienta w gniezdzie trzecim}
TELL METHOD Obsluguj();
VAR
kl:Klient;
zmlos:REAL;
tmp1: REAL;
BEGIN
WHILE kolejka3.numberIn > 0
kl := ASK kolejka3 TO Usun();
tmp1:= ASK SELF TO UniformReal(0.0, 5.0); {zmienna okreslajaca parametr rozkladu}
czasCierp:=ASK SELF TO Exponential(tmp1);{czas cierpliwosci ustalany rozkladem wykladniczym}
IF stanowiska <= ileStanowisk
IF (SimTime - kolejka3.wej) < czasCierp {sprawdzenie czy klient stracil cierpliwosc}
INC(stanowiska);
{kl:=ASK kolejka3 TO Usun();}
IF komunikaty
OUTPUT(SimTime, " Gniazdo 3 rozpoczyna obsluge klienta nr: ", kl.nr," liczba zajetych stanowisk: ", stanowiska);
END IF;
WAIT DURATION Exponential(lambda1); {rozkald wykladniczy}
ON INTERRUPT;
END WAIT;
IF komunikaty
OUTPUT(SimTime, " Klient nr: ", kl.nr, " zostal obsluzony w gniezdzie 3");
END IF;
zmlos:=ASK SELF TO UniformReal(0.0, 1.0);
IF zmlos > prawdopodobienstwo
IF komunikaty
OUTPUT(SimTime, " Klienta nr: ", kl.nr," zostaje przekierowany do do kolejki 1");
END IF;
DEC(stanowiska);
ASK kolejka1 TO Wstaw(kl);
ELSE
IF komunikaty
OUTPUT(SimTime, " Klient nr: ", kl.nr, " zostal ostatecznie obsluzony i opuscil system");
END IF;
DEC(stanowiska);
czasPrzebywania:=SimTime - kl.czasWejscia;
DISPOSE(kl);
END IF;
ELSE
IF komunikaty
OUTPUT(SimTime, " Klient nr: ", kl.nr, " stracil cierpliwosc, opuszcza system");
END IF;
czasPrzebywania:=SimTime - kl.czasWejscia;
DISPOSE(kl);
END IF;
ELSE
OUTPUT(SimTime, "Klienta nr: ", kl.nr ,"odrzucono z powodu braku miejsc w SMO3");
END IF;
END WHILE;
END METHOD;
END OBJECT;
OBJECT Klient;
{metoda inicjalizujaca obiekt klienta}
ASK METHOD Init(IN n: INTEGER; IN kol1: Kol1Prior; IN prior: REAL; IN komun: BOOLEAN);
BEGIN
nr:=n; {zmienna okreslajaca numer klienta}
kolejka1:=kol1; {obiekt kolejki priorytetowej}
komunikaty:=komun; {zmienna odpowiedajaca za wyswietlanie komunikatow}
priorytet:=prior; {zmienna okreslajaca priorytet klienta}
END METHOD;
{metoda ustawiajaca czas wejscia klienta do systemu}
ASK METHOD UstawCzas();
BEGIN
czasWejscia:=SimTime; {zmienna okreslajaca czas wejscia klienta do systemu}
END METHOD;
END OBJECT;
VAR
generator: Generator; {zmienna okreslajaca obiekt Generator}
kolejka1: Kol1Prior; {zmienna okreslajaca obiekt kolejki priorytetowej }
kolejka2: Kol2Fifo; {zmienna okreslajaca obiekt kolejki FIFO}
kolejka3: Kol3Lifo; {zmienna okreslajaca obiekt kolejki LIFO}
gniazdo1: SMO1Prior; {zmienna okreslajaca obiekt gniazda pierwszego}
gniazdo2: SMO2Fifo; {zmienna okreslajaca obiekt gniazda drugiego}
gniazdo3: SMO3Lifo; {zmienna okreslajaca obiekt gniazda trzeciego}
plik: StreamObj; {Zmienna okreslajaca obiekt odpowiadajacy za uzycie pliku tekstowego}
{zmienne typu rzeczywistego okreslajace parametry rozkladow oraz prawdopodobienstwa p1,p2,p3}
low,high,a,b,c,lambda1,ksztalt,skala,p1,p2,p3: REAL;
{zmienne typu INTEGER okreslajace liczbe osob,dlugosc kolejki FIFO(drugiej), liczbe stanowisk w gniazdach}
ileOsob, maxDl2, ileSt1,ileSt2,ileSt3 :INTEGER;
{zmienne typu STRING,CHAR,REAL odpowiadajace za wczytanie odpowiednich linijek z pliku zrodlowego}
tmpString:STRING;
tmpChar :CHAR;
tmpReal : REAL;
Key :CHAR;
{monitory}
monZglKol1, monZglKol2, monZglKol3, monZajKan1,monZajKan2, monZajKan3, monZgl1, monZgl2, monZgl3: ITimedStatObj;
monCzasPrzebyw1 ,monCzasPrzebyw2, monCzasPrzebyw3 :RStatObj;
komunikaty: BOOLEAN;
BEGIN
{zapytanie w konsoli, czy pokazac komunikaty}
OUTPUT("Czy pokazywac komunikaty? [T/N]: ");
Key := ReadKey();
OUTPUT("");
komunikaty:=TRUE;
IF ((Key = 'n') OR (Key = 'N'))
komunikaty := FALSE;
END IF;
IF ((Key = 't') OR (Key = 'T'))
komunikaty := TRUE;
END IF;
{Stworzenie uzytych w programie obiektow}
NEW(generator);
NEW(kolejka1);
NEW(kolejka2);
NEW(kolejka3);
NEW(gniazdo1);
NEW(gniazdo2);
NEW(gniazdo3);
NEW(plik);
{Dlugosc kolejki FIFO, jako kolejki ograniczonej}
maxDl2:=3;
{Liczba stanowisk obslugi w gniezdzie:}
ileSt1:=1; {pierwszym}
ileSt2:=2; {drugim}
ileSt3:=3; {trzecim}
{Odczyt poszczegolnych parametrow z pliku dane.txt}
ASK plik TO Open("dane.txt", Input);
ASK plik TO ReadLine(tmpString);
ASK plik TO ReadInt(ileOsob);
ASK plik TO ReadChar(tmpChar);
ASK plik TO ReadLine(tmpString);
ASK plik TO ReadReal(low);
ASK plik TO ReadChar(tmpChar);
ASK plik TO ReadLine(tmpString);
ASK plik TO ReadReal(high);
ASK plik TO ReadChar(tmpChar);
ASK plik TO ReadLine(tmpString);
ASK plik TO ReadReal(a);
ASK plik TO ReadChar(tmpChar);
ASK plik TO ReadLine(tmpString);
ASK plik TO ReadReal(b);
ASK plik TO ReadChar(tmpChar);
ASK plik TO ReadLine(tmpString);
ASK plik TO ReadReal(c);
ASK plik TO ReadChar(tmpChar);
ASK plik TO ReadLine(tmpString);
ASK plik TO ReadReal(ksztalt);
ASK plik TO ReadChar(tmpChar);
ASK plik TO ReadLine(tmpString);
ASK plik TO ReadReal(skala);
ASK plik TO ReadChar(tmpChar);
ASK plik TO ReadLine(tmpString);
ASK plik TO ReadReal(lambda1);
ASK plik TO ReadChar(tmpChar);
ASK plik TO ReadLine(tmpString);
ASK plik TO ReadReal(p1);
ASK plik TO ReadChar(tmpChar);
ASK plik TO ReadLine(tmpString);
ASK plik TO ReadReal(p2);
ASK plik TO ReadChar(tmpChar);
ASK plik TO ReadLine(tmpString);
ASK plik TO ReadReal(p3);
{zamkniecie pliku zrodlowego}
ASK plik TO Close;
{Otworzenie pliku w ktorym zapisane beda wyniki symulacji}
ASK plik TO Open("Wyniki.txt",Output);
{inicjalizacja uzytych w programie obiektow z wczytanymi parametrami z pliku wejsciowego}
ASK generator TO Init(low, high, kolejka1, ileOsob, komunikaty, plik);
ASK gniazdo1 TO Init(a,b,c,kolejka1,kolejka2,kolejka3,ileSt1,p1,komunikaty,plik);
ASK kolejka1 TO Init(gniazdo1,komunikaty,plik);
ASK gniazdo2 TO Init(skala,ksztalt,kolejka2,ileSt2,p2,komunikaty,plik);
ASK kolejka2 TO Init(gniazdo2,maxDl2,komunikaty,plik);
ASK gniazdo3 TO Init(lambda1,kolejka1,kolejka3,ileSt3,p3,komunikaty,plik);
ASK kolejka3 TO Init(gniazdo3,komunikaty,plik);
{poczatek symulacji, tzn wygenerowanie klientow}
TELL generator TO Generuj;
{poczatek symulacji}
StartSimulation();
{wyswietlenie statystyk liczby zgloszen w poszczegolnych kolejkach}
monZglKol1 := GETMONITOR(kolejka1.przyjete, ITimedStatObj);
monZglKol2 := GETMONITOR(kolejka2.przyjete, ITimedStatObj);
monZglKol3 := GETMONITOR(kolejka3.przyjete, ITimedStatObj);
{wyswietlenie statystyk zajetych stanowisk w poszczegolnych SMO}
monZajKan1 := GETMONITOR(gniazdo1.stanowiska, ITimedStatObj);
monZajKan2 := GETMONITOR(gniazdo2.stanowiska, ITimedStatObj);
monZajKan3 := GETMONITOR(gniazdo3.stanowiska, ITimedStatObj);
{wyswietlenie statystyk czasu przebywania zgloszenia w poszczegolnych SMO}
monCzasPrzebyw1 := GETMONITOR(gniazdo1.czasPrzebywania, RStatObj);
monCzasPrzebyw2 := GETMONITOR(gniazdo2.czasPrzebywania, RStatObj);
monCzasPrzebyw3 := GETMONITOR(gniazdo3.czasPrzebywania, RStatObj);
{wyswietlenie statystyk liczby zgloszen w poszczegolnych SMO}
monZgl1 := GETMONITOR(kolejka1.sumka, ITimedStatObj);
monZgl2 := GETMONITOR(kolejka2.sumka, ITimedStatObj);
monZgl3 := GETMONITOR(kolejka3.sumka, ITimedStatObj);
{zapis otrzymanych wynikow do pliku}
ASK plik TO WriteString("=========================================================================");
ASK plik TO WriteLn;
ASK plik TO WriteString("LICZBA ZGLOSZEN W KOLEJCE 1: ");
ASK plik TO WriteReal(ASK monZglKol1 TO Mean,7,4);
ASK plik TO WriteString(" ODCHYLENIE: ");
ASK plik TO WriteReal(ASK monZglKol1 TO StdDev(),7,4);
ASK plik TO WriteLn;
ASK plik TO WriteString("LICZBA ZGLOSZEN W KOLEJCE 2: ");
ASK plik TO WriteReal(ASK monZglKol2 TO Mean(),7,4);
ASK plik TO WriteString(" ODCHYLENIE: ");
ASK plik TO WriteReal(ASK monZglKol2 TO StdDev(),7,4);
ASK plik TO WriteLn;
ASK plik TO WriteString("LICZBA ZGLOSZEN W KOLEJCE 3: ");
ASK plik TO WriteReal(ASK monZglKol3 TO Mean(),7,4);
ASK plik TO WriteString(" ODCHYLENIE STANDARDOWE: ");
ASK plik TO WriteReal(ASK monZglKol3 TO StdDev(),7,4);
ASK plik TO WriteLn;
ASK plik TO WriteString("SREDNI CZAS PRZEBYWANIA ZGLOSZENIA1: ");
ASK plik TO WriteReal(ASK monCzasPrzebyw1 TO Mean(),5,2);
ASK plik TO WriteString(" ODCHYLENIE STANDARDOWE: ");
ASK plik TO WriteReal(ASK monCzasPrzebyw1 TO StdDev(),5,2);
ASK plik TO WriteLn;
ASK plik TO WriteString("SREDNI CZAS PRZEBYWANIA ZGLOSZENIA2: ");
ASK plik TO WriteReal(ASK monCzasPrzebyw2 TO Mean(),5,2);
ASK plik TO WriteString(" ODCHYLENIE STANDARDOWE: ");
ASK plik TO WriteReal(ASK monCzasPrzebyw2 TO StdDev(),5,2);
ASK plik TO WriteLn;
ASK plik TO WriteString("SREDNI CZAS PRZEBYWANIA ZGLOSZENIA3: ");
ASK plik TO WriteReal(ASK monCzasPrzebyw3 TO Mean(),5,2);
ASK plik TO WriteString(" ODCHYLENIE STANDARDOWE: ");
ASK plik TO WriteReal(ASK monCzasPrzebyw3 TO StdDev(),5,2);
ASK plik TO WriteLn;
ASK plik TO WriteString("SREDNIA LICZBA ZAJETYCH KANALOW W SMO 1: ");
ASK plik TO WriteReal(ASK monZajKan1 TO Mean(),5,2);
ASK plik TO WriteString(" ODCHYLENIE STANDARDOWE: ");
ASK plik TO WriteReal(ASK monZajKan1 TO StdDev(),5,2);
ASK plik TO WriteLn;
ASK plik TO WriteString("SREDNIA LICZBA ZAJETYCH KANALOW W SMO 2: ");
ASK plik TO WriteReal(ASK monZajKan2 TO Mean(),5,2);
ASK plik TO WriteString(" ODCHYLENIE STANDARDOWE: ");
ASK plik TO WriteReal(ASK monZajKan2 TO StdDev(),5,2);
ASK plik TO WriteLn;
ASK plik TO WriteString("SREDNIA LICZBA ZAJETYCH KANALOW W SMO 3: ");
ASK plik TO WriteReal(ASK monZajKan3 TO Mean(),5,2);
ASK plik TO WriteString(" ODCHYLENIE STANDARDOWE: ");
ASK plik TO WriteReal(ASK monZajKan3 TO StdDev(),5,2);
ASK plik TO WriteLn;
{wyznacznie poszczegolnych prawdopodobienstw obsluzenie zgloszenia}
p1 := FLOAT(kolejka1.przyjete)/FLOAT(kolejka1.przyjete + kolejka1.odrzucone);
p2 := FLOAT(kolejka2.przyjete)/FLOAT(kolejka2.przyjete + kolejka2.odrzucone);
p3 := FLOAT(kolejka3.przyjete)/FLOAT(kolejka3.przyjete + kolejka3.odrzucone);
ASK plik TO WriteString("PRAWDOPODOBIENSTWO OBSLUZENIA ZGLOSZENIA PRZEZ SMO 1: ");
ASK plik TO WriteReal(p1,5,2);
ASK plik TO WriteLn;
ASK plik TO WriteString("PRAWDOPODOBIENSTWO OBSLUZENIA ZGLOSZENIA PRZEZ SMO 2: ");
ASK plik TO WriteReal(p2,5,2);
ASK plik TO WriteLn;
ASK plik TO WriteString("PRAWDOPODOBIENSTWO OBSLUZENIA ZGLOSZENIA PRZEZ SMO 3: ");
ASK plik TO WriteReal(p3,5,2);
ASK plik TO WriteLn;
ASK plik TO WriteString("SREDNIA LICZBA ZGLOSZEN W SMO 1: ");
ASK plik TO WriteReal(ASK monZgl1 TO Mean(),7,4);
ASK plik TO WriteString(" ODCHYLENIE STANDARDOWE: ");
ASK plik TO WriteReal(ASK monZgl1 TO StdDev(),7,4);
ASK plik TO WriteLn;
ASK plik TO WriteString("SREDNIA LICZBA ZGLOSZEN W SMO 2: ");
ASK plik TO WriteReal(ASK monZgl2 TO Mean(),7,4);
ASK plik TO WriteString(" ODCHYLENIE STANDARDOWE: ");
ASK plik TO WriteReal(ASK monZgl2 TO StdDev(),7,4);
ASK plik TO WriteLn;
ASK plik TO WriteString("SREDNIA LICZBA ZGLOSZEN W SMO 3: ");
ASK plik TO WriteReal(ASK monZgl3 TO Mean(),7,4);
ASK plik TO WriteString(" ODCHYLENIE STANDARDOWE: ");
ASK plik TO WriteReal(ASK monZgl3 TO StdDev(),7,4);
ASK plik TO WriteLn;
ASK plik TO WriteString("=========================================================================");
OUTPUT(" ");
OUTPUT(" ");
{zapytanie, czy wyswietlic w konsoli otrzymane wyniki symulacji}
OUTPUT("Czy chcesz zobaczyc wyniki symulacji? [T/N]: ");
Key := ReadKey();
OUTPUT("");
IF ((Key = 't') OR (Key = 'T'))
{Wyswietlenie wynikow symulacji w konsoli}
OUTPUT ("=========================================================================");
OUTPUT ("LICZBA ZGLOSZEN W KOLEJCE 1: ",ASK monZglKol1 TO Mean, " ODCHYLENIE STANDARDOWE: ", ASK monZglKol1 TO StdDev());
OUTPUT ("LICZBA ZGLOSZEN W KOLEJCE 2: ",ASK monZglKol2 TO Mean, " ODCHYLENIE STANDARDOWE: ", ASK monZglKol2 TO StdDev());
OUTPUT ("LICZBA ZGLOSZEN W KOLEJCE 3: ",ASK monZglKol3 TO Mean, " ODCHYLENIE STANDARDOWE: ", ASK monZglKol3 TO StdDev());
OUTPUT (" ");
OUTPUT ("SREDNI CZAS PRZEBYWANIA ZGLOSZENIA1: ",ASK monCzasPrzebyw1 TO Mean(), " ODCHYLENIE STANDARDOWE: ", ASK monCzasPrzebyw1 TO StdDev());
OUTPUT ("SREDNI CZAS PRZEBYWANIA ZGLOSZENIA2: ",ASK monCzasPrzebyw2 TO Mean(), " ODCHYLENIE STANDARDOWE: ", ASK monCzasPrzebyw2 TO StdDev());
OUTPUT ("SREDNI CZAS PRZEBYWANIA ZGLOSZENIA3: ",ASK monCzasPrzebyw3 TO Mean(), " ODCHYLENIE STANDARDOWE: ", ASK monCzasPrzebyw3 TO StdDev());
OUTPUT (" ");
OUTPUT ("SREDNIA LICZBA ZAJETYCH KANALOW W SMO 1: ", ASK monZajKan1 TO Mean(), " ODCHYLENIE STANDARDOWE: ", ASK monZajKan1 TO StdDev());
OUTPUT ("SREDNIA LICZBA ZAJETYCH KANALOW W SMO 2: ", ASK monZajKan2 TO Mean(), " ODCHYLENIE STANDARDOWE: ", ASK monZajKan2 TO StdDev());
OUTPUT ("SREDNIA LICZBA ZAJETYCH KANALOW W SMO 3: ", ASK monZajKan3 TO Mean(), " ODCHYLENIE STANDARDOWE: ", ASK monZajKan3 TO StdDev());
OUTPUT (" ");
OUTPUT ("PRAWDOPODOBIENSTWO OBSLUZENIA ZGLOSZENIA PRZEZ SMO 1: ", p1);
OUTPUT ("PRAWDOPODOBIENSTWO OBSLUZENIA ZGLOSZENIA PRZEZ SMO 2: ", p2);
OUTPUT ("PRAWDOPODOBIENSTWO OBSLUZENIA ZGLOSZENIA PRZEZ SMO 3: ", p3);
OUTPUT (" ");
OUTPUT ("SREDNIA LICZBA ZGLOSZEN W SMO 1: ",ASK monZgl1 TO Mean, " ODCHYLENIE STANDARDOWE: ", ASK monZgl1 TO StdDev());
OUTPUT ("SREDNIA LICZBA ZGLOSZEN W SMO 2: ",ASK monZgl2 TO Mean, " ODCHYLENIE STANDARDOWE: ", ASK monZgl2 TO StdDev());
OUTPUT ("SREDNIA LICZBA ZGLOSZEN W SMO 3: ",ASK monZgl3 TO Mean, " ODCHYLENIE STANDARDOWE: ", ASK monZgl3 TO StdDev());
OUTPUT ("==========================================================================");
END IF;
{usuniecie wszytskich obiektow}
DISPOSE(gniazdo1);
DISPOSE(gniazdo2);
DISPOSE(gniazdo3);
DISPOSE(kolejka1);
DISPOSE(kolejka2);
DISPOSE(kolejka3);
DISPOSE(generator);
{zamkniecie pliku}
ASK plik TO Close;
DISPOSE(plik);
OUTPUT("");
OUTPUT("Aby zakonczyc dzialanie programu wcisnij dowolny klawisz");
Key := ReadKey();
END MODULE.