Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

108
Magazzino pezzi da lavorare LABORATORIO DI SIMULAZIONE Molinari Davis Esercizio per la parte pratica dell’esame Sistema da simulare

description

Realizzazione di un simulatore software scritto in C++ per simulare un prototipo di sistema reale. Si parte da una simulazione a run indipendenti e poi si passa ad una simulaizone a batch per lo studio del fenomeno del transitorio iniziale. In seguito si realizza una Rete di Petri, tramite il tool GreatSPN, equivalente al sistema da studiare, si effettua la simulazione e si confrontano i risultati ottenuti nei 2 casi.

Transcript of Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Page 1: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Magazzinopezzi da lavorare

LABORATORIO DI SIMULAZIONE

Molinari Davis

Esercizio per la parte pratica dell’esame

Sistema da simulare

Page 2: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

PRIMA PARTE

“ Nella prima fase si dovrà analizzare il sistema e si dovranno definire (sulla carta) le variabili di stato, gli eventi - distinguendo quelli incondizionati, che dovranno essere memorizzati nella FEL da quelli condizionati, trattati in seguito al verificarsi di un cambiamento di stato causato da un evento incondizionato, le procedure per il trattamento degli eventi, gli accumulatori per il calcolo degli indici di prestazione. “

Page 3: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

VARIABILI DI STATO

Le variabili che mi serviranno per tenere traccia dello stato del sistema sono sostanzialmente:

-Il numero di pezzi che ci sono in coda nel primo stato (dove con questo è inteso il numero di pezzi in coda più il pezzo in lavorazione)

- Una variabile booleana necessaria ad indicarmi se il servitore si trova o meno in stato di blocco a causa di un riempimento della coda2. Se necessario verrà settata a bloccato (true) durante la gestione di un evento di tipo Partenza1 e verrà poi riportata a non bloccato (false) quando di verifica una partenza dalla coda2 (che poi è anche dal sistema) e si libera un posto in coda2.Quindi un boolean che vale:

true se il servitore1 è bloccatofalse altrimenti

In realtà il servitore1 si può trovare in 3 diversi stati che sono bloccato, libero e occupato. Ma ci basta solo il boolean per sapere se si trova in blocco o meno perché poi la discriminazione tra libero e occupato la ricaviamo tramite il numero di pezzi presenti nella coda, che siccome contiene anche l’eventuale pezzo in lavorazione basta verificare se è maggiore di 0.

- Il numero di pezzi che ci sono in coda nel secondo stato anche in questo caso mi basta questo, e lo stato, libero o occupato, lo determino dal valore di tale variabile.

Page 4: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

DISTINZIONE TRA GLI EVENTI

Per prima cosa occorre definire quelli che saranno gli eventi che interessano il nostro sistema. Ci saranno eventi incondizionati che si verificano sempre senza dipendere dallo stato del sistema o da altre condizioni e che dovranno essere memorizzati nella FEL (Future Event List) ed eventi condizionati che si verificano in seguito a particolari situazioni o a cambiamenti di stato causati dal verificarsi di eventi incondizionati.

EVENTI INCONDIZIONATI- Arrivo in coda 1- Partenza da 1- Partenza da 2- Fine simulazione

EVENTI CONDIZIONATI- Scarto del pezzo- Coda della seconda stazione piena (dipende praticamente da tutti e 3 gli eventi condizionati cioè dalla frequenza degli arrivi e delle partenze dai 2 stadi del sistema)- Conseguente blocco del servitore1 (cambia stato a bloccato)- Successivo sblocco del servitore1 quando si libero un posto nella coda del secondo servitore. Questo evento è quindi condizionato ad un evento di tipo partenza da 2.

Page 5: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

GESTIONE DEGLI EVENTI INCONDIZIONATI

Arrivo in 1 di N clienti- Incremento di N (dimensione del carrello) il numero di pezzi presenti nella coda1- Se coda1 == N, cioè prima era 0, schedulo subito una partenza perchè vuol dire che il servitore1 era libero-In ogni caso schedulo l'evento per il prossimo arrivo

Partenza dal servitore 1- Per prima cosa guardo se il pezzo è buono o da scartare- Se è da scartare decremento coda1 e incremento scarti- Se non è da scartare controllo la lunghezza della coda della seconda postazione- Guardo se c’è posto , se NO non posso schedulare eventi- Se SI mi ci infilo

- Sposto il pezzo nella coda 2 - se era vuota schedulo partenza da 2- se coda1 non vuota schedulo partenza da 1, questo controllo lo faccio anche nel caso in cui il pezzo fosse stato

scartato.

Partenza dal servitore 2- Decremento coda2- Controllo se il pezzo è da scartare, se si incremento scarti- In ogni caso controllo coda2, se non vuota schedula la prossima partenza- Controllo comunque se servitore 1 bloccato

- se SI sposta il pezzo e cambio stato servitore1 a NON occupato

DA QUESTE CONSIDERAZIONI SON ARRIVATO AI FLOW-CHART PRESENTI NELLE PAGINE SEGUENTI

Page 6: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

GESTIONE DELL’EVENTO DI SCARTO DI UN PEZZO

(EVENTO CONDIZIONATO)

Per vedere se un pezzo è da scartare o meno faccio così:

Definisco, con una #define, all’inizio del programma una costante simbolica che indica quale è la probabilità che il pezzo venga scartato e che potrà chiamarsi ad esempio P_SCART.

Poi, utilizzando la libreria “rnd.h” presente nel progetto effettuo la generazione casuale (pseudo-casuale) di un numero compreso fa 1 e 100.

A questo punto vado a vedere se il numero generato è minore o uguale al valore di P_SCART. Se lo è vorrà dire che il pezzo è da scartare (e quindi andrò ad incrementare il contatore dei pezzi scartati), altrimenti no. Chiamando ad esempio ‘p’ il numero generato avrò la situazione:

1 <= p <= P_SCART SCARTO IL PEZZO

P_SCART < p <= 100 NON SCARTO

Siccome i pezzi possono essere scartati dopo le lavorazioni di entrambe le macchine, suppongo che le probabilità di scarto siano diverse e quindi ho definito 2 costanti P_SCART1 e P_SCART2 e, a seconda della situazione in cui mi trovo (se a fine lavorazione1 o a fine lavorazione2), confronto il numero generato con il relativo valore della probabilità di scarto.

Page 7: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Tipo_EventoARRIVO

Coda1 += N

Coda 1 == N

Inserisci in FEL unevento PARTENZA

dalla stazione 1

Inserisci in FELl’evento del prossimo

ARRIVO di N pezzi

SI

NO

Flow-chart della gestione di un evento di tipo ARRIVO

Page 8: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Tipo_EventoPARTENZA-1

Scarto?

Coda2 <= K

Coda1 --Coda2 ++

Serv1 = bloccato

Coda1 --PezziScart ++

Coda2 == 1?

Coda1 > 0 ?

Inserisci in FEL unevento PARTENZA2

Inserisci in FEL unevento PARTENZA1

NO

NO

NO

NO

SI

SI

SI

SI

Flow-chart della gestione di un evento di tipo Partenza dal servitore 1

Page 9: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Tipo_EventoPARTENZA-2

Coda2--

Scarto?

Coda2 > 0

Serv1bloccato?

Coda1 > 0

Coda1 --Coda2 ++

Inserisci in FEL unevento PARTENZA2

Inserisci in FEL unevento PARTENZA1

NO

NO

NO

NO

SI

SI

SI

SI

PezziScart ++

Serv1 =Non bloccato

Flow-chart della gestione di un evento di tipo Partenza dal servitore 2

Page 10: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

GESTIONE DELL’EVENTO DI “FINE SIMULAZIONE”

Tipo_EventoFINE SIMULAZIONE

Rimuovo dalla FELL’ evento di tipo

ARRIVO

EndOfSimulation = true

In questo modo non arresto brutalmente la simulazione ma blocco gli arrivi e finisco di gestire i pezzi che sono presenti nel sistema. In questo modo può capitare che la simulazione non termini esattamente al tempo stabilito ma qualche istante dopo a causa della fine del trattamento di qualche pezzo. L’arresto del simulatore avverrà solo quando EndOfSimulation varrà true e la FEL sarà vuota. Quindi ho realizzato 2 nuove funzioni che lavorano sulla List, una per rimuovere gli eventi di tipo ARRIVO e un che restituisce true se la lista è vuota o false altrimenti.

Quindi avrò, nel ciclo do-while principale del programma la seguente condizione:

do Clock();while (EndOfSimulation == false || Lista.Vuota() == false);

Page 11: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

ACCUMULATORI

Gli accumulatori che pensavo di tenere per la simulazione del sistema sono i seguenti:

- Numero di pezzi presenti nella coda1

- Numero di pezzi presenti nella coda2

- Numero di pezzi completati

- Numero pezzi scartati dalla prima stazione

- Numero pezzi scartati dalla seconda stazione

- Il numero totale di pezzi presenti nel sistema lo ricavo dalla somma dei pezzi presenti nelle 2 code visto che tali variabili tengono conto sia dei pezzi in coda che di quello in lavorazione.

- Una variabile per tenere aggiornata l’area sotto la curva n(t) che indica quanti pezzi sono presenti nel sistema al tempo t. Questa servirà poi per calcolare il tempo medio di pezzi presenti nel sistema e il tempo medio di permanenza.

- Due variabili Busy1 e Busy2 che accumulano il tempo totale in cui sono occupate rispettivamente la stazione1 e la stazione2. In seguito saranno necessarie per il calcolo delle utilizzazioni delle 2 stazioni.

- Una variabile che tiene conto di quanto tempo la macchina1 trascorre nello stato “bloccato”

Page 12: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

CALCOLI ED INDICI DI PRESTAZIONE

- Il numero medio di pezzi presenti nel sistema lo calcolo facendo l’area sotto la curva diviso il tempo totale di osservazione.-Il throughput del sistema lo calcolo facendo il numero di pezzi completati / tempo totale- Il tempo medio di permanenza nel sistema è invece:

