ANYLOGIC V Una prima introduzione: processi, sistemi, agenti. AR 26 XI 04 AnyLogic Simulazione di processo Dinamica dei sistemi Simulazione ad agenti L’elemento fondamentale nella creazione dei modelli in AnyLogic è l’Active Object, che può essere utilizzato per modellare qualunque cosa: unità produttive, oggetti fisici, persone. Questo elemento è un’instance della Active Object Class: quando realizziamo un modello in Anylogic, sviluppiamo questo tipo di classi e definiamo le relazioni che fra queste intercorrono. Nelle librerie abbiamo già diverse classi a disposizione. L’Active Object Class fa riferimento a classi Java: la modellizzazione è sempre object-oriented, con tutti i vantaggi che ne conseguono. Possiamo decomporre gli elementi, incapsularli, riutilizzarli e generare più instances dalla stessa classe: le classi supportano ereditarietà, polimorfismo dei metodi… PROCESSI La simulazione di processo è supportata in AnyLogic per mezzo di una libreria ad eventi discreti che consente di modellizzare processi produttivi, sistemi di servizi, problemi di carattere logistico. Prendiamo in considerazione la realizzazione di un elementare processo produttivo, costituito da una unità produttiva e due nastri trasportatori, uno in entrata ed uno in uscita. I pezzi arrivano per la lavorazione ad intervalli cadenzati secondo una distribuzione esponenziale (media 10): l’unità processa un pezzo alla volta, sempre casualmente e secondo la medesima distribuzione. I nastri si muovono a velocità costante, ogni componente ne occupa 10 piedi di lunghezza. Il diagramma di flusso E’ composto dai seguenti elementi: queue source # # # sink conv eyor1 # SZ/CAP #ARR REM queue1 delay conv eyor # SZ/CAP AV SZ # SZ/CAP ACC Q # # LAST VAL UTIL #ARR SZ/CAP AV SZ # SZ/CAP ACC Q # INTERARR L’oggetto sorgente genera gli elementi secondo gli intervalli temporali specificati; Le parti generate devono essere inserite in una coda, dal momento che il nastro trasportatore ha una velocità fissa, ma le parti arrivano ad intervalli casuali; L’oggetto delay modella l’unità produttiva “perdendo tempo” nel processare il pezzo arrivato; Dal momento che anche il tempo di lavorazione è casuale, avremo bisogno di un contenitore, ovvero un’altra coda, per il nastro trasportatore successivo. DINAMICA DEI SISTEMI Il modello descrive il processo di diffusione di un prodotto: i potenziali acquirenti sono invogliati all’acquisto dalla pubblicità e dal passaparola di coloro che lo hanno già acquistato. La logica della SD impone di pensare al modello in termini di stock e flussi: consumatori e consumatori potenziali saranno stock, un flusso il tasso di acquisto. In AnyLogic gli stock sono variabili espresse in forma di differenziale; i flussi sono variabili che raccolgono diverse componenti per mezzo di un espressione; le costanti sono parametri della classe di riferimento; le variabili ausiliarie sono variabili descritte per mezzo di un espressione. La diffusione di prodotto in SD Avremo: 2 stock: Customers, Potential_Customers; 1 flusso: Adoption_Rate; 4 costanti: Total_Population, Advertising_Effectiveness, Contact_Rate, Adoption_Fraction; 2 variabili ausiliarie: Adoption_From_Advertising, Adoption_From_Word_Of_Mouth P otential_C ustomers C ustomers A doption_Rate A doption_F rom_A dv ertising A doption_F rom_Word_O f_Mouth I rapporti di causa-effetto della consueta rappresentazione grafica di SD derivano dalle dichiarazioni formali circa le relazioni fra gli elementi del modello. Equations d(Customers)/dt = Adoption_Rate d(Potential_Customers)/dt = -Adoption_Rate Adoption_Rate = Adoption_From_Advertising+Adoption_From_Word_Of_Mouth Adoption_From_Advertising = Advertising_Effectiveness*Potential_Customers Adoption_From_Word_Of_Mouth = Contact_Rate*Adoption_Fraction*Potential_Customers*Customers/Total_Population AGENTI Sviluppiamo il modello di diffusione del prodotto, ma secondo la logica ad agenti, e aggiungendo successivamente alcuni elementi in più. Definiamo la struttura interna degli agenti utilizzando la active object class, e quindi creando il necessario numero di istanze della classe, ciascuna delle quali rappresenta il singolo agente. Inseriamo l’agente nell’ambiente del modello, incapsulando l’oggetto che modella l’agente nella classe che modella l’ambiente. Le caratteristiche degli agenti: i parametri della classe, le variabili ausiliarie Definiamo le caratteristiche degli agenti per mezzo dei parametri della classe: indichiamo i parametri nelle Properties della classe. Definiamo nome, tipo, valore, visibilità. Abbiamo nel nostro caso tre parametri: la suggestionabilità tramite la pubblicità delle persone; il numero di contatti che ogni individuo intrattiene in un anno; la forza di persuasione di ciascun individuo. Abbiamo inoltre necessità di creare delle variabili relative ai nostri agenti, per poter dialogare con l’ambiente e per conoscere lo stato dell’agente. Le variabili le creiamo trascinandole all’interno del diagramma della classe in questione: model: (Main)getOwner(), questo metodo restituisce l’oggetto che incapsula quello della variabile . isAdopter: ci permette di sapere se l’agente sia un consumatore effettivo o potenziale. E’ una variabile di tipo Booleano, il cui valore iniziale è false: all’inizio tutti gli agenti sono non consumatori. Definire il comportamento degli agenti – gli statecharts Il comportamento degli agenti è definito per mezzo dei diagrammi di stato: il diagramma è da inserire nella classe. Nel nostro caso definiamo due stati: quello di consumatore potenziale, lo stato iniziale: l’agente non è un consumatore fino a che questo stato è attivo; quello di consumatore effettivo: l’agente diviene consumatore all’attivarsi di questo stato. I due stati sono connessi tramite una transizione: il comportamento della transizione è definito nelle proprietà. La transizione avviene (Fire) dopo il timeout (After Timeout), vale a dire ad ogni tot di tempo, calcolato tramite un’espressione. Nel nostro caso il valore del timeout è dato dall’espressione: exponential(Ad_Effectiveness). In altri termini, la transizione modella l’acquisto del prodotto: il tempo necessario per decidere di comprare il prodotto dipende secondo una distribuzione casuale esponenziale dalla suggestionabilità alla pubblicità degli individui. Rendere quantitativo il modello Il nostro obiettivo è studiare in che modo si diffonde il nuovo prodotto: abbiamo bisogno di sapere quante persone acquistano il prodotto ad ogni dato momento. Con due variabili calcoliamo quanti sono i consumatori potenziali e quanti quelli effettivi: MAIN: potential_adopters, adopters; real, Init=0 Le due variabili sono naturalmente aggiornate da ciascuno dagli agenti: il modo in cui avviene l’aggiornamento fa parte del comportamento degli individui. Avremo, per quanto riguarda gli stati del diagramma: PotentialAdopter Entry action model.potential_adopters++; model.setModified(); isAdopter=false; Exit action model.potential_adopters--; model.setModified(); Adopter Entry action model.adopters++; model.setModified(); isAdopter=true; Exit action model.adopters--; model.setModified(); Il passaparola L’effetto della pubblicità influenza solo il primo periodo di vita del prodotto: successivamente gli acquirenti aumentano principalmente in seguito alla conoscenza di chi già ha acquistato il prodotto. Allo stato che si attiva quando l’agente diviene un consumatore, aggiungiamo allora una transizione interna così descritta: Timeout exponential(Contact_Rate*Adoption_Fraction) Action int r = uniform_discr(model.people.size()-1); Person p = model.people.item(r); p.adoption.fireEvent( "buy" ); Abbiamo inoltre una nuova transizione dallo stato PotentialAdopter a quello Adopter, che modella l’acquisto del prodotto conseguente al passaparola. Avremo nelle proprietà: Fire If signal event occurs Signal event "buy" Una logica di consumo Non abbiamo considerato che il prodotto possa essere consumato, scartato o migliorato, il che comporterebbe un acquisto ripetuto: a tal fine assumiamo allora che un consumatore divenga nuovamente un potenziale quando la prima unità acquistata viene scartata o consumata. Definiamo il tempo di vita del prodotto, ovvero dopo quanto tempo il bene acquistato viene scartato o consumato: parametro nel Main: Discard_Time,real, val=1 (1 anno di vita del prodotto), global; Inoltre modifichiamo il comportamento degli agenti, che adesso deve tenere conto del fatto che dopo 1 anno di vita il prodotto non è più utile: inseriamo una nuova transizione dallo stato Adopter a PotentialAdopter, con proprietà Fire After Timeout Timeout Main.Discard_Time La dimensione territoriale Possiamo definire la posizione nello spazio degli agenti, come caratteristica degli stessi, in modo da influenzare il tasso di contatto. Creiamo quindi una funzione che sia in grado di calcolare la distanza fra i vari agenti nello spazio. La funzione è interna alla classe person. Infine aggiorniamo il comportamento dei nostri agenti intervenendo sullo statechart, di modo che coloro che sono già consumatori contattino solo i propri vicini. Dal momento che a descrivere il passaparola è la transizione interna allo stato Adopter, la modifichiamo come segue: Action Person p; do { p = model.people.item( uniform_discr( model.people.size() - 1 ) ); } while( distance( p.x, p.y ) > 25 ); p.adoption.fireEvent( "buy" ): Campagne pubblicitarie Fin qui nel modello consideriamo la pubblicità come costante in ogni periodo: ma in realtà le campagne si tengono periodicamente in modo da aumentare le vendite in una particolare regione. Modelliamo le campagne pubblicitarie per mezzo di un timer, ovvero un generatore di eventi: ChartTimer adTimer Timeoutuniform(0.5,1) Expire At Startup No Expiry Action adX=uniform(adRange,300-adRange); adY=uniform(adRange,300-adRange); adTime=getTime(); for (int i=0;i<people.size();i++) { Person p= people.item(i); if(p.distance(adX,adY)<adRange) p.adoption.fireEvent("buy"); } Eliminiamo la transizione, dal momento che il cambiamento di stato non è più funzione della sensibilità alla pubblicità: ora, questa situazione è modellata territorialmente, e se l’agente si trova in una zona in cui c’è pubblicità, compra. Agenti in movimento Per rendere ancora più realistico il modello, facciamo sì che i nostri agenti possano muoversi fra le diverse aree. Nella classe Person aggiungiamo tre variabili ausiliarie, due per le coordinate sul piano, una per indicare il momento in cui l’agente si muove. Il movimento lo modelliamo ancora per mezzo di un timer: quindi sempre tramite una logica event-driven. ChartTimer moveTimer Timeout uniform( 5, 10 ) Expire At Startup No Expiry Action oldx = x; oldy = y; tmoved = getTime(); x = triangular( 0, 150, 300 ); y = triangular( 0, 150, 300 ); Inoltre sfruttiamo una algorithmic function per fare lo smoothing della grafica dell’agente in movimento Migrazioni di agenti L’ultimo passo è la modellizzazione dell’ingresso di nuovi agenti nell’ambiente, o dell’uscita di alcuni dallo stesso. Quello che allora dovremo fare sarà creare nuovi agenti ad intervalli determinati, ed eliminarne degli altri, in modo da rendere variabile la popolazione all’interno del modello. Usiamo due timer. Il primo, quello relativo all’immigrazione nell’area, lo inseriamo nella classe Main: ChartTimer inMigration Timeout exponential( 20 ) Expire At Startup No Expiry Action setup_people( new Person(), 0) L’azione è nel metodo setup_agentObject(): il primo argomento specifica che l’agente della classe è creato, il secondo determina la posizione in cui creare l’oggetto replicato. Stiamo dunque replicando, dal Main, un’istanza della classe Person contenuta nell’oggetto People. Migrazioni di agenti(2) Quello relativo alla migrazione fuori dall’area lo inseriamo invece all’interno di Person: ChartTimer outMigration Timeout exponential(0.02) Expiry Action model.dispose_people( Person.this ); if (isAdopter) model.adopters--; else model.potential_adopters--; Rimuoviamo l’agente per mezzo del metodo dispose_agentObject(). L’argomento della funzione definisce quale agente debba essere rimosso: l’espressione AgentClass.this indica che proprio quello è l’agente da rimuovere. Obbiettivo ultimo: modelli ibridi? Modelli per il prossimo futuro Patatrac: Simulazione del processo di affidamento: prima per processi, poi ad agenti AR 26 XI 04