Your SlideShare is downloading. ×
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Simulazione ad Eventi Discreti (C++) e tramite Rete di Petri di un sistema.
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

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

4,250

Published on

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 …

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.

Published in: Technology, Business
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
4,250
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
37
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Magazzino pezzi da lavorare LABORATORIO DI SIMULAZIONE Molinari Davis Esercizio per la parte pratica dell’esame Sistema da simulare
  • 2. 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. “
  • 3.
    • 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 è bloccato
    • false 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.
  • 4.
    • 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.
  • 5.
    • 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
  • 6. 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.
  • 7. Tipo_Evento ARRIVO Coda1 += N Coda 1 == N Inserisci in FEL un evento PARTENZA dalla stazione 1 Inserisci in FEL l’evento del prossimo ARRIVO di N pezzi SI NO Flow-chart della gestione di un evento di tipo ARRIVO
  • 8. Tipo_Evento PARTENZA-1 Scarto? Coda2 <= K Coda1 -- Coda2 ++ Serv1 = bloccato Coda1 -- PezziScart ++ Coda2 == 1? Coda1 > 0 ? Inserisci in FEL un evento PARTENZA2 Inserisci in FEL un evento PARTENZA1 NO NO NO NO SI SI SI SI Flow-chart della gestione di un evento di tipo Partenza dal servitore 1
  • 9. Tipo_Evento PARTENZA-2 Coda2-- Scarto? Coda2 > 0 Serv1 bloccato? Coda1 > 0 Coda1 -- Coda2 ++ Inserisci in FEL un evento PARTENZA2 Inserisci in FEL un evento 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
  • 10. GESTIONE DELL’EVENTO DI “FINE SIMULAZIONE ” Tipo_Evento FINE SIMULAZIONE Rimuovo dalla FEL L’ 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);
  • 11.
    • 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”
  • 12.
    • 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 totale
    • Busytime2 lo calcolo facendo la stessa cosa calcolando il tempo in cui la postazione 2 è occupata.
  • 13. 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.
  • 14. 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.
  • 15. 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
  • 16. 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'evento
    • double 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 list
    • Evento *Get(); // preleva dalla event list l'evento in testa
    • void RimuoviArrivi(); // elimina eventi di tipo ARRIVO dalla event list
    • bool Vuota(); // ritorna true se la lista è vuota, false altrimenti
    • private:
    • list<Evento*> ev_list; // event list implementata mediante la STL
    • };
    • inline EventList::EventList()
    • {
    • }
  • 17.
    • 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
  • 18. 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.
  • 19. event_list.cc
    • #include &quot;event_list.h&quot;
    • 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 NULL
    • Evento* EventList::Get(void)
    • {
    • if (ev_list.empty())
    • return NULL;
    • Evento* ev = ev_list.front();
    • ev_list.pop_front();
    • return ev;
    • }
  • 20. event_list.cc (2)
    • // Elimina dalla event list gli eventi di tipo arrivo
    • void EventList::RimuoviArrivi(void)
    • {
    • list<Evento*>::iterator it = ev_list.begin();
    • // scorro fino a quando non trovo un evento di // tipo arrivo
    • while ((*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 altrimenti
    • bool EventList::Vuota(void)
    • {
    • if (ev_list.empty())
    • return true;
    • else
    • return false;
    • }
  • 21. 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
  • 22. 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 0
    • ev = new Evento(ARRIVO,0.0);
    • // inseriscilo nella event list
    • Lista.Sched(ev);
    • ev = new Evento(FINE_BATCH,BATCH_TIME);
    • Lista.Sched(ev);
    • // crea un nuovo evento di tipo SIM_END previsto per l'instante 45000
    • ev = new Evento(SIM_END,45000.0);
    • // inseriscilo nella event list
    • Lista.Sched(ev);
    • CurrentTime=0.0;
    • i=1;
    • }
  • 23. 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;
    • }
    • }
  • 24. 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 << &quot; Arrivo al tempo &quot; << CurrentTime << &quot; [Coda1: &quot; << Coda1 << &quot;, Coda2: &quot; << Coda2 << &quot;]&quot;;
    • #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_SERV1
    • ev = new Evento(PARTENZA1,CurrentTime+DT);
    • Lista.Sched(ev);
    • }
    • }
  • 25. Funzione per la gestione di un evento di tipo PARTENZA DAL SERVITORE 1
    • void partenza1()
    • {
    • Evento *ev;
    • AccumulaStatistiche();
    • #ifdef VERBOSE
    • cout << &quot; Partenza da 1 al tempo &quot; << CurrentTime << &quot; [Coda1: &quot; << Coda1 << &quot;, Coda2: &quot; << Coda2 << &quot;]&quot;;
    • #endif
    • p = ProbScarto.Generate();
    • if (p <= P_SCART1)
    • {
    • Coda1--;
    • Scarti1++;
    • Sc1Batch++;
    • #ifdef VERBOSE
    • cout << &quot; PEZZO SCARTATO DA 1&quot;;
    • #endif
    • }
    • else
    • {
    • if (Coda2 < QUE2)
    • {
    • Coda1--;
    • Coda2++;
    • if (Coda2 == 1)
    • {
    • // DT = &quot;Genera un'instanza di una variabile casuale&quot;;
    • DT = TempoServizio2.Generate();
    • // schedula partenza al tempo CurrentTime+DT
    • ev = new Evento(PARTENZA2,CurrentTime+DT);
    • Lista.Sched(ev);
    • }
    • }
    • else
    • {
    • bloccato = true;
    • NBlocc++;
    • #ifdef VERBOSE
    • cout << &quot; SISTEMA BLOCCATO &quot; << &quot; [Coda1: &quot; << Coda1 << &quot;, Coda2: &quot; << Coda2 << &quot;]&quot;;
    • #endif
    • return;
    • }
    • }
    • if (Coda1 > 0)
    • {
    • DT = TempoServizio1.Generate();
    • // schedula partenza al tempo CurrentTime+DT
    • ev = new Evento(PARTENZA1,CurrentTime+DT);
    • Lista.Sched(ev);
    • }
    • }
  • 26. Funzione per la gestione di un evento di tipo PARTENZA DAL SERVITORE 2
    • void partenza2()
    • {
    • Evento *ev;
    • AccumulaStatistiche();
    • Coda2--;
    • ComplBatch ++;
    • #ifdef VERBOSE
    • cout << &quot; Partenza da 2 al tempo &quot; << CurrentTime << &quot; [Coda1: &quot; << Coda1 << &quot;, Coda2: &quot; << Coda2 << &quot;]&quot;;
    • #endif
    • p = ProbScarto.Generate();
    • if (p <= P_SCART2)
    • {
    • Scarti2++;
    • Sc2Batch++;
    • #ifdef VERBOSE
    • cout << &quot; PEZZO SCARTATO DA 2&quot;;
    • #endif
    • }
    • if (Coda2 > 0)
    • {
    • DT = TempoServizio2.Generate();
    • // schedula partenza al tempo CurrentTime+DT
    • ev = new Evento(PARTENZA2,CurrentTime+DT);
    • Lista.Sched(ev);
    • }
    • if (bloccato == true)
    • {
    • Coda1--;
    • Coda2++;
    • bloccato = false;
    • #ifdef VERBOSE
    • cout << &quot; SISTEMA SBLOCCATO &quot; << &quot; [Coda1: &quot; << Coda1 << &quot;, Coda2: &quot; << Coda2 << &quot;]&quot;;
    • #endif
    • if (Coda1 > 0)
    • {
    • DT = TempoServizio1.Generate();
    • // schedula partenza al tempo CurrentTime+DT
    • ev = new Evento(PARTENZA1,CurrentTime+DT);
    • Lista.Sched(ev);
    • }
    • }
    • }
  • 27. Funzione per la gestione di un evento di tipo FINE BATCH
    • void batch()
    • {
    • cout << &quot; ARRIVI NEL BATCH &quot; << NArrBatch;
    • cout << &quot; SCARTI DA 1 NEL BATCH &quot; << Sc1Batch;
    • double pezzi = (ComplBatch - Sc2Batch);
    • double tot = (ComplBatch + Sc1Batch);
    • AccumulaStatistiche();
    • u1 << (Busy1Batch/BATCH_TIME) << &quot; &quot;;
    • u2 << (Busy2Batch/BATCH_TIME) << &quot; &quot;;
    • thr << (pezzi/BATCH_TIME) << &quot; &quot;;
    • tdp << (AreaBatch / tot) << &quot; &quot;;
    • cout << &quot; Utilizzazione del servitore 1 nel batch &quot; << i << &quot;: &quot; << (Busy1Batch/BATCH_TIME);
    • cout << &quot; Utilizzazione del servitore 2 nel batch &quot; << i << &quot;: &quot; << (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);
    • }
    • }
  • 28. 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 << &quot; ----------------------------------------------------&quot;;
    • cout << &quot; Risultati dell'esperimento di simulazione: &quot;;
    • cout << &quot; Durata REALE della simulazione: &quot; << CurrentTime;
    • cout << &quot; Numero di pezzi arrivati durante la simulazione: &quot; << NArr;
    • cout << &quot; Numero di pezzi scartati dalla prima stazione: &quot; << Scarti1;
    • cout << &quot; Numero di pezzi scartati dalla seconda stazione: &quot; << Scarti2;
    • cout << &quot; Numero totale di pezzi scartati: &quot; << Scarti1 + Scarti2;
    • cout << &quot; Numero di partenze (senza scarti): &quot; << NCompl;
    • cout << &quot; Tempo di occupazione della stazione 1: &quot; << BTIME1;
    • cout << &quot; Tempo di occupazione della stazione 2: &quot; << BTIME2;
    • cout << &quot; Tempo totale di blocco della stazione 1: &quot; << BLOCCO;
    • cout << &quot; Numero di blocchi del servitore 1: &quot; << NBlocc;
    • if (NBlocc > 0)
    • cout << &quot; Durata media di blocco del servitore 1: &quot; << BLOCCO / NBlocc;
    • cout << &quot; Utilizzazione stazione 1: &quot; << BTIME1 / CurrentTime;
    • cout << &quot; Utilizzazione stazione 2: &quot; << BTIME2 / CurrentTime;
    • cout << &quot; Tempo medio di servizio della stazione 1: &quot; << BTIME1/NArr;
    • cout << &quot; Tempo medio di servizio della stazione 2: &quot; << BTIME2/(NArr-Scarti1);
    • cout << &quot; Throughput (senza scarti): &quot; << NCompl / CurrentTime;
    • cout << &quot; Flusso di scarto: &quot; << (Scarti1 + Scarti2) / CurrentTime;
    • cout << &quot; Throughput (con scarti): &quot; << (NCompl / CurrentTime) + ((Scarti1 + Scarti2) / CurrentTime);
    • cout << &quot; Throughput (con scarti) calcolato con la legge del tempo di attesa: &quot; << thr;
    • cout << &quot; Frequenza degli arrivi: &quot; << NArr / CurrentTime;
    • // cout << &quot; Valore dell'integrale 'Area': &quot; << Area;
    • cout << &quot; Numero medio di pezzi nel sistema: &quot; << Area/CurrentTime;
    • cout << &quot; Tempo medio di permanenza nel sistema: &quot; << Area / NArr;
    • cout << &quot; ----------------------------------------------------&quot;;
    • }
  • 29. 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
  • 30. Funzione che gestisce il ciclo principale del simulatore
    • void Clock()
    • {
    • Evento *ev;
    • // preleva l'evento in cima alla event list
    • ev = Lista.Get();
    • // aggiorna il tempo corrente assegnandogli il tempo
    • // di schedulazione dell'evento in cima alla event list
    • CurrentTime = 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 VERBOSE
    • cout << &quot; EVENTO DI FINE SIMULAZIONE (Rimuovo gli arrivi)&quot;;
    • #endif
    • Lista.RimuoviArrivi();
    • EndOfSimulation = true;
    • break;
    • }
    • // rilascia la memoria allocata all'evento appena elaborato
    • delete ev;
    • }
  • 31. Funzione Main del simulatore main(int argc, char* argv[]) { int j; long seed; if (argc != 2) usage(argv[0]); NRun = atoi(argv[1]); if (NRun == 0) { printf(&quot;ERRORE: Il parametro passato deve essere un intero. &quot;); usage(argv[0]); } u1.open(&quot;utilizzazione1.txt&quot;); u2.open(&quot;utilizzazione2.txt&quot;); thr.open(&quot;throughput.txt&quot;); tdp.open(&quot;tempPerm.txt&quot;); for (j = 1; j <= NRun; j++) { cout << &quot; Inserisci il seme per la generazione dei numeri casuali: &quot;; cin >> seed; seme.set(seed); inizializza(); do Clock(); while (EndOfSimulation == false || Lista.Vuota() == false); Report(); } u1.close(); u2.close(); thr.close(); tdp.close(); cout << &quot; FINE SIMULAZIONE &quot; << flush; }
  • 32. 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
  • 33. 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.
  • 34. 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
  • 35.
    • 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.txt
    • Utilizzazione1.txt
    • Utilizzazione2.txt
    • TempPerm.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
  • 36. Esportazione dei risultati su 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.
  • 37. Esportazione dei risultati su 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
  • 38.
    • 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(&quot;.&quot;, &quot;,&quot;)
    Modulo Visual Basic.NET per l’esportazione dei risultati
  • 39.
    • Imports System.IO
    • Module 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() + &quot;Analisi.xls&quot;)
    • foglioExc = appExcel.Worksheets(&quot;Tabella2&quot;)
    • objReader = New StreamReader(&quot;utilizzazione1.txt&quot;)
    • For i = firstRow To lastRow
    • For n = firstCol To lastCol
    • foglioExc.Cells(i, n).Value = objReader.ReadLine().Replace(&quot;.&quot;, &quot;,&quot;)
    • Next n
    • Next i
    • foglioExc.SaveAs(CurDir() + &quot;Utilizzazione1.xls&quot;)
    Modulo Visual Basic.NET per l’esportazione dei risultati
  • 40. 'Utilizzazione del servitore 2 wbookExcel = appExcel.Workbooks.Open(CurDir() + &quot;Analisi.xls&quot;) foglioExc = appExcel.Worksheets(&quot;Tabella2&quot;) objReader = New StreamReader(&quot;utilizzazione2.txt&quot;) For i = firstRow To lastRow For n = firstCol To lastCol foglioExc.Cells(i, n).Value = objReader.ReadLine().Replace(&quot;.&quot;, &quot;,&quot;) Next n Next i foglioExc.SaveAs(CurDir() + &quot;Utilizzazione2.xls&quot;) 'Throughput del sistema senza scarti wbookExcel = appExcel.Workbooks.Open(CurDir() + &quot;Analisi.xls&quot;) foglioExc = appExcel.Worksheets(&quot;Tabella2&quot;) objReader = New StreamReader(&quot;throughput.txt&quot;) For i = firstRow To lastRow For n = firstCol To lastCol foglioExc.Cells(i, n).Value = objReader.ReadLine().Replace(&quot;.&quot;, &quot;,&quot;) Next n Next i foglioExc.SaveAs(CurDir() + &quot;Throughput.xls&quot;) 'Throughput del sistema senza scarti wbookExcel = appExcel.Workbooks.Open(CurDir() + &quot;Analisi.xls&quot;) foglioExc = appExcel.Worksheets(&quot;Tabella2&quot;) objReader = New StreamReader(&quot;tempPerm.txt&quot;) For i = firstRow To lastRow For n = firstCol To lastCol foglioExc.Cells(i, n).Value = objReader.ReadLine().Replace(&quot;.&quot;, &quot;,&quot;) Next n Next i foglioExc.SaveAs(CurDir() + &quot;TempPerm.xls&quot;) appExcel.Quit() End Sub End Module
  • 41. Analisi dell’output della 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
  • 42.
    • 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’output della simulazione Analisi in Transitorio VS Analisi a Regime
  • 43. 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 R 0 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 S R     R conoscendo il valore S 0 per R = R 0 si può tentare una stima di quanti run aggiuntivi sono necessari: R  (t α/2,R-1 S 0 /  ) 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 S 0 /  ) 2 ) Il valore iniziale di repliche (Run) che ho adottato è 15.
  • 44. Un primo esempio di simulazione con campioni indipendenti
    • Ho 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
  • 45. 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:
  • 46. 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 – α)%.
  • 47. Tabella dei risultati dell’esperimento di simulazione con 15 run indipendenti senza batch: Throughput   0,182274226 0,181421774       INTERVALLO DI CONFIDENZA                         ACCURATEZZA 0,000426226                 STUDENT 2,145                 VARIANZA 0,000198707           somma delle differenze   valor medio   3,94843E-08 8,29171E-06   0,181848               7,33326E-06 0,002708 0,17914     1,33225E-05 0,00365 0,178198     2,8224E-06 -0,00168 0,183528     2,23204E-06 -0,001494 0,183342     5,29E-10 2,3E-05 0,181825     2,17858E-06 -0,001476 0,183324     6,56384E-06 0,002562 0,179286     6,46176E-06 -0,002542 0,18439     5,53536E-07 0,000744 0,181104     1,28522E-05 0,003585 0,178263     9,72816E-06 0,003119 0,178729     2,503E-05 -0,005003 0,186851     1,87964E-06 -0,001371 0,183219     3,40772E-06 -0,001846 0,183694     9,58441E-07 -0,000979 0,182827     quadrato differenza valor medio - valore Risultato ottenuto
  • 48. Tabella dei risultati dell’esperimento di simulazione con 15 run indipendenti senza batch: utilizzazione servitore 1   0,954992065 0,950742335       INTERVALLO DI CONFIDENZA                         ACCURATEZZA 0,002124865                 STUDENT 2,145                 VARIANZA 0,000990613           somma delle differenze   valor medio   9,81314E-07 0,000206076   0,9528672               0,000158261 0,0125802 0,940287     0,000841302 0,0290052 0,923862     4,27662E-08 -0,0002068 0,953074     3,20786E-05 -0,0056638 0,958531     2,33888E-05 0,0048362 0,948031     5,1984E-10 -2,28E-05 0,95289     0,000312377 0,0176742 0,935193     0,000970497 -0,0311528 0,98402     0,000184465 -0,0135818 0,966449     0,000586037 0,0242082 0,928659     3,62548E-05 0,0060212 0,946846     0,000501975 -0,0224048 0,975272     3,27047E-05 -0,0057188 0,958586     7,49748E-05 -0,0086588 0,961526     4,78145E-05 -0,0069148 0,959782     quadrato differenza valor medio - valore Risultato ottenuto
  • 49. Tabella dei risultati dell’esperimento di simulazione con 15 run indipendenti senza batch: utilizzazione servitore 2   0,678124507 0,674940693       INTERVALLO DI CONFIDENZA                         ACCURATEZZA 0,001591907                 STUDENT 2,145                 VARIANZA 0,000742148           somma delle differenze   valor medio   5,50783E-07 0,000115664   0,6765326               3,35519E-05 -0,0057924 0,682325     5,00358E-05 0,0070736 0,669459     0,000241069 -0,0155264 0,692059     2,98737E-06 -0,0017284 0,678261     2,51462E-05 0,0050146 0,671518     4,55976E-05 0,0067526 0,66978     0,00016873 0,0129896 0,663543     8,33094E-05 -0,0091274 0,68566     6,37762E-07 0,0007986 0,675734     0,000161204 0,0126966 0,663836     0,000200806 0,0141706 0,662362     0,00028674 -0,0169334 0,693466     3,94058E-05 -0,0062774 0,68281     0,000173512 -0,0131724 0,689705     8,21126E-05 0,0090616 0,667471     quadrato differenza valor medio - valore Risultato ottenuto
  • 50. Tabella dei risultati dell’esperimento di simulazione con 15 run indipendenti senza batch: Tempo di permanenza nel sistema   211,0541033 176,19443       INTERVALLO DI CONFIDENZA                         ACCURATEZZA 17,42983665                 STUDENT 2,145                 VARIANZA 8,125797971           somma delle differenze   valor medio   66,02859267 13866,00446   193,6242667               4382,607708 66,20126667 127,423     8003,318234 89,46126667 104,163     411,0648117 -20,27473333 213,899     16,632259 4,078266667 189,546     2651,762489 51,49526667 142,129     1482,424538 38,50226667 155,122     4451,994315 66,72326667 126,901     30475,63922 -174,5727333 368,197     4,716425671 -2,171733333 195,796     6389,966602 79,93726667 113,687     4600,673759 67,82826667 125,796     46515,15925 -215,6737333 409,298     430,6980773 20,75326667 172,871     629,7724091 25,09526667 168,529     9483,396751 -97,38273333 291,007     quadrato differenza valor medio - valore Risultato ottenuto
  • 51.
    • 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
  • 52. 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 )) / 8 2 =
    • = 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%
  • 53. 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.
  • 54. 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.
  • 55.  
  • 56.  
  • 57.  
  • 58.  
  • 59. Grafici dell’andamento delle utilizzazioni del servitore 1 e del servitore 2
  • 60. 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.
  • 61. 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 necessari
    • per 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.
  • 62. Nuova simulazione con 5 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).
  • 63. Tavola della distribuzione Student Siccome 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
  • 64. Tabella dei risultati dell’esperimento di simulazione con 5 run indipendenti senza batch: Throughput   0,188262 0,17969       INTERVALLO DI CONFIDENZA                         ACCURATEZZA 0,004286                 STUDENT 2,776                 VARIANZA 0,001543986           somma delle differenze   valor medio   2,38389E-06 4,76778E-05   0,1839764                                   3,59568E-05 0,0059964 0,17798     5,29644E-06 0,0023014 0,181675     8,92269E-07 -0,0009446 0,184921     1,54418E-05 -0,0039296 0,187906     1,1721E-05 -0,0034236 0,1874     quadrato differenza valor medio - valore Risultato ottenuto
  • 65. Tabella dei risultati dell’esperimento di simulazione con 5 run indipendenti senza batch: Utilizzazione Servitore1   0,85735 0,81027       INTERVALLO DI CONFIDENZA                         ACCURATEZZA 0,02354                 STUDENT 2,776                 VARIANZA 0,008480292           somma delle differenze   valor medio   7,19154E-05 0,001438307   0,8338184                                   0,001321352 0,0363504 0,797468     7,877E-06 -0,0028066 0,836625     2,78425E-05 -0,0052766 0,839095     0,000304593 -0,0174526 0,851271     0,000116956 -0,0108146 0,844633     quadrato differenza valor medio - valore Risultato ottenuto
  • 66. Tabella dei risultati dell’esperimento di simulazione con 5 run indipendenti senza batch: Utilizzazione Servitore2   0,65616 0,623329       INTERVALLO DI CONFIDENZA                         ACCURATEZZA 0,016416                 STUDENT 2,776                 VARIANZA 0,00591352           somma delle differenze   valor medio   3,49697E-05 0,000699394   0,6397454                                   0,000328385 0,0181214 0,621624     0,000486838 0,0220644 0,617681     1,55047E-05 -0,0039376 0,643683     0,000288545 -0,0169866 0,656732     0,000371009 -0,0192616 0,659007     quadrato differenza valor medio - valore Risultato ottenuto
  • 67. Tabella dei risultati dell’esperimento di simulazione con 5 run indipendenti senza batch: Tempo medio di permanenza   53,52156 40,728       INTERVALLO DI CONFIDENZA                         ACCURATEZZA 6,39678                 STUDENT 2,776                 VARIANZA 2,30431936           somma delle differenze   valor medio   5,309887713 106,1977543   47,12478                                   89,31535246 9,45068 37,6741     2,735980646 1,65408 45,4707     6,810116544 -2,60962 49,7344     19,23980314 -4,38632 51,5111     16,88240179 -4,10882 51,2336     quadrato differenza valor medio - valore Risultato ottenuto
  • 68. 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.
  • 69. Tavola della distribuzione Student Avendo 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.
  • 70. Tabella dei risultati dell’esperimento di simulazione con 15 run indipendenti senza batch: Throughput   0,18280146 0,18161654       INTERVALLO DI CONFIDENZA                         ACCURATEZZA 0,00059246                 STUDENT 2,145                 VARIANZA 0,000276205           somma delle differenze   valor medio   7,62892E-08 1,60207E-05   0,182209               3,40402E-06 -0,001845 0,184054     6,48025E-07 0,000805 0,181404     2,79893E-06 -0,001673 0,183882     7,4529E-08 -0,000273 0,182482     5,79121E-07 -0,000761 0,18297     1,57252E-06 0,001254 0,180955     5,79121E-07 -0,000761 0,18297     1,57252E-06 0,001254 0,180955     5,79121E-07 -0,000761 0,18297     3,74911E-05 0,006123 0,176086     1,27916E-06 -0,001131 0,18334     1,57252E-06 0,001254 0,180955     1,27916E-06 -0,001131 0,18334     1,4352E-06 0,001198 0,181011     1,26167E-05 -0,003552 0,185761     quadrato differenza valor medio - valore Risultato ottenuto
  • 71. Tabella dei risultati dell’esperimento di simulazione con 15 run indipendenti senza batch: Utilizzazione Servitore 1   0,827609427 0,823142707       INTERVALLO DI CONFIDENZA                         ACCURATEZZA 0,00223336                 STUDENT 2,145                 VARIANZA 0,001041194           somma delle differenze   valor medio   1,08408E-06 0,000227658   0,825376067               1,96078E-05 0,004428067 0,820948     0,000156477 0,012509067 0,812867     2,31945E-05 0,004816067 0,82056     8,99071E-05 -0,009481933 0,834858     6,7403E-05 -0,008209933 0,833586     5,12751E-07 0,000716067 0,82466     6,7403E-05 -0,008209933 0,833586     5,12751E-07 0,000716067 0,82466     6,7403E-05 -0,008209933 0,833586     0,00174023 0,041716067 0,78366     9,26971E-05 -0,009627933 0,835004     5,12751E-07 0,000716067 0,82466     9,26971E-05 -0,009627933 0,835004     4,72657E-06 0,002174067 0,823202     0,00020805 -0,014423933 0,8398     quadrato differenza valor medio - valore Risultato ottenuto
  • 72. Tabella dei risultati dell’esperimento di simulazione con 15 run indipendenti senza batch: Utilizzazione Servitore 2   0,636132284 0,63159025       INTERVALLO DI CONFIDENZA                         ACCURATEZZA 0,002271017                 STUDENT 2,145                 VARIANZA 0,001058749           somma delle differenze   valor medio   1,12095E-06 0,000235399   0,633861267               5,78776E-05 -0,007607733 0,641469     0,000109783 -0,010477733 0,644339     3,93472E-05 -0,006272733 0,640134     3,77152E-05 0,006141267 0,627720     1,87763E-06 0,001370267 0,632491     4,58501E-05 0,006771267 0,627090     1,87763E-06 0,001370267 0,632491     4,43725E-05 0,006661267 0,627200     1,87763E-06 0,001370267 0,632491     0,000431653 0,020776267 0,613085     8,68324E-06 -0,002946733 0,636808     4,57147E-05 0,006761267 0,627100     8,68324E-06 -0,002946733 0,636808     5,84725E-05 -0,007646733 0,641508     0,000177522 -0,013323733 0,647185     quadrato differenza valor medio - valore Risultato ottenuto
  • 73. Tabella dei risultati dell’esperimento di simulazione con 15 run indipendenti senza batch: Tempo medio di permanenza nel sistema   47,56398387 45,61865613       INTERVALLO DI CONFIDENZA                         ACCURATEZZA 0,972663871                 STUDENT 2,145                 VARIANZA 0,45345635           somma delle differenze   valor medio   0,205622662 43,18075893   46,59132               27,88030083 -5,28018 51,8715     48,08202017 6,93412 39,6572     2,308515584 -1,51938 48,1107     71,60002842 -8,46168 55,0530     1,64999163 1,28452 45,3068     10,58057773 -3,25278 49,8441     1,64999163 1,28452 45,3068     10,58057773 -3,25278 49,8441     1,64999163 1,28452 45,3068     102,6314877 10,13072 36,4606     16,17986266 4,02242 42,5689     10,58057773 -3,25278 49,8441     16,17986266 4,02242 42,5689     0,001029126 -0,03208 46,6234     15,3004581 -3,91158 50,5029     quadrato differenza valor medio - valore Risultato ottenuto
  • 74. Differenza di accuratezza tra i 2 esperimenti di simulazione a 5 e 15 run 0,004286 5 0,0005924 15 Accuratezza Numero di run Throughput 0,02354 5 0,00223336 15 Accuratezza Numero di run Utilizzazione Servitore 1 0,016416 5 0,002271017 15 Accuratezza Numero di run Utilizzazione Servitore 2 6,39678 5 0,972663871 15 Accuratezza Numero di run Tempo medio di permanenza
  • 75. Differenza in termini di errore percentuale 2,36 % 5 0,33 % 15 Accuratezza Numero di run Throughput 2,85 % 5 0,27 % 15 Accuratezza Numero di run Utilizzazione Servitore 1 2,59 % 5 0,36 % 15 Accuratezza Numero di run Utilizzazione Servitore 2 13,73 % 5 2,08 % 15 Accuratezza Numero di run Tempo medio di permanenza
  • 76. Il problema del transitorio 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.
  • 77. 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.
  • 78. 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).
  • 79. 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 ).
  • 80. 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.
  • 81. Risultati della di simulazione a batch svolto con 10 run da 15 batch
  • 82. Risultati della di simulazione a batch svolto con 10 run da 15 batch
  • 83. Risultati della di simulazione a batch svolto con 10 run da 15 batch
  • 84. Risultati della di simulazione a batch svolto con 10 run da 15 batch
  • 85.  
  • 86.  
  • 87. Risultati della di simulazione a batch svolto con 15 run da 15 batch
  • 88. Risultati della di simulazione a batch svolto con 15 run da 15 batch
  • 89. Risultati della di simulazione a batch svolto con 15 run da 15 batch
  • 90. Risultati della di simulazione a batch svolto con 15 run da 15 batch
  • 91. Differenza di accuratezza tra i 2 esperimenti di simulazione a batch (15 batch) svolti con 10 e 15 run 0,0029 10 0,0019 15 Accuratezza Numero di run Throughput 0,0145 10 0,0098 15 Accuratezza Numero di run Utilizzazione Servitore 1 0,0108 10 0,008 15 Accuratezza Numero di run Utilizzazione Servitore 2 4,06 10 3,17 15 Accuratezza Numero di run Tempo medio di permanenza
  • 92. Confronto dei risultati: Simulatore vs GreatSPN 0,18599 0,1856 0,18212 15 0,1865 0,1856 0,1806 10 Estremo sup. GreatSPN Estremo inf. Run Throughput 0,8428 0,83663 0,8231 15 0,84391 0,83663 0,81492 10 Estremo sup. GreatSPN Estremo inf. Run Utilizzazione servitore 1 0,6520 0,6445 0,63606 15 0,6503 0,6445 0,6287 10 Estremo sup. GreatSPN Estremo inf. Run Utilizzazione servitore 2 52,64 57,30 46,30 15 52,16 57,30 44,04 10 Estremo sup. GreatSPN Estremo inf. Run Tempo medio di permanenza
  • 93. 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
  • 94. 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.
  • 95. Rete di Petri equivalente al sistema da simulare
  • 96. Descrizione dei vari componenti della rete di Petri equivalente al sistema
    • Posti
    • 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.
  • 97.
    • Transizioni temporizzate
    • Arrivi: 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 immediate
    • IniziaServ1
    • 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)
  • 98. 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.
  • 99. GreatSPN: impostazione della distribuzione dei tempi di servizio dei 2 servitori Nel 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.
  • 100. GreatSPN: impostazione delle probabilità di scarto dei pezzi da parte delle 2 postazioni Nei 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%
  • 101. GreatSPN: i risultati Per 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.
  • 102. 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.
  • 103. 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.
  • 104. 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 X is1 W = Dove con X is1 si intende il throughput in ingresso alla postazione 1 che calcolo nel modo seguente: Xis1 = N * X arrivi N = 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 = X scarto1 + X scarto2 + X NonScarto2 Xis1 = 0,0363 + 0,020 + 0,185 = 0,241
  • 105. 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
  • 106. 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 X is1 W = 13,75 0,24 W = = 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,24 W = = 57,3
  • 107. Conclusioni
    • Lo 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.
  • 108. Confronto dei risultati: Simulatore vs GreatSPN 0,18599 0,1856 0,18212 15 0,1865 0,1856 0,1806 10 Estremo sup. GreatSPN Estremo inf. Run Throughput 0,8428 0,83663 0,8231 15 0,84391 0,83663 0,81492 10 Estremo sup. GreatSPN Estremo inf. Run Utilizzazione servitore 1 0,6520 0,6445 0,63606 15 0,6503 0,6445 0,6287 10 Estremo sup. GreatSPN Estremo inf. Run Utilizzazione servitore 2 52,64 57,30 46,30 15 52,16 57,30 44,04 10 Estremo sup. GreatSPN Estremo inf. Run Tempo medio di permanenza

×