Area sotto la curva / pezzi totali usciti(quindi anche di quelli scartati)- Il numero di pezzi totali sarà semplicemente la somma dei pezzi lavorati con i pezzi scartati (dalle 2 postazioni)Pezzi totali = pezzi scartati1 + pezzi scartati2 +pezzi buoni- La percentuale di pezzi scartati la calcolo facendo il numero di pezzi scartati diviso il totale dei pezzi buoni più quelli scartati.- Percentuale di blocco macchina1:

tempo di blocco/tempo totale- Utilizzazione macchina1 = busytime1 / tempo totale- Busytime1 lo calcolo facendo la somma degli intervalli in cui il servitore1 è occupato, cioè quando non è bloccato e c’è almeno un pezzo in coda. - Utilizzazione macchina2 = busytime2 / tempo totaleBusytime2 lo calcolo facendo la stessa cosa calcolando il tempo in cui la postazione 2 è occupata.

Page 13: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

SECONDA PARTE

REALIZZAZIONE DEL CODICE DEL SIMULATORE

La seconda parte del progetto di laboratorio consiste nella realizzazione di un simulatore software, scritto in C++, del sistema preso in considerazione.

La realizzazione di tale simulatore è avvenuta per fasi:

- La prima versione del simulatore era semplificata, prevedeva un’unica Run senza suddivisione in batch.

- Poi ho effettuato una modifica in modo da poter specificare da parametro di linea di comando il numero di run da seguire.

- Si è poi passati alla simulazione a batch, e quindi il simulatore è stato modificato in modo da implementare questa funzionalità. E’ stato necessario inserire un nuovo tipo di evento, che ho chiamato FINE_BATCH, e la funzione per la sua gestione.

Page 14: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Realizzazione del simulatore: cosa occorre definire

Per procedere alla realizzazione del simulatore, quindi alla stesura del codice C++, occorre prendere alcune decisioni di tipo implementativo e definire quindi alcuni aspetti, e più precisamente:

- le strutture dati e le funzioni per implementare la Event List;

- una funzione di inizializzazione dello stato e della event list;

- le funzioni per la gestione degli eventi;- una funzione di aggiornamento degli accumulatori

per il calcolo dei risultati dell’esperimento di simulazione;

- una funzione per il calcolo e la stampa dei risultati;

- un ciclo di avanzamento del tempo simulato;

Inoltre, se, come nel nostro caso, il modello è stocastico, servono anche delle funzioni per la generazione di sequenze casuali, estratte da distribuzioni di vario tipo.

Page 15: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

EventList: Strutture dati

Per quanto riguarda la EventList si è scelto di utilizzare un’implementazione semplice di tipo lista, basata sulle Standard Template Libraries del C++.

La definizione della classe EventList e della classe Evento viene fatta nel file header chiamato event_list.h. Un oggetto di tipo evento non è altro che una struttura composta sostanzialmente da 2 campi che costituiscono:

- il tipo dell’evento

- l’istante di tempo per cui è schedulato

I tipi di eventi possibili vengono sempre definiti nell’header event_list.h tramite un enumeratore.

enum EventType {ARRIVO,PARTENZA1,PARTENZA2,FINE_BATCH,SIM_END};

Come si vede vengono definiti i 5 tipi di eventi previsti: arrivo di pezzi nel sistema, partenza dal servitore 1, partenza dal servitore 2, fine del batch corrente e fine della simulazione.

In questo caso stiamo sempre parlando di eventi incondizionati

Page 16: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

event_list.h

#include <list> //classe della Standard Template Library (STL)using namespace std;

//tipi di evento enum EventType {ARRIVO,PARTENZA1,PARTENZA2,FINE_BATCH,SIM_END};

class Evento {public:

EventType tipo; // tipo dell'evento// istante di tempo in cui è schedulato l'eventodouble sched_time;// metodo costruttore inline Evento(enum EventType type,double time);

};

inline Evento::Evento(enum EventType type, double time) : tipo(type), sched_time(time){}

class EventList {public:

inline EventList(); // metodo costruttore void Sched(Evento *ev); // inserisce l'evento nella event listEvento *Get(); // preleva dalla event list l'evento in

testavoid RimuoviArrivi(); // elimina eventi di tipo ARRIVO dalla event listbool Vuota(); // ritorna true se la lista è vuota, false

altrimentiprivate:

list<Evento*> ev_list; // event list implementata mediante la STL};

inline EventList::EventList(){}

Page 17: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Dopo aver definito come è implementata la EventList occorre definire quali sono le funzioni che ci servono per manipolarla.

Nel nostro caso ci occorre:- Una funzione per la schedulazione degli

eventi, ovvero, più semplicemente per l’inserimento degli eventi nella EventList.

- Una funzione che ci restituisce l’evento in testa alla EventList, cioè quello con il tempo di schedulazione minore (il “prossimo” evento).

- Una funzione per rimuovere dalla EventList gli eventi di tipo ARRIVO; necessaria quando si raggiunge il tempo di fine simulazione; si rimuove il prossimo evento di tipo ARRIVO che impedisce quindi la generazione di altri eventi di questo tipo.

- Una funzione per effettuare un test sulla EventList per controllare se essa è vuota oppure no.

EventList: Funzioni di gestione

Page 18: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

EventList: Tipi e Parametri delle funzioni di gestione

Dopo aver determinato quali sono le funzioni che servono per operare sulla EventList vediamo quali sono i tipi e i parametri che le caratterizzano:

- Funzione “Sched”: è una funzione di tipo void che prende come parametro un Evento; inserisce tale evento nella EventList.

- Funzione “Get”: è una funzione che restituisce un oggetto di tipo Evento che rappresenta il primo evento nella EventList; non ha parametri.

- Funzione “RimuoviArrivi”: è una funzione di tipo void che non prende nessun parametro; si limita semplicemente a scorrere la EventList e a rimuovere l’evento di tipo Arrivo

- Funzione “Vuota”: è una funziona di tipo booleano che non prende parametri e ritorna true se la EventList è vuota e false altrimenti.

Page 19: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

event_list.cc#include "event_list.h"using namespace std;/* inserisce l'evento << ev >> nella Event List; l'inserimento e‘

ordinato in base a << ev->sched_time >> */void EventList::Sched(Evento* ev){ // cerca il punto dove inserire l'evento // iteratore su una lista che contiene elementi di tipo Evento

list<Evento*>::iterator it = ev_list.begin(); for (; (it != ev_list.end()) && ((*it)->sched_time <= ev-

>sched_time) ; ++it); ev_list.insert(it, ev);}

// restituisce l'evento di testa della event list, cioe' l'evento // con il tempo di schedulazione minore;// se la Event List e' vuota ritorna NULLEvento* EventList::Get(void){ if (ev_list.empty()) return NULL; Evento* ev = ev_list.front(); ev_list.pop_front(); return ev;}

Page 20: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

event_list.cc (2)

// Elimina dalla event list gli eventi di tipo arrivovoid EventList::RimuoviArrivi(void){ list<Evento*>::iterator it = ev_list.begin(); // scorro fino a quando non trovo un evento di //

tipo arrivowhile ((*it)->tipo != ARRIVO)

it++;ev_list.erase(it); // lo rimuovo

}

// Effettua un test per vedere lo stato della lista// Restituisce true se la lista è vuota, false altrimentibool EventList::Vuota(void){

if (ev_list.empty()) return true;

elsereturn false;

}

Page 21: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Inizializzazione del sistema e della EventList

La prima cosa che il simulatore deve fare quando viene mandato in esecuzione è chiamare la funzione per l’inizializzazione delle variabili di sistema e della Futur Event List.

Essa deve andare a settare a 0 i valori delle variabili necessarie per il calcolo delle prestazioni del sistema, come ad esempio: il CurrentTime della simulazione, il numero di pezzi completati, il numero di pezzi scartati, i BusyTime dei 2 servitori, ecc..

Viene ovviamente inizializzata a false la variabile booleana EndofSimulation sulla quale si basa il ciclo principale del simulatore

Inoltre deve essere accuratamente inizializzata la Event List, affichè la simulazione vada a buon fine, ed è quindi necessario:

- Schedulare un evento di tipo Arrivo per l’istante 0 per dare il via alla simulazione

- Schedulare un evento di tipo Sim_End (Fine simulazione) per l’istante di tempo in cui si intende far terminare la simulazione.

- Schedulare, nel caso si tratti già di simulazione a batch, un evento di tipo Fine-batch previsto per l’istante di tempo pari alla durata prevista dei batch

Nella slide successiva è riportato il codice della funzione Inizializza() del mio simulatore che esegue quanto appena descritto

Page 22: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Funzione di inizializzazione delle variabili del sistema

void inizializza(){

Evento *ev;Busy1Batch = 0.0;Busy2Batch = 0.0;NArrBatch = 0;Sc1Batch = 0;Sc2Batch = 0;ComplBatch = 0;Area = 0.0;AreaBatch = 0.0;Coda1 = 0;Coda2 = 0;NArr = 0;Scarti1 = 0;Scarti2 = 0;BTIME1 = 0.0;BTIME2 = 0.0;BLOCCO = 0.0;NBlocc = 0;bloccato = false;EndOfSimulation = false;OldTime=0.0;// crea un nuovo evento di tipo ARRIVO previsto per l'instante 0ev = new Evento(ARRIVO,0.0); // inseriscilo nella event listLista.Sched(ev);ev = new Evento(FINE_BATCH,BATCH_TIME);Lista.Sched(ev);// crea un nuovo evento di tipo SIM_END previsto per l'instante 45000ev = new Evento(SIM_END,45000.0); // inseriscilo nella event listLista.Sched(ev);CurrentTime=0.0;i=1;

}

Page 23: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Funzione per l’aggiornamento dei valori degli accumulatori necessari per la

valutazione degli indici di prestazione

void AccumulaStatistiche(){

double Interval;Interval = CurrentTime-OldTime;OldTime = CurrentTime;

Area = Area + (Coda1 + Coda2) * Interval;AreaBatch = AreaBatch + (Coda1 + Coda2) * Interval;

if (bloccato == false){

if (Coda1 > 0){

BTIME1 = BTIME1 + Interval; Busy1Batch = Busy1Batch + Interval;

}}else

BLOCCO = BLOCCO + Interval; if (Coda2 > 0){

BTIME2 = BTIME2 + Interval;Busy2Batch = Busy2Batch + Interval;

}}

Page 24: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Funzione per la gestione di un evento di tipo ARRIVO

void arrivo(){

Evento *ev;AccumulaStatistiche();

Coda1 = Coda1 + N;NArr = NArr + N;NArrBatch = NArrBatch + N;

#ifdef VERBOSE cout << "\nArrivo al tempo " << CurrentTime << "\t\t\t[Coda1: "

<< Coda1 << ", Coda2: " << Coda2 << "]";#endif

AT = TempiInterarrivo.Generate();ev = new Evento(ARRIVO,CurrentTime+AT);Lista.Sched(ev);if (Coda1 == N){

DT = TempoServizio1.Generate();// schedula partenza al tempo CurrentTime + T_SERV1ev = new Evento(PARTENZA1,CurrentTime+DT);Lista.Sched(ev);

}}

Page 25: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Funzione per la gestione di un evento di tipo PARTENZA DAL SERVITORE 1

void partenza1(){

Evento *ev;AccumulaStatistiche();

#ifdef VERBOSE cout << "\nPartenza da 1 al tempo " << CurrentTime << "\t\t[Coda1: " << Coda1 << ", Coda2: " <<

Coda2 << "]";#endif

p = ProbScarto.Generate();if (p <= P_SCART1){

Coda1--;Scarti1++;Sc1Batch++;#ifdef VERBOSE

cout << "\nPEZZO SCARTATO DA 1";#endif

}else{

if (Coda2 < QUE2){

Coda1--;Coda2++;if (Coda2 == 1){

// DT = "Genera un'instanza di una variabile casuale"; DT = TempoServizio2.Generate();

// schedula partenza al tempo CurrentTime+DTev = new Evento(PARTENZA2,CurrentTime+DT);Lista.Sched(ev);

}}else{

bloccato = true;NBlocc++;

#ifdef VERBOSE cout << "\nSISTEMA BLOCCATO " << "\t\t[Coda1: " << Coda1 << ", Coda2: " << Coda2 << "]";

#endif

return;}

}if (Coda1 > 0){

DT = TempoServizio1.Generate();// schedula partenza al tempo CurrentTime+DTev = new Evento(PARTENZA1,CurrentTime+DT);Lista.Sched(ev);

}}

Page 26: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Funzione per la gestione di un evento di tipo PARTENZA DAL SERVITORE 2

void partenza2(){

Evento *ev; AccumulaStatistiche();

Coda2--;ComplBatch ++;

#ifdef VERBOSE cout << "\nPartenza da 2 al tempo " << CurrentTime << "\t\t[Coda1: " << Coda1 << ",

Coda2: " << Coda2 << "]";#endif

p = ProbScarto.Generate();if (p <= P_SCART2){

Scarti2++;Sc2Batch++;#ifdef VERBOSE

cout << "\nPEZZO SCARTATO DA 2";#endif

}if (Coda2 > 0){ DT = TempoServizio2.Generate();

// schedula partenza al tempo CurrentTime+DTev = new Evento(PARTENZA2,CurrentTime+DT);Lista.Sched(ev);

}

if (bloccato == true){

Coda1--;Coda2++;bloccato = false;

#ifdef VERBOSE cout << "\nSISTEMA SBLOCCATO " << "\t\t[Coda1: " << Coda1 << ", Coda2: " <<

Coda2 << "]";#endif

if (Coda1 > 0){

DT = TempoServizio1.Generate();// schedula partenza al tempo CurrentTime+DTev = new Evento(PARTENZA1,CurrentTime+DT);Lista.Sched(ev);

}}

}

Page 27: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Funzione per la gestione di un evento di tipo FINE BATCH

void batch(){

cout << "\n ARRIVI NEL BATCH " << NArrBatch;cout << "\n SCARTI DA 1 NEL BATCH " << Sc1Batch;

double pezzi = (ComplBatch - Sc2Batch);double tot = (ComplBatch + Sc1Batch);

AccumulaStatistiche();u1 << (Busy1Batch/BATCH_TIME) << "\n";u2 << (Busy2Batch/BATCH_TIME) << "\n";thr << (pezzi/BATCH_TIME) << "\n";tdp << (AreaBatch / tot) << "\n";

cout << "\nUtilizzazione del servitore 1 nel batch " << i << ": " << (Busy1Batch/BATCH_TIME);

cout << "\nUtilizzazione del servitore 2 nel batch " << i << ": " << (Busy2Batch/BATCH_TIME);

Busy1Batch = 0;Busy2Batch = 0;NArrBatch = 0;Sc1Batch = 0;Sc2Batch = 0;AreaBatch = 0;ComplBatch = 0;i++;if (EndOfSimulation == false){

Evento *ev;ev = new Evento(FINE_BATCH,CurrentTime+BATCH_TIME);Lista.Sched(ev);

}}

Page 28: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Funzione per la stampa a video dei risultati dell’esperimento di simulazione

void Report(){

int NCompl = NArr - (Scarti1 + Scarti2); double thr = (Area/CurrentTime) / (Area / NArr);

cout << "\n\n----------------------------------------------------"; cout << "\nRisultati dell'esperimento di simulazione:\n"; cout << "\nDurata REALE della simulazione: " << CurrentTime; cout << "\nNumero di pezzi arrivati durante la simulazione: " << NArr; cout << "\nNumero di pezzi scartati dalla prima stazione: " << Scarti1; cout << "\nNumero di pezzi scartati dalla seconda stazione: " << Scarti2; cout << "\nNumero totale di pezzi scartati: " << Scarti1 + Scarti2; cout << "\nNumero di partenze (senza scarti): " << NCompl; cout << "\nTempo di occupazione della stazione 1: " << BTIME1; cout << "\nTempo di occupazione della stazione 2: " << BTIME2; cout << "\nTempo totale di blocco della stazione 1: " << BLOCCO; cout << "\nNumero di blocchi del servitore 1: " << NBlocc; if (NBlocc > 0)

cout << "\nDurata media di blocco del servitore 1: " << BLOCCO / NBlocc; cout << "\nUtilizzazione stazione 1: " << BTIME1 / CurrentTime; cout << "\nUtilizzazione stazione 2: " << BTIME2 / CurrentTime; cout << "\nTempo medio di servizio della stazione 1: " << BTIME1/NArr; cout << "\nTempo medio di servizio della stazione 2: " << BTIME2/(NArr-

Scarti1); cout << "\nThroughput (senza scarti): " << NCompl / CurrentTime; cout << "\nFlusso di scarto: " << (Scarti1 + Scarti2) / CurrentTime; cout << "\nThroughput (con scarti): " << (NCompl / CurrentTime) + ((Scarti1 +

Scarti2) / CurrentTime); cout << "\nThroughput (con scarti) calcolato con la legge del tempo di attesa:

" << thr; cout << "\nFrequenza degli arrivi: " << NArr / CurrentTime; // cout << "\nValore dell'integrale 'Area': " << Area; cout << "\nNumero medio di pezzi nel sistema: " << Area/CurrentTime; cout << "\nTempo medio di permanenza nel sistema: " << Area / NArr; cout << "\n----------------------------------------------------"; }

Page 29: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Funzione Clock() del simulatore

La funzione clock() rappresenta il cuore del simulatore, e viene richiamata dal main del programma all’interno di un ciclo do-while fino a quando non si è raggiunta la fine della simulazione.

Essa quando viene richiamata preleva il primo evento presente nella Future Event List tramite il metodo Get e aggiorna il valore della variabile CurrentTime, che rappresenta l’istante attuale della simulazione, impostandola al valore dell’istante di tempo associato all’evento appena estratto dalla FEL.

A questo punto effettua un controllo su che tipo di evento è quello appena estratto e chiama di conseguenza l’opportuna funzione di gestione.

Nel caso si tratti dell’evento di fine simulazione, SIM_END, viene chiamata la funzione che si occupa di togliere l’evento di tipo ARRIVO dalla FEL fermando cosi i futuri arrivi, e viene anche impostato a true il valore della variabile booleana EndOfSimulation che gestisce la fine della simulazione.

Il codice della funzione Clock() è nella slide seguente

Page 30: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Funzione che gestisce il ciclo principale del simulatore

void Clock() {

Evento *ev;// preleva l'evento in cima alla event listev = Lista.Get();// aggiorna il tempo corrente assegnandogli il tempo// di schedulazione dell'evento in cima alla event listCurrentTime = ev->sched_time;

switch (ev->tipo){

case ARRIVO: arrivo(); break;

case PARTENZA1: partenza1();break;

case PARTENZA2: partenza2();break;

case FINE_BATCH: batch();break;

case SIM_END: #ifdef VERBOSEcout << "\nEVENTO DI FINE SIMULAZIONE (Rimuovo gli

arrivi)";#endif

Lista.RimuoviArrivi();EndOfSimulation = true;

break;}// rilascia la memoria allocata all'evento appena elaboratodelete ev;

}

Page 31: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Funzione Main del simulatoremain(int argc, char* argv[]){ int j; long seed;

if (argc != 2) usage(argv[0]);

NRun = atoi(argv[1]); if (NRun == 0) { printf("ERRORE: Il parametro passato deve essere un intero.\n"); usage(argv[0]); } u1.open("utilizzazione1.txt"); u2.open("utilizzazione2.txt"); thr.open("throughput.txt"); tdp.open("tempPerm.txt");

for (j = 1; j <= NRun; j++) { cout << "\nInserisci il seme per la generazione dei numeri casuali: "; cin >> seed; seme.set(seed); inizializza(); do Clock(); while (EndOfSimulation == false || Lista.Vuota() == false);

Report(); }

u1.close(); u2.close(); thr.close(); tdp.close(); cout << "\nFINE SIMULAZIONE\n" << flush;}

Page 32: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Funzionamento del simulatore

Vediamo nella pratica come far funzionare il simulatore:

- Compilazione tramite il comando “make” che recupera le informazioni dal makefile

- Esecuzione: per mandarlo in esecuzione basta lanciarlo passandogli come argomento da linea di comando un intero che rappresenta il numero di run che deve eseguire.

Screenshot di esempio

Page 33: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Funzionamento del simulatore

Se non viene lanciato nel modo giusto viene segnalato all’utente l’errore, come dimostra lo screenshot sottostante:

- Nel primo caso il simulatore viene invocato senza parametri e quindi mostra a video le istruzione corrette.

- Nel secondo caso il parametro che gli viene passato non è un valore intero e quindi non è accettabile dovendo rappresentare il numero di run da eseguire. Viene quindi segnalato il tipo di errore e vengono nuovamente mostrate le istruzioni corrette.

Page 34: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Funzionamento del simulatore

Se il programma viene lanciato correttamente, inizia la simulazione e vengono stampate a video le informazioni dei pezzi in arrivo e in partenza. Alla fine di ogni run vengono stampati a video, oltre che su files per la successiva analisi, i risultati ottenuti.

Screenshot di esempio

Page 35: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Nell’analisi dell’output ho preso in considerazione 4 grandezze:

- Throughput- Utilizzazione servitore 1- Utilizzazione servitore 2- Tempo medio di permanenza

Il simulatore in C++ che ho scritto salva quindi i valori di tali grandezze su 4 files di testo, rispettivamente

Throughput.txtUtilizzazione1.txtUtilizzazione2.txtTempPerm.txt

I valori contenuti in tali files devono a loro volta essere esportati su un foglio di calcolo Excel, dato come modello, per effettuarne l’analisi.

Esportazione dei risultati

Page 36: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Esportazione dei risultatisu foglio di calcolo Excel

Il simulatore scrive i risultati della simulazione su diversi file di testo, uno per ogni grandezza che si vuole prendere in considerazione e studiare.

Negli screenshot qui di fianco è riportato il contenuto del file

Throughput.txt che contiene tutti i valori calcolati dal simulatore per tale grandezza. In questo caso particolare

i valori si riferiscono alla simulazione a batch dove vengono eseguiti 10 Run da 15 batch ciascuno per un totale qundi di 150 valori che verrano poi esportati su un foglio di calcolo Excel.

Page 37: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Esportazione dei risultatisu foglio di calcolo Excel

Siccome i valori da esportare dai 4 files di output del simulatore erano molti (con 10 run da 15 batch ciascuno sono 150 valori per ognuna delle grandezze considerate) mi sono scritto un’applicazione ad hoc in Visual Basic .NET, che ho chiamato SimAnalisi.exe, che esegue tale operazione in modo completamente automatico.

L’applicazione va a leggere i files di testo, ne estrae i valori e li inserisce nelle giuste celle del file Analisi.xls dato come modello, salvando poi per ogni grandezza il relativo file .xls con i valori inseriti.

Dall’esecuzione della mia applicazione ottengo quindi i 4 file Excel:

Throughput.xls

Utilizzazione1.xls

Utilizzazione2.xls

TempPerm.xls

Una volta terminata la simulazione lanciando la mia applicazione SimAnalisi.exe ottengo la creazione di un foglio Excel per ogni grandezza con i valori automaticamente inseriti

Page 38: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Nelle 2 slide seguenti ho riportato il codice del modulo Visual Basic.NET che ho scritto per realizzare l’applicazione per il trasferimento automatico dei dati dai file di testo generati dal simulatore ai fogli di calcolo Excel per lo studio delle grandezze di interesse.

Tale applicazione prende il file Analisi.xls dato come modello, lo apre e inserisce nelle apposite celle i dati relative alle 4 grandezze e poi salva ogni volta il file con il nome della grandezza .xls.

In questo modo una volta effettuati i vari run dell’esperimento di simulazione basta lanciare l’applicazione, che si deve trovare nellla stessa directory dei file di testo output del simulatore, per trovarsi i fogli excel automaticamente compilati (come si vede nello screenshot della slide precedente).

Nella fase di esportazione ho dovuto effettuare la sostituzione dei caratteri “.” (punto) con i caratteri “,” (virgola) in quanto utilizzo la versione di Excel in italiano. Questo è stato fatto come si vede dal codice con la funzione Replace(".", ",")

Modulo Visual Basic.NET per l’esportazione dei risultati

Page 39: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Imports System.IOModule Module1

Sub Main() Dim appExcel As New Excel.Application Dim wbookExcel As Excel.Workbook Dim foglioExc As Excel.Worksheet Dim lastCol As Integer = 16 Dim firstCol As Integer = 2 Dim firstRow As Integer = 12 Dim lastRow As Integer = 21 Dim n As Integer

Dim objReader As StreamReader Dim i As Integer appExcel.Visible = True appExcel.Workbooks.Add()

'Utilizzazione del servitore 1 wbookExcel = appExcel.Workbooks.Open(CurDir() +

"\Analisi.xls") foglioExc = appExcel.Worksheets("Tabella2") objReader = New StreamReader("utilizzazione1.txt") For i = firstRow To lastRow For n = firstCol To lastCol foglioExc.Cells(i, n).Value =

objReader.ReadLine().Replace(".", ",") Next n Next i foglioExc.SaveAs(CurDir() + "\Utilizzazione1.xls")

Modulo Visual Basic.NET per l’esportazione dei risultati

Page 40: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

'Utilizzazione del servitore 2wbookExcel = appExcel.Workbooks.Open(CurDir() + "\Analisi.xls")foglioExc = appExcel.Worksheets("Tabella2")objReader = New StreamReader("utilizzazione2.txt")For i = firstRow To lastRow For n = firstCol To lastCol foglioExc.Cells(i, n).Value = objReader.ReadLine().Replace(".", ",") Next nNext i foglioExc.SaveAs(CurDir() + "\Utilizzazione2.xls")

'Throughput del sistema senza scartiwbookExcel = appExcel.Workbooks.Open(CurDir() + "\Analisi.xls")foglioExc = appExcel.Worksheets("Tabella2")objReader = New StreamReader("throughput.txt")For i = firstRow To lastRow For n = firstCol To lastCol foglioExc.Cells(i, n).Value = objReader.ReadLine().Replace(".", ",") Next nNext ifoglioExc.SaveAs(CurDir() + "\Throughput.xls")

'Throughput del sistema senza scartiwbookExcel = appExcel.Workbooks.Open(CurDir() + "\Analisi.xls")foglioExc = appExcel.Worksheets("Tabella2")objReader = New StreamReader("tempPerm.txt")For i = firstRow To lastRow For n = firstCol To lastCol foglioExc.Cells(i, n).Value = objReader.ReadLine().Replace(".", ",") Next nNext ifoglioExc.SaveAs(CurDir() + "\TempPerm.xls")

appExcel.Quit()End Sub

End Module

Page 41: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Analisi dell’outputdella simulazione

La simulazione di un modello stocastico permette di ricavare misure (lunghezza media della coda, tempo medio di attraversamento del sistema, throughput, ...) che sono esse stesse variabili casuali. Per questo motivo non ha senso eseguire una sola simulazione (seguendo un unico sample path) e da questa trarre delle conclusioni sulle prestazioni del sistema. Occorre invece eseguire molte volte la simulazione, utilizzando diverse sequenze di numeri casuali, in modo da ottenere molti sample path, e di conseguenza molti valori per le misure di interesse (istanze delle corrispondenti variabili casuali).

INTRODUZIONE TEORICA

PARTE TERZA

Page 42: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Il tipo di risposte che si possono voler ottenere dalla simulazione di un modello di sistema possono riguardare il comportamento su un periodo di tempo prefissato, a partire da un ben preciso stato iniziale

Es: lunghezza media della coda al drive-in nelle prime due ore dall’apertura

oppure il comportamento “tipico” del sistema, se osservato per un periodo molto lungo (tendente all’infinito)

Es: il tempo medio impiegato a produrre un’automobile in una fabrica automatizzata (valore “tipico” di tale indice, quando il sistema sia “a regime”, quindi non in situazioni particolari come subito dopo un periodo di fermo macchine per manutenzione)

Il primo tipo di analisi è detta “in transitorio”, il secondo tipo di analisi è detta “a regime”. Nel primo caso lo stato iniziale e la durata del periodo di osservazione fanno parte dei dati del problema da studiare, nel secondo caso questi due parametri della simulazione devono essere scelti opportunamente da chi conduce l’esperimento di simulazione.

Analisi dell’outputdella simulazione

Analisi in Transitorio VS Analisi a Regime

Page 43: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Dimensione del campione e accuratezza del risultato

Se si desidera ottenere un risultato con una certa accuratezza può essere necessario effettuare più esperimenti di simulazione: come stabilire quanti?

Si inizia con un numero R0 di repliche. Se l’accuratezza non è stata raggiunta si cerca di stimare quante ulteriori repliche sono necessarie per raggiungere l’accuratezza.

Supponiamo di voler raggiungere una accuratezza di ±ε , cioè tα/2,R-1 SR

≤ ε √R

conoscendo il valore S0 per R = R0 si può tentare una stima di quanti run aggiuntivi sono necessari:

R ≥ (tα/2,R-1 S0/ ε)2

poiché R compare sia a sinistra che a destra della disequazione (numero di gradi di libertà della t), operiamo una sostituzione di tα/2,R-1 con zα/2 (dato che tα/2,R-1 ≥ zα/2, R dovra’ essere ≥ (zα/2 S0/ ε)2 )

Il valore iniziale di repliche (Run) che ho adottato è 15.

Page 44: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Un primo esempio di simulazione con campioni

indipendentiHo eseguito un primo esperimento di simulazione “di prova”

eseguendo 15 run indipendenti scegliendo i seguenti valori come caratterizzanti del sistema software realizzato:

#define N 3 //numero di pezzi in arrivo/* probabilità (in percentuale) che il pezzo sia scartato dalla

stazione1 */#define P_SCART1 15/* probabilità (in percentuale) che il pezzo sia scartato dalla

stazione2 */#define P_SCART2 10//dimensione della coda del secondo servitore#define QUE2 10 #define SIM_TIME 45000.0 // Durata Simulazione

DUniform ProbScarto(0.0,99.0,&seme);Exponential TempoServizio1(0.25,&seme);Exponential TempoServizio2(0.30,&seme);Exponential TempiInterarrivo(0.08,&seme);

Ho ottenuto i risultati illustrati di seguito

Page 45: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Come ho proceduto

Nella prima colonna della tabella che ho realizzato vengono riportati i risultati ottenuti nei vari run di simulazione per le grandezze in questione.

Calcolo poi il valor medio tra essi (riportato più in basso nella stessa colonna) applicando la formula:

Valore medio

Ho calcolato per ogni risultato della simulazione la differenza rispetto al valor medio, riportata nella seconda colonna, e ne ho fatto il quadrato, riportato nella terza colonna. A questo punto ho fatto la somma dei quadrati delle differenze e l’ho divisa per il numero dei run eseguiti moltiplicato per tale numero -1. Quanto spiegato ora altro non è che l’applicazione della formula:

Page 46: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Come ho proceduto (2)A questo punto ho estratto la radice del valore

calcolato:

E ho calcolato un intervallo di confidenza al 95% moltiplicando tale valore per il valore della distribuzione t di student tα/2,n-1 e sommandolo e sottraendolo al valor medio calcolato in precedenza.

Nell’esempio con confidenza al 95% e 15 run eseguite il valore è quello della colonna 0.975 (α/2 = (100-95)/2 % = 2,5%) 14 gradi di libertà .

L’interpretazione è che il valore atteso si sta cercando di stimare è incluso nell’intervallo di confidenza con una probabilità del 100(1 – α)%.

Page 47: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

0,1822742260,181421774

INTERVALLO DI CONFIDENZA

ACCURATEZZA0,000426226

STUDENT2,145

VARIANZA0,000198707

somma delle

differenze valor medio

3,94843E-088,29171E-06 0,181848

7,33326E-060,0027080,17914

1,33225E-050,003650,178198

2,8224E-06-0,001680,183528

2,23204E-06-0,0014940,183342

5,29E-102,3E-050,181825

2,17858E-06-0,0014760,183324

6,56384E-060,0025620,179286

6,46176E-06-0,0025420,18439

5,53536E-070,0007440,181104

1,28522E-050,0035850,178263

9,72816E-060,0031190,178729

2,503E-05-0,0050030,186851

1,87964E-06-0,0013710,183219

3,40772E-06-0,0018460,183694

9,58441E-07-0,0009790,182827

quadrato differenzavalor medio - valoreRisultato ottenuto

Tabella dei risultati dell’esperimento di simulazione con 15 run indipendenti

senza batch: Throughput

Page 48: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Tabella dei risultati dell’esperimento di simulazione con 15 run indipendenti senza batch: utilizzazione servitore 1

0,9549920650,950742335

INTERVALLO DI CONFIDENZA

ACCURATEZZA0,002124865

STUDENT2,145

VARIANZA0,000990613

somma delle differenze valor medio

9,81314E-070,000206076 0,9528672

0,0001582610,01258020,940287

0,0008413020,02900520,923862

4,27662E-08-0,00020680,953074

3,20786E-05-0,00566380,958531

2,33888E-050,00483620,948031

5,1984E-10-2,28E-050,95289

0,0003123770,01767420,935193

0,000970497-0,03115280,98402

0,000184465-0,01358180,966449

0,0005860370,02420820,928659

3,62548E-050,00602120,946846

0,000501975-0,02240480,975272

3,27047E-05-0,00571880,958586

7,49748E-05-0,00865880,961526

4,78145E-05-0,00691480,959782

quadrato differenzavalor medio - valoreRisultato ottenuto

Page 49: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

0,6781245070,674940693

INTERVALLO DI CONFIDENZA

ACCURATEZZA0,001591907

STUDENT2,145

VARIANZA0,000742148

somma delle

differenze valor medio

5,50783E-070,000115664 0,6765326

3,35519E-05-0,00579240,682325

5,00358E-050,00707360,669459

0,000241069-0,01552640,692059

2,98737E-06-0,00172840,678261

2,51462E-050,00501460,671518

4,55976E-050,00675260,66978

0,000168730,01298960,663543

8,33094E-05-0,00912740,68566

6,37762E-070,00079860,675734

0,0001612040,01269660,663836

0,0002008060,01417060,662362

0,00028674-0,01693340,693466

3,94058E-05-0,00627740,68281

0,000173512-0,01317240,689705

8,21126E-050,00906160,667471

quadrato differenzavalor medio - valoreRisultato ottenuto

Tabella dei risultati dell’esperimento di simulazione con 15 run indipendenti senza batch: utilizzazione servitore 2

Page 50: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

211,0541033176,19443

INTERVALLO DI CONFIDENZA

ACCURATEZZA17,42983665

STUDENT2,145

VARIANZA8,125797971

somma delle

differenze valor medio

66,0285926713866,00446 193,6242667

4382,60770866,20126667127,423

8003,31823489,46126667104,163

411,0648117-20,27473333213,899

16,6322594,078266667189,546

2651,76248951,49526667142,129

1482,42453838,50226667155,122

4451,99431566,72326667126,901

30475,63922-174,5727333368,197

4,716425671-2,171733333195,796

6389,96660279,93726667113,687

4600,67375967,82826667125,796

46515,15925-215,6737333409,298

430,698077320,75326667172,871

629,772409125,09526667168,529

9483,396751-97,38273333291,007

quadrato differenzavalor medio - valoreRisultato ottenuto

Tabella dei risultati dell’esperimento di simulazione con 15 run indipendenti

senza batch:Tempo di permanenza nel sistema

Page 51: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Dall’analisi effettuata si ottiene un valore di accuratezza dell’utilizzazione del servitore 1 pari

a 0,002124. Possiamo stabilire che questo risultato non ci soddisfa e che vogliamo ottenere un’accuratezza migliore.

Fissiamo ad esempio l’accuratezza a 0,001 quindi e calcoliamo quanti run sarebbero necessari per ottenerla.

(1,96)2 * (15 * (0,0009906 2)) / 0,001 2 =

= 3,8416 * (15 *(0,0009906 2)) / 0,000001 =

= 56,54

Se si vuole migliorare l’accuratezza dell’utilizzazione del servitore 1 e scendere dall’attuale 0,002124 a 0,001 si deve condurre l’esperimento di simulazione eseguendo 57 RUN.

Migliorare l’accuratezza dell’utilizzazione del servitore 1

Page 52: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Migliorare l’accuratezza del tempo medio di permanenza nel sistema

Dall’analisi effettuata si ottiene un valore di accuratezza del tempo medio di permanenza di 17,42.

Questo, tradotto in percentuale, corrisponde ad un errore del

17,42 : 193,62 = X : 100

circa 9%Possiamo stabilire che questo risultato non ci soddisfa

e che vogliamo ottenere un’accuratezza migliore e quindi un errore inferiore.

Fissiamo ad esempio l’accuratezza a 8, quindi circa la metà della precedente e calcoliamo quanti run sarebbero necessari per ottenerla.

(1,96)2 * (15 * (8,1257 2)) / 82 =

= 3,8416 * (15 *(8,1257 2)) / 64 =

= 59,44

Se voglio migliorare l’accuratezza del tempo medio di permanenza e passare dell’attuale 17,42 a circa la metà, 8 si deve condurre l’esperimento di simulazione eseguendo 60 RUN.

L’errore percentuale scende così intorno al 4%:

8 : 193,62 = X : 100 e = 4,13%

Page 53: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Considerazioni sull’accuratezza

Eseguendo l’esperimento di simulazione con 15 batch indipendenti si è ottenuta una accuratezza soddisfacente per il throughput e per l’utilizzazione del servitore 2, mentre per il tempo medio di permanenza e per l’utilizzazione del servitore 1 si è supposto di volere una accuratezza migliore e si sono quindi eseguiti i calcoli visti precedentemente.

Per ottenere il valore di accuratezza desiderato per il tempo medio di permanenza è necessario eseguire 60 RUN mentre per l’accuratezza dell’utilizzazione del servitore 1, come visto, ne sono necessari 57.

In questo caso si prende in considerazione il numero maggiore di RUN, quindi 60, ed eseguendole si avrà l’accuratezza desiderata per tutte le grandezze del sistema misurate.

Page 54: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Risultati prima prova di simulazione

Nelle slide seguenti riporto le immagini dei risultati ottenuti con questa prima prova di simulazione.

Si tratta di fogli di calcolo Excel dove vengono riportati i risultati degli esperimenti di simulazione e vengono effettuati in automatico, tramite formule impostate, i calcoli di interesse.

Tali risultati si riferiscono però alla seconda fase della simulazione, ovvero all’esperimento di simulazione a batch, che però non ho ancora introdotto. Li inserisco ora per concludere il discorso su questo primo esperimento di simulazione “di prova”.

La simulazione a batch verrà introdotta e descritta in dettaglio più avanti in questa relazione.

Di seguito vengono poi anche inseriti i grafici di alcune delle grandezze ottenuti sempre in automatico con il foglio di calcolo Excel dopo l’immissione dei valori ottenuti dalla simulazione.

Dopo questa primo esperimento di simulazione ho cambiato i valori delle distribuzioni dei tempi di servizio e di interarrivo e ho eseguito una nuova simulazione che descrivo nel dettaglio.

Page 55: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Page 56: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Page 57: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Page 58: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Page 59: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Grafici dell’andamento delle utilizzazioni del servitore 1 e del servitore 2

Effetto della cancellazione dei primi batch

0,8400000

0,8600000

0,8800000

0,9000000

0,9200000

0,9400000

0,9600000

0,9800000

1,0000000

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

num.batch

med

ia c

um

ula

tiva

Serie1

Serie2

Serie3

Serie4

Effetto della cancellazione dei primi batch

0,6000000

0,6100000

0,6200000

0,6300000

0,6400000

0,6500000

0,6600000

0,6700000

0,6800000

0,6900000

0,7000000

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

num.batch

med

ia c

um

ula

tiva

Serie1

Serie2

Serie3

Serie4

Page 60: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Modifica ai parametri di simulazione

A posteriori dell’analisi di questa prima simulazione ho deciso di cambiare le distribuzioni che caratterizzano il sistema. In particolare il tempo medio di permanenza con questi primi valori raggiungeva un valore troppo elevato. Quindi il fatto che i pezzi rimangano molto tempo all’interno del sistema significa anche che il numero medio di pezzi all’interno del sistema può assumere valori grandi, visto che comunque il tasso di arrivo è costante.

Questo fatto può portare dei problemi quando si fa ad effettuare la simulazione della rete di Petri equivalente al sistema con il tool GreatSPN.

Per questo motivo, oltre al fatto che volevo ottenere un valore del tempo di permanenza più realistico, ho modificato le distribuzioni come segue:

DUniform ProbScarto(0.0,99.0,&seme);Exponential TempoServizio1(0.29,&seme);Exponential TempoServizio2(0.32,&seme);Exponential TempiInterarrivo(0.08,&seme);

Il numero di pezzi in arrivo, la durata della simulazione e le percentuali di scarto invece le ho lasciate ai valori indicati precedentemente.

Page 61: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Simulazione con i nuovi valori delle distribuzioni

Praticamente ho proceduto cosi:- ho fatto girare il simulatore vecchio, senza batch, eseguendo 5 Run di simulazione e ho calcolato gli intervalli e l’accuratezza per le 4 grandezze in questione.- ho fatto girare il simulatore vecchio, senza batch, eseguendo 15 Run di simulazione e ho calcolato gli intervalli e l’accuratezza per le 4 grandezze in questione.- ho confrontato i risultati evidenziando e facendo le opportune considerazioni sulle differenze di accuratezza ottenute sui 2 campioni.- ho supposto di voler una determinata accuratezza e quindi fatto i relativi calcoli del numero di run necessariper ottenerla (anche se l'accuratezza con 15 run era già buona per tutte le grandezze).- ho effettuato una simulazione a batch del sistema utilizzando la versione finale del simulatore, che prevede appunto di eseguire i run di simulazione divisi in diversi bath.- ho importato i valori ottenuti col simulatore sul foglio di calcolo Excel effettuandone lo studio- ho riprodotto il sistema come Rete di Petri grazie al tool GreatSPN ed effettuato la simulazione- ho eseguito il calcolo dei valori delle grandezze di interesse anche in questo caso; alcune ottenute come risultato diretto della simulazione altre invece da calcolare con le opportune formule.- ho eseguito il confronto tra i valori ottenuti con le 2 metodologie di simulazione.

Page 62: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Nuova simulazione con5 Run

Per eseguire questa prima simulazione ho utilizzato la prima versione del simulatore, quella che non esegue i batch. L’ho fatto girare 5 volte e ho preso i risultati, che ad ogni run il simulatore scrive su un file di testo, e li ho esportati su un foglio di calcolo Excel preimpostato dove ho calcolato il valor medio dei campioni ottenuti, la varianza, l’accuratezza e quindi l’intervallo di confidenza.

Il procedimento seguito è lo stesso illustrato in precedenza (slide 45 e 46).

Page 63: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Tavola della distribuzione StudentSiccome gli intervalli di confidenza che calcolo sono al 95% (α/2 = (100-95)/2 % = 2,5%) devo prendere il valore della student sulla colonna dello 0.975 e per quanto riguarda la riga dei gradi di libertà della distribuzione (df = degree of freedon) devo prendere il valore del numero di run – 1. Avendo eseguito 5 run devo prendere il valore della riga 4. Il valore ottenuto l’ho colorato e cerchiato nell’immagine sottostante: tα/2,n-1

Page 64: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

0,1882620,17969

INTERVALLO DI CONFIDENZA

ACCURATEZZA0,004286

STUDENT2,776

VARIANZA0,001543986

somma delle

differenze valor medio

2,38389E-064,76778E-05 0,1839764

3,59568E-050,00599640,17798

5,29644E-060,00230140,181675

8,92269E-07-0,00094460,184921

1,54418E-05-0,00392960,187906

1,1721E-05-0,00342360,1874

quadrato differenza

valor medio - valore

Risultato ottenuto

Tabella dei risultati dell’esperimento di simulazione con 5 run

indipendenti senza batch: Throughput

Page 65: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Tabella dei risultati dell’esperimento di simulazione con 5 run

indipendenti senza batch:Utilizzazione Servitore1

0,857350,81027

INTERVALLO DI CONFIDENZA

ACCURATEZZA0,02354

STUDENT2,776

VARIANZA0,008480292

somma delle

differenze valor medio

7,19154E-050,001438307 0,8338184

0,0013213520,03635040,797468

7,877E-06-0,00280660,836625

2,78425E-05-0,00527660,839095

0,000304593-0,01745260,851271

0,000116956-0,01081460,844633

quadrato differenza

valor medio - valore

Risultato ottenuto

Page 66: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Tabella dei risultati dell’esperimento di simulazione con 5 run

indipendenti senza batch:Utilizzazione Servitore2

0,656160,623329

INTERVALLO DI CONFIDENZA

ACCURATEZZA0,016416

STUDENT2,776

VARIANZA0,00591352

somma delle

differenze valor medio

3,49697E-050,000699394 0,6397454

0,0003283850,01812140,621624

0,0004868380,02206440,617681

1,55047E-05-0,00393760,643683

0,000288545-0,01698660,656732

0,000371009-0,01926160,659007

quadrato

differenzavalor medio -

valoreRisultato

ottenuto

Page 67: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Tabella dei risultati dell’esperimento di simulazione con 5 run

indipendenti senza batch:Tempo medio di permanenza

53,5215640,728

INTERVALLO DI CONFIDENZA

ACCURATEZZA6,39678

STUDENT2,776

VARIANZA2,30431936

somma delle

differenze valor medio

5,309887713106,1977543 47,12478

89,315352469,4506837,6741

2,7359806461,6540845,4707

6,810116544-2,6096249,7344

19,23980314-4,3863251,5111

16,88240179-4,1088251,2336

quadrato

differenzavalor medio -

valoreRisultato

ottenuto

Page 68: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Nuova simulazione con 15 Run

A questo punto ho effettuato un nuovo esperimento di simulazione utilizzando lo stesso simulatore, senza batch, ma ampliando il campione ed eseguendo in questo caso 15 run contro le sole 5 eseguite nell’esperimento precedente.

Ho rieseguito le stesse operazioni fatte in precedenza arrivando anche in questo secondo caso al calcolo di valor medio, varianza, intervallo di confidenza e accuratezza delle 4 grandezze di interesse.

Nelle slide seguenti vengono riportate le tabelle con i risultati ottenuti in questo esperimento costituito dall’esecuzione di 15 run e viene fatto un confronto con quelli ottenuti in precedenza con l’esperimento dei soli 5 run.

Page 69: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Tavola della distribuzione StudentAvendo ampliando il numero di campioni su cui si basa l’esperimento da 5 a 15 occorre prendere in considerazione il nuovo valore della distribuzione T di Student. Ponendo sempre: 95% (α/2 = (100-95)/2 % = 2,5%) devo prendere sempre il valore della colonna 0.975 però questa volta il numero di gradi di libertà sarà 15 – 1 = 14.

Nello screenshot sottostante ho evidenziato tale valore, utilizzato per eseguire i calcoli.

Page 70: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Tabella dei risultati dell’esperimento di simulazione con 15 run indipendenti senza

batch:Throughput

0,182801460,18161654

INTERVALLO DI CONFIDENZA

ACCURATEZZA0,00059246

STUDENT2,145

VARIANZA0,000276205

somma delle differenze valor medio

7,62892E-081,60207E-05 0,182209

3,40402E-06-0,0018450,184054

6,48025E-070,0008050,181404

2,79893E-06-0,0016730,183882

7,4529E-08-0,0002730,182482

5,79121E-07-0,0007610,18297

1,57252E-060,0012540,180955

5,79121E-07-0,0007610,18297

1,57252E-060,0012540,180955

5,79121E-07-0,0007610,18297

3,74911E-050,0061230,176086

1,27916E-06-0,0011310,18334

1,57252E-060,0012540,180955

1,27916E-06-0,0011310,18334

1,4352E-060,0011980,181011

1,26167E-05-0,0035520,185761

quadrato

differenzavalor medio -

valoreRisultato

ottenuto

Page 71: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Tabella dei risultati dell’esperimento di simulazione con 15 run indipendenti senza

batch:Utilizzazione Servitore 1

0,8276094270,823142707

INTERVALLO DI CONFIDENZA

ACCURATEZZA0,00223336

STUDENT2,145

VARIANZA0,001041194

somma delle

differenze valor medio

1,08408E-060,000227658 0,825376067

1,96078E-050,0044280670,820948

0,0001564770,0125090670,812867

2,31945E-050,0048160670,82056

8,99071E-05-0,0094819330,834858

6,7403E-05-0,0082099330,833586

5,12751E-070,0007160670,82466

6,7403E-05-0,0082099330,833586

5,12751E-070,0007160670,82466

6,7403E-05-0,0082099330,833586

0,001740230,0417160670,78366

9,26971E-05-0,0096279330,835004

5,12751E-070,0007160670,82466

9,26971E-05-0,0096279330,835004

4,72657E-060,0021740670,823202

0,00020805-0,0144239330,8398

quadrato differenzavalor medio - valoreRisultato ottenuto

Page 72: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Tabella dei risultati dell’esperimento di simulazione con 15 run indipendenti

senza batch:Utilizzazione Servitore 2

0,6361322840,63159025

INTERVALLO DI CONFIDENZA

ACCURATEZZA0,002271017

STUDENT2,145

VARIANZA0,001058749

somma delle

differenze valor medio

1,12095E-060,000235399 0,633861267

5,78776E-05-0,0076077330,641469

0,000109783-0,0104777330,644339

3,93472E-05-0,0062727330,640134

3,77152E-050,0061412670,627720

1,87763E-060,0013702670,632491

4,58501E-050,0067712670,627090

1,87763E-060,0013702670,632491

4,43725E-050,0066612670,627200

1,87763E-060,0013702670,632491

0,0004316530,0207762670,613085

8,68324E-06-0,0029467330,636808

4,57147E-050,0067612670,627100

8,68324E-06-0,0029467330,636808

5,84725E-05-0,0076467330,641508

0,000177522-0,0133237330,647185

quadrato

differenzavalor medio -

valoreRisultato

ottenuto

Page 73: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Tabella dei risultati dell’esperimento di simulazione con 15 run indipendenti senza

batch:Tempo medio di permanenza nel sistema

47,5639838745,61865613

INTERVALLO DI CONFIDENZA

ACCURATEZZA0,972663871

STUDENT2,145

VARIANZA0,45345635

somma delle differenze valor medio

0,20562266243,18075893 46,59132

27,88030083-5,2801851,8715

48,082020176,9341239,6572

2,308515584-1,5193848,1107

71,60002842-8,4616855,0530

1,649991631,2845245,3068

10,58057773-3,2527849,8441

1,649991631,2845245,3068

10,58057773-3,2527849,8441

1,649991631,2845245,3068

102,631487710,1307236,4606

16,179862664,0224242,5689

10,58057773-3,2527849,8441

16,179862664,0224242,5689

0,001029126-0,0320846,6234

15,3004581-3,9115850,5029

quadrato

differenzavalor medio -

valoreRisultato

ottenuto

Page 74: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Differenza di accuratezza tra i 2 esperimenti di simulazione a 5 e 15 run

0,0042865

0,000592415

AccuratezzaNumero di run

Throughput

0,023545

0,0022333615

AccuratezzaNumero di run

Utilizzazione Servitore 1

0,0164165

0,00227101715

AccuratezzaNumero di run

Utilizzazione Servitore 2

6,396785

0,97266387115

AccuratezzaNumero di run

Tempo medio di permanenza

Page 75: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Differenza in termini dierrore percentuale

2,36 %5

0,33 %15

AccuratezzaNumero di run

Throughput

2,85 %5

0,27 %15

AccuratezzaNumero di run

Utilizzazione Servitore 1

2,59 %5

0,36 %15

AccuratezzaNumero di run

Utilizzazione Servitore 2

13,73 %5

2,08 %15

AccuratezzaNumero di run

Tempo medio di permanenza

Page 76: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Il problema deltransitorio iniziale

Gli esperimenti di simulazione del sistema svolti finora consistevano nell’esecuzione di diversi run indipendenti dove ogni volta il sistema partiva dallo stato iniziale vuoto e la raccolta dei dati veniva effettuata a partire dall’inizio del tempo di osservazione senza scartarne alcuno.

Un’analisi di questo tipo è detta “in transitorio” perché tiene conto anche di quei valori iniziali in cui il sistema non ha ancora iniziato a lavorare a regime e deve cioè ancora stabilizzarsi. Questo è proprio dovuto al fatto che le code sono inizialmente vuote.

Questo è un fenomeno di cui occorre tenere conto perché può influenzare i risultati ottenuti.

Nel nostro caso, si vuole effettuare un’analisi del sistema a regime e studiare quindi il suo comportamento in una situazione “normale” di funzionamento.

L’analisi in transitorio invece, siccome parte sempre dalla situazione di sistema vuoto, può essere utilizzata per effettuare lo studio del comportamento del sistema in situazioni particolari come può essere la ripresa del funzionamento in seguito ad un guasto.

Page 77: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Simulazione a batch

Per superare il problema del transitorio iniziale ed effettuare un’analisi che può essere significativa del comportamento a regime del sistema si è passati da una simulazione basata sulla raccolta di campioni indipendenti ottenuti con l’esecuzione di singole run ad una simulazione a batch.

La simulazione a batch consiste nel suddividere ogni run di simulazione in diversi batch e calcolando i risultati delle grandezze di interesse per ognuno di essi come se fossero run indipendenti.

La differenza sostanziale sta nel fatto che lo stato del sistema viene mantenuto persistente tra la fine di un batch e l’inizio del successivo.

Nel nostro caso quindi alla fine di un batch le code NON vengono azzerate ma vengono mantenute nel batch successivo in modo che i dati raccolti non siano relativi ad una simulazione che parte dal sistema vuoto.

Page 78: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Simulazione a batch:osservazioni varie

- Introducendo la simulazione a batch si è in grado di identificare oltre a quale punto i valori tendono a convergere attorno ad un valor medio “stabile”

- Il miglioramento dell’accuratezza nel caso di simulazione a batch può essere ottenuto in 2 modi:- aumentando il numero di batch all’interno di un run- aumentando la durata dei batch

- Il valore tipico del numero di batch in cui occorre suddividere un run viene indicato da un minimo di 10 ad un massimo di 30.

- Occorre prestare attenzione al fatto che la strategia utilizzata, quella delle medie cumulative, può in certi casi dare una falsa impressione di stabilità. Questo è dovuto al fatto che più si va avanti e più la media viene fatta su un numero maggiore di campioni. (Il valore corrispondente all’ultimo batch è la media tra tutti i precedenti, esclusi quelli considerati come transitorio).

Page 79: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Simulazione a batch:come si è proceduto

Per il calcolo dei valori delle grandezze utilizzando i risultati della simulazione a batch si è proceduto in questo modo:

- Si è calcolato il valore medio tra i risultati dei vari batch di un singolo run

- Si sono calcolate le medie dei risultati dei vari run per ogni batch in cui sono stati suddivisi

- Si è utilizzata la strategia delle medie cumulative mediando i risultati ottenuti al punto precedendo per ogni batch (media delle medie)

- Si è ripetuto lo stesso procedimento del punto precedente escludendo prima il primo batch, poi i primi 2 batch e poi i primi 3 batch

- A questo punto per calcolare l’intervallo di confidenza occorre calcolare la differenza tra il valor medio e il valore della media cumulativa ed è però necessario effettuare una scelta sui valori da prendere in considerazione:

- per il calcolo del valore medio tra i batch di un run ho deciso di escludere i primi 2 batch prendendo in considerazione solo i successivi- di conseguenza come valore della media cumulativa ho considerato quello che esclude i primi 2 batch (nel foglio excel è la prima riga un azzurro).

Page 80: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Simulazione a batch:i risultati

Nelle slide seguenti vengono illustrati i risultati ottenuti inserendo i valori generati dalla versione del simulatore C++ che utilizza la suddivisione in batch.

Anche in questo caso, come per la simulazione a run indipendenti ho effettuato 2 diversi esperimenti eseguendo nel primo caso 10 run e nel secondo 15 run sempre suddivisi ciascuno in 15 batch.

Seguono il confronto dell’accuratezza dei risultati ottenuti in entrambi i casi con i risultati ottenuti nella fase successiva dello studio, ovvero la simulazione di una rete di Petri equivalente al sistema, e le considerazioni su di essi.

Vengono anche inseriti i grafici relativi all’andamento delle grandezze prese in esame che mostrano l’andamento delle medie cumulative con eliminazione di 1, 2, e 3 batch di transitorio.

Quelli riportati di seguito sono screenshot dei fogli di calcolo contenenti i risultati che sono allegati a questa relazione.

Page 81: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Ris

ultati d

ella di s

imu

lazion

e a b

atch

svo

lto co

n 10

run

da

15 b

atch

Page 82: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Ris

ultati d

ella di s

imu

lazion

e a b

atch

svo

lto co

n 10

run

da

15 b

atch

Page 83: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Ris

ultati d

ella di s

imu

lazion

e a b

atch

svo

lto co

n 10

run

da

15 b

atch

Page 84: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Ris

ultati d

ella di s

imu

lazion

e a b

atch

svo

lto co

n 10

run

da

15 b

atch

Page 85: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Page 86: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Page 87: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Ris

ultati d

ella di s

imu

lazion

e a b

atch

svo

lto co

n 15

run

da

15 b

atch

Page 88: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Ris

ulta

ti della

di sim

ulazio

ne

a ba

tch svo

lto co

n 1

5 run

da 15 b

atch

Page 89: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Ris

ulta

ti della

di sim

ulazio

ne

a ba

tch svo

lto co

n 1

5 run

da 15 b

atch

Page 90: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Ris

ultati d

ella di s

imu

lazion

e a b

atch

svo

lto co

n 15

run

da

15 b

atch

Page 91: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Differenza di accuratezza tra i 2 esperimenti di simulazione a batch (15

batch) svolti con 10 e 15 run

0,002910

0,001915

AccuratezzaNumero di run

Throughput

0,014510

0,009815

AccuratezzaNumero di run

Utilizzazione Servitore 1

0,010810

0,00815

AccuratezzaNumero di run

Utilizzazione Servitore 2

4,0610

3,1715

AccuratezzaNumero di run

Tempo medio di permanenza

Page 92: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Confronto dei risultati:Simulatore vs GreatSPN

0,185990,18560,1821215

0,18650,18560,180610

Estremo sup.GreatSPNEstremo inf.Run

Throughput

0,84280,836630,823115

0,843910,836630,8149210

Estremo sup.GreatSPNEstremo inf.Run

Utilizzazione servitore 1

0,65200,64450,6360615

0,65030,64450,628710

Estremo sup.GreatSPNEstremo inf.Run

Utilizzazione servitore 2

52,6457,3046,3015

52,1657,3044,0410

Estremo sup.GreatSPNEstremo inf.Run

Tempo medio di permanenza

Page 93: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Realizzazione del sistema con reti di Petri e

simulazione con il tool GreatSPN

Screenshot dell’interfaccia di GreatSPN con la rete di Petri equivalente al sistema

Page 94: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Sistema a reti di Petri con GreatSPN

L’ultima parte dell’esperimento di simulazione consisteva nel realizzare un sistema a reti di Petri, utilizzando il software GreatSPN, equivalente al sistema precedentemente modellato col simulatore in C++ per testare la correttezza dei risultati da esso forniti.

Page 95: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Rete di Petri equivalente al sistema da simulare

Page 96: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Descrizione dei vari componenti della rete di Petri equivalente al

sistemaPosti

• Popolazione: è una rete chiusa e di conseguenza bisogna indicare il numero di token. Occorre inserire un valore grande a sufficienza per gestire il numero di utenti all’interno del sistema. Il valore massimo ammissibile da GreatSPN è 256. Io l’ho impostato a 200 (come si vede dalla figura)

• Coda1: corrisponde alla coda del primo stadio del sistema. In base alle caratteristiche del sistema è una coda illimitata.

• Serv1Idle: indica lo stato del servitore 1; infatti se all’interno di questo posto c’è un token, significa che il servitore 1 è idle, in caso contrario il servitore risulta essere busy

• Serv1Busy: indica i pezzi in lavorazione nello stadio 1 del sistema

• Controllo1: qui ci sono i pezzi che sono stati lavorati e che devono essere

• sottoposti ad un test in cui viene deciso se scartare oppure no.• Serv1Bloccato• Coda2: corrisponde alla coda del secondo stadio del sistema.

Questa coda è limitata ad un valore K• SpazioInCoda2: questo posto ha Kmenouno token che

corrisponde alla capacità della coda.• Serv2Busy: pezzi in lavorazione nello stadio 2• Serv2Idle: indica lo stato del servitore 2. Se c’è il token il

server 2 è idle diversamente è busy.• Controllo2: pezzi lavorati e che devono essere valutati in

modo tale da considerarli buoni o da scartare.

Page 97: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Transizioni temporizzateArrivi: transizione che rappresenta il tempo di interarrivo tra

i pezzi

Serv1: transizione che indica l’esecuzione della lavorazione del pezzo da parte del servitore 1.

Serv2: transizione che indica l’esecuzione della lavorazione del pezzo da parte del servitore 2.

Transizioni immediateIniziaServ1

Scarto1 → Si suppone che la scelta di scartare o meno un pezzo richieda tempo = 0

NonScarto1

InCoda2 → i pezzi vengono immessi nel secondo stadio del sistema (sempre un pezzo alla volta)

IniziaServ2 (chiamata in realtà T7 nell’immagine)

NonScarto2→ Si suppone che la scelta di scartare o meno un pezzo richieda tempo = 0

Scarto2

Descrizione dei vari componenti della rete di Petri equivalente al

sistema (2)

Page 98: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

GreatSPN: impostazione della distribuzione del tempo

di interarrivo dei pezzi

Per eseguire la simulazione sulla rete di Petri equivalente al sistema da studiare occorre ovviamente impostare i corretti valori delle distribuzioni per le transizioni. GreatSPN lavora con la distribuzione esponenziale, motivo per cui si è adottata questa scelta anche nell’implementazione del simulatore software.

Lo screenshot mostra il valore per la transizione che gestisce gli arrivi che è impostata a 0,08 come nel codice del simulatore.

Inoltre viene anche impostata come transizione a servitore singolo come previsto nel sistema reale.

Page 99: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

GreatSPN: impostazione della distribuzione dei tempi di servizio dei

2 servitoriNel codice del simulatore, lo ricordo, i valori che avevo impostato erano:

Exponential TempoServizio1(0.29,&seme);Exponential TempoServizio2(0.32,&seme);

I 2 screenshot sottostanti mostrano come ho impostato gli stessi valori anche in GreatSPN.

Page 100: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

GreatSPN: impostazione delle probabilità di scarto dei pezzi da

parte delle 2 postazioniNei 2 screenshot sottostanti si vede come ho impostato le percentuali di scarto delle 2 postazioni.

Lo scarto viene rappresentato nella rete di Petri come una transazione immediata, che quindi richiede tempo 0. (indicate dal rettangolo nero pieno, a differenza delle precedenti che erano temporizzate rappresentate quindi dal rettangolo bianco “vuoto”).

Con la seguente definizione indico la probabilità che ha un token di finire in ramo della rete (uscire, quindi tornare nel posto “popolazione”) piuttosto che in un altro (proseguire alla stazione 2 nel caso di uscita dalla stazione 1).

Le relative transazioni di “NonScarto1” e “NonScarto2” avranno probabilità data da 1 meno i valori indicati qui sotto.

Probabilità scarto1 = 15% Probabilità scarto2 = 10%

Page 101: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

GreatSPN: i risultatiPer quanto riguarda i risultati ricavati con greatSPN, alcuni, come il Throughpu, sono visualizzati direttamente nella rete dopo il calcolo della Steady-StateSolution. Questo perché esso si riverisce ad una transazione.

Altri, quelli riguardanti i posti, come le Utilizzazioni dei servitori sono mostrati tramite il comando “Show” in apposite finestre.

Page 102: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

GreatSPN: i risultati

Utilizzazione 2: 0,64459

Utilizzazione 1: 83663

Per vedere i risultati delle Utilizzazioni dei 2 servitori, che sono tra quelle che interessano e che si devono studiare occore utilizzare il comando “Show” results e poi cliccare sui rispettivi posti. Vengono cosi aperte le rispettive finestre con i risultati.

I 2 screenshot sottostanti mostrano i valori delle Utilizzazioni dei 2 servitori risultanti dalla simulazione con GreatSPN.

Page 103: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

GreatSPN: calcolo del tempo medio di permanenza

Per quanto riguarda il calcolo del tempo medio di permanenza il discorso è diverso, in quanto tale grandezza non si ha a disposizione direttamente ma occorre ricavarla in modo indiretto tramite una formula, partendo sempre da alcuni valori ricavati tramite GreatSPN. Quelli che ho cerchiato in blu nell’immagine ad esempio servono per il calcolo del numero medio di pezzi nel sistema.

Page 104: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

GreatSPN: calcolo del tempo medio di permanenza

Per calcolare il tempo medio di permanenza del sistema uso la formula della

LEGGE DEL TEMPO DI ATTESA

N

Xis1

W =

Dove con Xis1 si intende il throughput in ingresso alla postazione 1 che calcolo nel modo seguente:

Xis1 = N * XarriviN = numero di pezzi in arrivo

Xis1 = 3 * 0,08 = 0,24

Come verifica provo che il valore di Xis1 deve essere uguale alla somma:

Xis1 = Xscarto1 + Xscarto2 + XNonScarto2

Xis1 = 0,0363 + 0,020 + 0,185 = 0,241

Page 105: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

GreatSPN: calcolo del tempo medio di permanenza

Una volta calcolato il valore di Xis1 mi rimane da calcolare il numero medio di pezzi presenti nel sistema. Questo lo ricavo dal numero medio di token presenti nelle giuste postazioni:

200 – n(Popolazione) =

= n(Coda1) + n(Serv1Busy) + n(Serv1Bloccato) + n(Coda2) +

n(Serv2Busy)

Dove con n(Popolazione) si intende il numero medio di token presente nella postazione “Popolazione”, e così via per le altre.

Ricordo che il posto “Popolazione” è stato introdotto perché con GreatSPN occorreva rappresentare il sistema da simulare come sistema chiuso.

n = 11,70 + 0,0836 + 0,0058 + 1,322 + 0,644

n = 13,75

Page 106: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

GreatSPN: calcolo del tempo medio di permanenza

A questo punto, dopo aver calcolato il Xis1 e il numero medio di pezzi presenti nel sistema, applico la LEGGE DEL TEMPO DI ATTESA definita così:

n = w * X

Da cui ricavo

N

Xis1

W =

13,75

0,24W = = 57,3

A questo punto, dopo aver calcolato il Xis1 e il numero medio di pezzi presenti nel sistema, applico la LEGGE DEL TEMPO DI ATTESA definita così:

n = w * X

Da cui ricavo

13,75

0,24W = = 57,3

Page 107: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

ConclusioniLo scopo di questa esercitazione era quello di mostrare

tutto il processo di approccio alla simulazione di un ipotetico sistema reale.

Si è partiti dalla sua definizione, e si è realizzato un simulatore software scritto in C++.

Si è effettuata prima una semplice simulazione basata su run indipendenti per passare poi all’analisi del problema del transitorio iniziale, in quanto si voleva fare uno studio a regime, introducendo la tecnica della simulazione a batch e il metodo delle medie cumulative.

Si è poi fatta una controanalisi utilizzando una tecnica diversa: realizzando un sistema a Rete di Petri equivalente al sistema tramite il tool GreatSPN per fare poi un confronto dei risultati.

Alla fine di tutto questo studio i risultati ottenuti si possono considerare più che soddisfacenti in quanto i valori delle grandezze calcolate con il sistema a Rete di Petri cadono tutti all’interno degli intervalli calcolati facendo girare il simulatore e facendo lo studio con il foglio di calcolo. L’unico valore che si discosta un po’ è quello del Tempo Medio di Permanenza e questo è dovuto al fatto che il simulatore software perde qualche pezzo una volta terminata la simulazione, quando il sistema si svuota. Tenendo conto di questo fatto, comunque, il valore ottenuto è comunque soddisfacente in quanto non si discosta poi molto da quello ottenuto con GreatSPN.

NELLA SLIDE SEGUENTE RIPORTO IL CONFRONTO TRA I RISULTATI OTTENUTI NEI DUE CASI CHE AVEVO GIA’ RIPORTATO PRECEDENTEMENTE.

Page 108: Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.

Confronto dei risultati:Simulatore vs GreatSPN

0,185990,18560,1821215

0,18650,18560,180610

Estremo sup.GreatSPNEstremo inf.Run

Throughput

0,84280,836630,823115

0,843910,836630,8149210

Estremo sup.GreatSPNEstremo inf.Run

Utilizzazione servitore 1

0,65200,64450,6360615

0,65030,64450,628710

Estremo sup.GreatSPNEstremo inf.Run

Utilizzazione servitore 2

52,6457,3046,3015

52,1657,3044,0410

Estremo sup.GreatSPNEstremo inf.Run

Tempo medio di permanenza