Software per l`identificazione di una RdP deterministica

Transcript

Software per l`identificazione di una RdP deterministica
Software per l’identificazione
di una RdP deterministica
A cura di:
Mauro Franceschelli
Simone Secchi
Pagina web:
http://www.diee.unica.it/∼giua/ARP/PROGETTI/FS
Contenuto:
1.…………..Introduzione
2.1…………Script interfaccia.m
2.2…………Funzione pnetfind.m
2.2.1……….Funzione conversione.m
2.2.2……….Funzione complementa.m
2.2.3……….Funzione D2linguaggio.m
2.2.4……….Funzione vincoli.m
2.2.5……….Funzione scrivifile.m
2.3…………Funzione leggidalindo.m
2.4…………Funzione langfind.m
3.…………..Conclusione
4.…………..Esempio
1
1. Introduzione
Il lavoro trattato di seguito fornisce una procedura automatica per l’identificazione di una
RdP deterministica basandosi sulla conoscenza di una parte del suo linguaggio generato,
comprendente tutte le sequenze di transizioni abilitate di lunghezza non superiore ad un valore noto
a priori. Come chiarito in [1] , le proprietà del linguaggio di cui si è a conoscenza definiscono un
insieme di vincoli strutturali per la RdP da identificare (cioè vincoli sulle sue matrici Pre e Post) e
un insieme di vincoli sulla sua marcatura iniziale M0. E’ possibile ricercare una soluzione ottima
(che minimizzi cioè le dimensioni totali della rete) per tale insieme di vincoli avvalendosi
dell’ausilio di un risolutore automatico (nel nostro caso LINDO ver. 6.01) .
Al fine di facilitare e velocizzare la fase di identificazione e testing della soluzione sono
state sviluppate diverse funzioni MATLAB; queste si occupano di:
1. Acquisire da tastiera le diverse sequenze di transizioni appartenenti al linguaggio
della RdP da identificare
2. Generare automaticamente il file di testo da presentare in ingresso al risolutore
LINDO , contenente i vincoli di cui sopra e in [1]
3. Leggere il file di testo generato dal risolutore, acquisire i valori della soluzione,
costruire le matrici Pre, Post, il vettore M0 di marcatura iniziale e salvarli in
opportune strutture dati MATLAB (matrici e vettore)
4. Costruire il linguaggio della RdP identificata a partire dalla conoscenza di Pre, Post,
M0 ricavate sopra, contenente le parole abilitate dalla rete di lunghezza non
superiore ad un valore specificato.
In particolare, le prime due caratteristiche enunciate sopra automatizzano l’acquisizione dei
dati e l’identificazione della rete, mentre le ultime due facilitano notevolmente la verifica della
correttezza della soluzione trovata.
2
2.1 Script “Interfaccia.m”
Introduzione
Lo script ‘interfaccia.m’ è stato implementato per rendere più semplice ed immediato l’ uso
del pacchetto software per la produzione del file di testo Lindo.
Parametri in ingresso:
nessuno al momento della chiamata
Parametri in uscita:
1. File di testo per Lindo
2. Tutte le variabili inizializzate al suo interno saranno disponibili al prompt di matlab ad
esempio per utilizzare la più veloce funzione ‘pnetfind.m’ senza dover ogni volta reinserire
gli stessi dati nel caso di simulazioni fallite dentro LINDO per cause esterne o
semplicemente se il nome file inserito era già esistente.
Implementazione:
Lo script interfaccia è un semplice elenco di richieste di input da tastiera con l’accortezza di
ridurre al minimo i dati richiesti all’ utente. I dati in ingresso riguardanti le parole del linguaggio e i
cicli sono inseriti in una struttura dinamica di celle che si espande man mano che l’ utente inserisce
i dati. Una volta che tutti i dati sono inseriti ‘interfaccia.m’ converte l’ array di celle in un array di
stringhe per fornire il corretto input a ‘pnetfind.m’.
Conclusione
Lo script è utile per inserire velocemente i dati da tastiera se non si vuole perdere tempo nel
creare l’ array di stringhe in matlab e non si è pratici della sintassi di ‘pnetfind.m’. Lo script darà
errore quando ‘pnetfind.m’ non ha dati in ingresso corretti. Gli errori più frequenti sono:
1. inserire la parola vuota: essa è già presente di default essendo un linguaggio chiuso per
prefisso
2. inserire le transizioni usando altre notazioni: es. T1 al posto di t1
3. inserire un numero di transizioni inferiori al numero totale di transizioni: le transizioni
mancanti saranno considerate presenti ma mai abilitate.
4. Inserire nei cicli un numero di elementi inferiore o superiore al numero di transizioni.
5. Inserire il nome di un file già esistente
Inoltre se ci si accorge di aver fatto un errore in una riga precedente alla corrente occorre terminare
lo script e riavviarlo.
3
2.2 Funzione “pnetfind.m”
Prototipo
pnetfind(path,linguaggio,posti,ntransizioni,kgrande,kpiugrande,invarianti)
Introduzione
Questa funzione consente, dati in ingresso il linguaggio generato dalla RdP ed altri
parametri ad esso relativi, di generare automaticamente un file di testo per il risolutore Lindo ed
ottenere quindi una soluzione ai vincoli proposti in [1] riguardanti una RdP senza funzione di
etichetta. Essa è eseguibile dal prompt di MATLAB 7 e produce file di testo leggibili da una
versione di LINDO pari o superiore alla 6.01 .
Parametri in ingresso
1. Il percorso del file da creare ed il nome del file completo dell’estensione desiderata.
2. Il linguaggio della RdP contenente tutte le sequenze di scatto consentite dalla marcatura
iniziale; tale linguaggio deve essere chiuso per prefisso, comprendere la parola vuota ed
essere passato come array di stringhe tutte della stessa lunghezza (aggiungere spazi vuoti per
parole più corte) con le parole nelle righe. Inoltre le parole devono essere composte da una
qualunque combinazione delle stringhe ‘t1’,’t2’,’t3’…’tn’ i quali indici non possono
superare il numero massimo di transizioni inserito dall’ utente come parametro. Se un indice
è saltato la transizione sarà considerata presente ma mai abilitata. La parola vuota è indicata
con la stringa ‘e0’.
3. Numero di posti massimo consentito alla RdP
4. Numero di transizioni presenti nella RdP
5. Una costante ‘K’ arbitrariamente grande occorrente a LINDO nella risoluzione dei vincoli di
blocco
6. Una ulteriore costante ‘K’ arbitrariamente grande occorrente a Lindo per la minimizzazione
della RdP
7. Eventuali cicli presenti nella RdP: questi devono essere passati come matrice di interi che
avrà per colonne il numero di transizioni, per righe il numero di cicli desiderati e per
argomento la somma algebrica del numero di volte che la transizione è incontrata nel ciclo
tenendo conto del verso. Es. : una RdP con 3 transizioni e un ciclo t1t2 avrà in ingresso [1 1
0]. Questo parametro può essere omesso.
Parametri in uscita
File di testo generato nella directory definita nel percorso col nome ed estensione indicato dall’
utente contenente i vincoli proposti in [1] .
1. I vincoli sulle parole appartenenti al linguaggio E delle parole abilitate sono raggruppati per
parole e riconoscibili da un commento indicante la parola di E a cui si riferiscono.
2. I vincoli sulle parole appartenenti al linguaggio D delle parole disabilitate sono raggruppati
per parole e riconoscibili da un commento indicante la parola di D a cui si riferiscono,
preceduta dal simbolo ¬.
3. I restanti vincoli non sono commentati ma facilmente riconoscibili in quanto separati da
righe vuote se appartenenti a gruppi diversi.
4
Implementazione
Avviata la funzione essa esegue un primo check sul percorso del file indicato dall’ utente per
verificare che non sia già esistente. Se è già esistente l’ utente viene avvisato ed il programma
termina. In caso contrario essa procede al calcolo della lunghezza del linguaggio che verrà richiesto
in seguito come parametro in ingresso delle altre funzioni richiamate. A questo punto vengono
richiamate nel seguente ordine le funzioni: ‘conversione.m’, ’complementa.m’, ’D2linguaggio.m’,
’vincoli.m’ e ’scrivifile.m’. Nella chiamata alla funzione ‘vincoli.m’ viene verificata la condizione
sul numero di parametri in ingresso nel caso sia stato omesso il parametro riguardante i cicli.
Conclusione
L’ implementazione modulare ha consentito un veloce debug e rende possibile un eventuale
espansione del programma a partire dalla struttura dati illustrata in ‘conversione.m’. Essa è stata
testata su vari linguaggi di prova ed il file di testo è sempre stato generato correttamente a partire
dalla coerenza dei dati in ingresso. La produzione del file di testo ovviamente non prova che
LINDO sia in grado di risolvere il problema in un tempo ragionevole o che esista una soluzione.
5
2.2.1 Funzione “conversione.m”
Prototipo
matriceE=conversione(linguaggio,k,ntransizioni)
Introduzione
La funzione “conversione” consente di cambiare la rappresentazione del linguaggio in
ingresso tramite array di stringhe con una matrice di interi più maneggevole per la funzione che
deve scrivere i vincoli.
Parametri in ingresso
1. Array di stringhe contenente nelle righe le parole del linguaggio.
2. Lunghezza della parola più lunga
3. numero di transizioni
Parametri in uscita
Matrice di interi rappresentante il linguaggio in ingresso
Struttura dati
La matrice di interi avrà dimensioni (numero di parole + la parola vuota)x(dimensione della
parola più lunga divisa per 2). Notare che la dimensione della parola più lunga viene divisa per 2
solo perché in linguaggio ogni transizione è rappresentata con 2 caratteri, quindi una parola di 2
transizioni avrà ad esempio 4 caratteri essendo però di lunghezza 2.
In ogni riga è presente una parola del linguaggio in ingresso, in ogni blocco di dimensione (numero
delle transizioni+1) (perché c’è ‘e0’) sono presenti tutte le transizioni nelle colonne, una di loro, se
presente, conterrà 1; tutte le altre 0. Esempio:
Linguaggio: ‘e0 ’ ; ‘t1 ’ ; ‘t1t2’
Matrice in uscita:
‘e0’
‘e0 ’ 1
‘t1 ’ 0
‘t1t2’ 0
‘t1’
0
1
1
‘t2’
0
0
0
‘e0’
0
0
0
‘t1’
0
0
0
‘t2’
0
0
1
Implementazione
La funzione è implementata con un semplice ciclo che scandisce il linguaggio in ingresso
per colonne e poi per righe, inserendo, quando incontra una stringa uguale a quelle generate come
paragone, un 1 nella posizione corrispondente della matrice. La matrice è poi salvata come matrice
sparsa per risparmiare memoria durante l’ elaborazione.
6
Conclusione
Questa funzione consente un’ interfaccia semplice per l’ utente che deve semplicemente
ricopiare le parole del linguaggio come ingresso, mentre alle successive funzioni restituisce una
struttura dati che è stata molto più maneggevole e di aiuto durante l’ implementazione del resto del
programma.
7
2.2.2 Funzione “complementa.m”
Prototipo
matriceD=complementa(matriceE,k,ntransizioni)
Introduzione
Questa funzione si occupa di costruire il linguaggio D , contenente le parole di lunghezza
non superiore a “k” , che dovranno essere disabilitate dalla RdP che si vuole identificare. Queste
parole definiranno poi un insieme di vincoli “di blocco” sulla rete considerata.
Parametri in ingresso
1. Il primo parametro è una matrice rappresentante il linguaggio E di parole abilitate; la struttura di
questa matrice è la stessa della matrice restituita in uscita dalla funzione “conversione.m”. Se il
linguaggio E contenesse ad esempio parole di lunghezza non superiore a 3 (quindi k=3) e se il
numero di transizioni fosse 4 (quindi n=4) le dimensioni della matrice E sarebbero:
• Tante righe quante sono le parole comprese nel linguaggio E
• k blocchi di colonne, ciascuno contenente un numero di colonne pari a n+1 (per tenere
conto della ipsilon-transizione); nel nostro esempio quindi risulterebbero k*(n+1)=15
colonne.
2. Il secondo parametro in ingresso, k, rappresenta la massima lunghezza delle parole appartenenti
al linguaggio generato dalla rete, quindi anche la massima lunghezza delle parole appartenenti al
linguaggio E.
3. L’ultimo parametro in ingresso, ntransizioni, rappresenta il numero di transizioni della RdP che
si vuole identificare.
Parametri in uscita
La funzione restituisce una matrice D, che rappresenta il linguaggio D con lo stesso criterio
con cui la matrice E in ingresso rappresenta il linguaggio E. Essa avrà dunque tante righe quante
sono le parole di lunghezza non superiore a k che devono essere disabilitate dalla rete; le colonne
saranno ancora raggruppate in k blocchi, ciascuno avente (n+1) colonne corrispondenti alle
transizioni (epsilon-transizione compresa).
Implementazione
Poiché ogni riga della “matriceE” rappresenta una parola, nel vettore “lenvect”
compariranno le lunghezze delle varie parole abilitate.
Per le parole di lunghezza unitaria si dovranno semplicemente individuare le transizioni mancanti
rispetto all’insieme di transizioni T e si dovrà inserire, per ognuna di esse, una riga nella matriceD
in cui viene posto a 1 l’elemento corrispondente alla transizione mancante (nel primo blocco poiché
la lunghezza è unitaria).
Per le parole di lunghezza superiore il criterio seguito per aggiungere righe alla matriceD è questo:
• per ogni riga della matriceE si cerca l’indice del blocco composto solo da zeri (indicato con
“last”)
• se questo indice non è maggiore di k si completa la riga di matriceE aggiungendo una
transizione (quindi scrivendo nel blocco vuoto un 1) in n modi possibili (uno per ogni
8
•
•
transizione) e si confronta quale di questi modi non compare nella matriceE. Tutti i
completamenti che non compaiono nella matriceE vanno aggiunti nella matriceD , perché
corrispondono a parole “σ tj” tali che “σ” appartiene al linguaggio L mentre “σ tj” non vi
appartiene (cioè parole che per definizione appartengono al linguaggioD).
Nel caso in cui le parole di lunghezza 1 siano tutte rappresentate nella matriceE la prima
riga della matriceD resta vuota, ragion per cui alla fine del codice compare un check che in
caso positivo elimina tale riga.
Infine viene convertita la matriceD in matrice sparsa per ragioni di occupazione di memoria,
dal momento che tale matrice potrebbe avere anche dimensioni molto elevate ma pochi
elementi diversi da zero.
Conclusione
Questa funzione consente di ottenere il linguaggio D di parole disabilitate, sotto forma di
matrice D, senza bisogno di chiederlo in input all’utente. Inoltre, chiamando questa funzione e
passando il suo risultato alla funzione “D2linguaggio.m” si può facilmente ottenere il linguaggio D
sotto forma di array di stringhe, al fine di una verifica intermedia per ispezione visiva.
9
2.2.3 Funzione “D2linguaggio.m”
Prototipo
linguaggioD=D2linguaggio(D,k,ntransizioni);
Introduzione
Questa funzione consente la riconversione della matrice di interi illustrata in
‘conversione.m’ in un array di stringhe contenente il linguaggio.
Parametri in ingresso
1. Matrice di interi rappresentante il linguaggio
2. Lunghezza della parola più lunga
3. Numero di transizioni
Parametri in uscita
Array di stringhe contenente il linguaggio rappresentato dalla matrice in ingresso
Implementazione
Un semplice ciclo che scandisce per righe la matrice di interi e una volta trovato un 1
riconosce la corrispondente transizione e la copia nell’ array di stringhe.
Conclusione
Questa funzione è stata molto utile in fase di debug in quanto consente di verificare
velocemente la coerenza delle strutture dati che sono utilizzate per la generazione dei vincoli.
Inoltre è utilizzata dalla funzione vincoli per scrivere i commenti sulle parole disabilitate
(linguaggio D) non inserito dall’ utente e generato da ‘complementa.m’ direttamente come matrice
di interi a partire dalla matrice del linguaggio E.
10
2.2.4 Funzione “vincoli.m”
Prototipo
file=vincoli(matriceE,matriceD,posti,ntransizioni,k,linguaggio,kgrande,kpiugrand
e,invarianti)
Introduzione
Questa funzione è la parte principale del corpo “pnetfind.m”, in quanto è qui che
effettivamente viene generato il contenuto esatto del file di testo che poi sarà presentato in ingresso
al risolutore LINDO. Essa scrive sotto forma di stringhe tutti i vincoli di abilitazione, i vincoli di
blocco e quelli di minimizzazione della rete, inoltre definisce tutte le variabili necessarie al
risolutore per procedere.
Parametri in ingresso
1. Il primo parametro in ingresso è la matrice E, rappresentante il linguaggio E delle parole
abilitate, che viene restituita dalla funzione “conversione.m”
2. Il secondo parametro in ingresso è la matrice D, rappresentante il linguaggio D delle parole
disabilitate, che viene restituita dalla funzione “complementa.m”
3. Il terzo parametro in ingresso è il numero massimo di posti che la RdP da identificare potrà
avere. E’ bene notare che tale valore è un valore massimo e la soluzione fornita dal
risolutore può anche rappresentare una rete con un numerosi posti inferiore (per maggiori
dettagli si veda “leggidalindo.m”)
4. Il quarto parametro in ingresso rappresenta il numero di transizioni della rete.
5. Il quinto parametro in ingresso rappresenta la massima lunghezza delle parole appartenenti
al linguaggio E (o equivalentemente del linguaggio D).
6. Il sesto parametro è un array di stringhe contenente tutte le parole del linguaggio E,
necessario per inserire nel file di testo i commenti relativi a ciascun insieme di vincoli.
7. Il settimo e l’ottavo parametro in ingresso sono due costanti intere sufficientemente grandi
necessarie al risolutore per il calcolo della soluzione ottima (numero minimo di posti e
numero minimo di archi della rete). Si noti che l’ottavo parametro deve essere almeno un
ordine di grandezza superiore al settimo.
8. Il nono parametro, una matrice di interi chiamata “invarianti”, è di particolare importanza
perché rappresenta un ulteriore vincolo che l’utente può decidere di specificare per la RdP
da identificare . Nel caso tra i parametri con cui viene chiamata la funzione “vincoli.m” sia
presente in ultima posizione tale matrice si scriveranno allora anche i vincoli relativi ai Tinvarianti della rete (cioè vincoli del tipo [Post-Pre]*y=0) ; nel caso in cui tale matrice non
sia invece specificata tra i parametri in ingresso la funzione non scriverà nessun vincolo per
gli invarianti sulla RdP da identificare.
Parametri in uscita
La funzione restituisce un array di celle (denominato“file”) in cui ogni riga è una riga del
file di testo da passare in input al LINDO.
Implementazione
Sebbene questa sia la funzione più corposa (in termini di righe di codice) tra tutte quelle
scritte, il suo funzionamento è abbastanza semplice.
11
Nella prima parte si dichiarano tutte le variabili come array di celle (unidimensionali nel caso dei
vettori “z” e “M0” e bidimensionali nel caso delle matrici Pre, Post e S) in cui ogni cella contiene
stringhe di lunghezza variabile.
Nella seconda parte si scrive la prima riga del file LINDO, costruendola pezzo per pezzo dentro una
variabile stringa temporanea denominata “temp”.
Nella terza parte si scrivono i vincoli di abilitazione: precisamente si avrà un vincolo “matriciale”
per ogni riga della matrice E , cioè per ogni parola del linguaggio E di parole abilitate; notare che il
meccanismo di scrittura delle righe sfrutta ancora la variabile temporanea “temp” e costruisce poco
per volta la riga di “file”. Ogni vincolo “matriciale” è identificato da una riga di commento in cui si
indica (dopo il carattere di escape “!”) la sequenza di transizioni abilitate. Si noti ancora che
“sigma” è il vettore di scatto (cioè che conta le tranaizioni) della parola “σ tj” mentre “sigma2” è il
vettore di scatto della parola “σ” , necessari per la scrittura del vincolo (vedasi anche [1]).
Nella quarta parte si scrivono i vincoli di blocco: il meccanismo che sta dietro tale procedura è del
tutto analogo a quanto esposto per la parte precedente, con l’unica differenza che, trattandosi ora di
vincoli di disabilitazione si dovrà scandire la matrice D e non la matrice E.
Nelle due parti seguenti si scrivono i vincoli sulle variabili binarie ausiliarie (matrice S e vettore z)
come esposto in [1].
Nella parte successiva si compongono i vincoli sui t-invarianti della rete (si noti il controllo su
“nargin” per verificare che effettivamente il parametro “invarianti” sia stato passato) considerando
ora il vettore “sigma” come il vettore di ciclo acquisito in input e presente nella matrice “invarianti”
Successivamente si devono elencare le variabili rispetto alle quali calcolare la soluzione,
specificando se siano definite sul campo degli interi positivi (descrittore “GIN”) o se siano variabili
binarie (descrittore “INT”).
Infine si fa una semplice trasposizione dell’array di celle per avere un array colonna.
Conclusione
Questa funzione ha il vantaggio di essere scritta in parti abbastanza indipendenti l’una
dall’altra, per cui si presta a facili modifiche da parte di terzi. Inoltre sia l’aggiunta di ulteriore
vincoli che la modifica di quelli attuali possono basarsi su un riuso efficace della stessa.
12
2.2.5 Funzione “scrivifile.m”
Prototipo
scrivifile(file,path)
Introduzione
Questa funzione consente di creare un nuovo file con nome e locazione impostati dall’
utente in cui ricopiare l’array di celle restituito dalla funzione ‘vincoli.m’.
Parametri in ingresso
1. Array di celle restituito da ‘vincoli.m’ contenente per ogni cella una riga del file di testo.
2. Il percorso completo del file.
Parametri in uscita
File di testo per LINDO.
Implementazione
La funzione apre il file e scrive riga per riga sul file copiandoci il contenuto della riga
corrispondente dell’ array di celle in ingresso. Siccome per un bug di MATLAB 7 non è possibile
usare come argomento di fprintf ‘\n’ per andare a capo il problema è stato risolto inserendo nella
direttamente nella stringa scritta sul file al termine della riga il carattere corrispondente in formato
ASCII che viene identificato correttamente come termine della riga da LINDO e dai più comuni
editor di testo.
Conclusione
Questa funzione è stata separata dal resto del programma in modo che l’ array di celle possa
essere incrementato dinamicamente, se ad esempio si volessero aggiungere ulteriori vincoli si
potrebbe sia modificare ‘vincoli.m’ anch’ essa costruita a blocchi separati oppure creare una
funzione nuova che prende in ingresso l’ array di celle di vincoli e restituisce l’ array di celle
aggiornato con le modifiche desiderate.
13
2.3 Funzione “leggidalindo.m”
Prototipo
[Pre Post M0]=leggidalindo(path,nposti,ntransizioni);
Introduzione
Questa funzione ha come obbiettivo di velocizzare la comprensione del file di testo restituito
da LINDO al termine della soluzione del problema di programmazione intera impostato da
‘pnetfind.m’. Essa leggi il file di teso prodotto da LINDO e restituisce in MATLAB 7 le matrici Pre
Post M0 che identificano la RdP.
Parametri in ingresso
1. Percorso del file LINDO contenente i risultati della simulazione
2. Numero di posti della RdP dati in ingresso a ‘pnetfind.m’
3. Numero di transizioni della RdP dati in ingresso a ‘pnetfind.m’
Parametri in uscita
Matrici Pre, Post, M0
Implementazione
La funzione legge il file di testo e lo copia in una stringa. Crea le stesse strutture dati con i
nomi delle variabili utilizzate per creare i vincoli da ‘vincoli.m’ e cancella tutto il file LINDO sino
alla frase precedente ai risultati. A questo punto cerca variabile per variabile l’ indice dell’inizio
della stringa corrispondente e prende come valore la conversione in intero della successiva stringa
delimitata da spazi vuoti che nel file prodotto da LINDO è appunto il valore della variabile. Una
volta ricavate le tre matrici le compatta eliminando gli eventuali posti superflui identificando le
righe completamente nulle in tutte e tre le matrici.
Conclusione
Questa funzione è molto utile per chiudere il cerchio con ‘pnetfind.m’ ed avere quindi una
soluzione veloce al problema posto in [1] senza dover decifrare e copiare a mano i risultati di
LINDO che nel caso di una RdP grande possono essere scomodi da leggere.
14
2.4 Funzione “langfind.m”
Prototipo
linguaggio=langfind(Pre,Post,M0,k)
Introduzione
Questa funzione consente, note le matrici Pre, Post e la marcatura iniziale M0, di costruire il
linguaggio generato dalla RdP corrispondente (a partire ovviamente dalla marcatura iniziale)
composto da parole di lunghezza fino ad un valore intero noto e passato come parametro in
ingresso.
Parametri in ingresso
1. Il primo parametro in ingresso è la matrice Pre caratteristica della rete, il secondo parametro
è invece la sua matrice Post.
2. Il terzo parametro è la marcatura iniziale M0, passata come vettore colonna.
3. Il quarto parametro è la lunghezza massima delle parole comprese nel linguaggio che si
vuole costruire.
Parametri in uscita
La funzione restituisce il linguaggio cercato sotto forma di array di stringhe, in cui ogni riga
dell’array è una diversa parola. Si noti che poiché la struttura è un array di stringhe (o
equivalentemente una matrice di caratteri) la lunghezza di tutte le stringhe deve essere la stessa, per
cui le parole più corte vengono completate con degli spazi.
Implementazione
Le principali strutture che sono state usate in questa funzione sono due matrici : “matriceM”
e “matriceL” strutturate e costruite come segue:
•
•
matriceM contiene due blocchi di colonne: le prime m colonne (tante quanti sono i posti
della rete) indicano una marcatura raggiunta, le altre k colonne (tante quanto può essere
lunga al massimo una parola del linguaggio che si vuole costruire) indicano la sequenza di
transizioni che ha portato alla marcatura a sinistra (ad esempio [1 0 0 | 1 2 0] indica la
marcatura [1 0 0] raggiunta con la parola “t1t2”)
matriceL sarà una matrice strutturata come si è esposto in “conversione.m” che conterrà le
parole del linguaggio costruito.
Per la costruzione della matriceM: per ogni riga si memorizza la marcatura in una variabile
temporanea (“Mtemp”) e poi (per tutte le transizioni possibili) si controlla (con un “if”) se la
transizione è abilitata e se la parola che ha portato a tale marcatura non sia già lunga k; nel caso l’if
dia esito positivo si calcola la nuova marcatura e si appende una nuova riga sulla matriceM,
compilando gli ultimi “n” elementi della riga con gli indici delle transizioni che hanno portato alla
nuova marcatura. (Si noti che le dimensioni della matriceM variano ad ogni ciclo del “while”
principale)
Dopo aver costruito tutta la matriceM, si può costruire la matriceL semplicemente leggendo, per
ogni riga della matriceM , gli ultimi “n” elementi, che sono proprio gli indici (con il giusto ordine)
delle transizioni delle parole abilitate.
15
Infine si converte la matriceL in un array di stringhe richiamando la funzione D2linguaggio.
Conclusione
L’utilità di questa funzione è doppia in quanto essa consente di:
• verificare la correttezza della soluzione fornita da LINDO del problema di identificazione di
una RdP noto il suo linguaggio (sarà infatti possibile acquisire le matrici Pre,Post e la
marcatura M0 con “leggidalindo.m” e richiamare poi “langfind.m”)
• costruire il linguaggio (fino alla lunghezza k) generato da una qualsiasi RdP di cui siano
note le matrici caratteristiche e di cui si voglia condurre una semplice analisi.
16
3. Conclusione:
Il pacchetto software fornito è in grado di testare velocemente e con facilità la soluzione del
problema posto in [1] per RdP senza funzione di etichetta. I vari moduli possono essere modificati
separatamente, inoltre la funzione ‘leggidalindo.m’ a patto di usare la stessa notazione per quanto
riguarda la rappresentazione di Pre, Post ed M0 può essere usata in contesti completamente diversi
con vincoli anche scritti direttamente dall’ utente. La funzione ‘langfind.m’ è utile ogni qualvolta
sia necessario produrre il linguaggio generato di una RdP date le sue matrici identificative.
Referenze:
[1] Maria Paola Cabasino, Alessandro Giua, Carla Seatzu. Identification of deterministic Petri nets
17
4. Esempio di utilizzo del set di funzioni
Supponiamo di voler identificare la RdP minima il cui linguaggio generato di lunghezza k=2 sia il
seguente:
L=[’e0
’
;
‘t1
’ ;
’t1t2’ ; ‘t1t3’]
Dal prompt di MATLAB 7 occorrerà richiamare lo script ‘interfaccia.m’ e seguire le istruzioni:
>> interfaccia
Inserire percorso e nome file : (es. c:\prova.ltx) : c:\esempio.ltx
Inserire il numero di posti massimo consentito alla rete di petri: 2
Inserire il numero di transizioni della rete di petri: 3
Ora saranno richieste le parole del linguaggio (esclusa la parola vuota),
premere invio senza inserire i dati per terminare
Inserire una parola :t1
Inserire una parola :t1t2
Inserire una parola :t1t3
Inserire una parola :
Ora saranno richiesti i cicli ad es. [1 2 0 -1] con 4 transizioni, premere invio
per terminare
Inserire ciclo: [1 1 0]
Inserire ciclo:
File creato in c:\esempio.ltx
A questo punto il file di testo esempio.ltx è stato creato ed è il seguente:
! FILE LINDO:
MIN 1000 z_1 + 1000 z_2 + mo_1 + mo_2 + e_1_1 + e_1_2 + e_1_3 + e_2_1 + e_2_2 +
e_2_3 + o_1_1 + o_1_2 + o_1_3 + o_2_1 + o_2_2 + o_2_3
SUBJECT TO
! t1
mo_1 - e_1_1 >= 0
mo_2 - e_2_1 >= 0
! t1t2
mo_1 + o_1_1 - e_1_1 - e_1_2 >= 0
mo_2 + o_2_1 - e_2_1 - e_2_2 >= 0
! t1t3
mo_1 + o_1_1 - e_1_1 - e_1_3 >= 0
mo_2 + o_2_1 - e_2_1 - e_2_3 >= 0
! ¬ t2
- 50 s_1_1 + mo_1 - e_1_2 <= -1
- 50 s_1_2 + mo_2 - e_2_2 <= -1
! ¬ t3
- 50 s_2_1 + mo_1 - e_1_3 <= -1
- 50 s_2_2 + mo_2 - e_2_3 <= -1
! ¬ t1t1
- 50 s_3_1 + mo_1 + o_1_1 - 2 e_1_1 <= -1
- 50 s_3_2 + mo_2 + o_2_1 - 2 e_2_1 <= -1
s_1_1 + s_1_2 <= 1
18
s_2_1 + s_2_2 <= 1
s_3_1 + s_3_2 <= 1
50 z_1 - e_1_1 - e_1_2 - e_1_3 - o_1_1 - o_1_2 - o_1_3 >= 0
50 z_2 - e_2_1 - e_2_2 - e_2_3 - o_2_1 - o_2_2 - o_2_3 >= 0
z_2 - z_1 <= 0
! ciclo 1
1
0
o_1_1 + o_1_2 - e_1_1 - e_1_2 = 0
o_2_1 + o_2_2 - e_2_1 - e_2_2 = 0
END
GIN mo_1
GIN mo_2
GIN
GIN
GIN
GIN
GIN
GIN
e_1_1
e_1_2
e_1_3
e_2_1
e_2_2
e_2_3
GIN
GIN
GIN
GIN
GIN
GIN
o_1_1
o_1_2
o_1_3
o_2_1
o_2_2
o_2_3
INT
INT
INT
INT
INT
INT
s_1_1
s_1_2
s_2_1
s_2_2
s_3_1
s_3_2
INT z_1
INT z_2
A questo punto occorre leggere il file da Lindo, risolverlo (comando veloce ctrl+s) e salvare il
report come file di testo, ad esempio risul.ltx. Il file prodotto sarà il seguente:
LP OPTIMUM FOUND AT STEP
6
OBJECTIVE VALUE = 0.000000000E+00
FIX ALL VARS.(
2)
SET
Z_1 TO >=
SET
S_3_1 TO >=
SET
Z_2 TO >=
WITH RC >
1 AT
1,
1 AT
2,
1 AT
3,
21.0000
BND= -1008.
BND= -1046.
BND= -2006.
TWIN=-0.1000E+31
TWIN= -1011.
TWIN=-0.1000E+31
NEW INTEGER SOLUTION OF
2006.00000
AT BRANCH
3 PIVOT
BOUND ON OPTIMUM: 127.0000
DELETE
Z_2 AT LEVEL
3
FLIP
S_3_1 TO <=
0 AT
2 WITH BND=
-1011.2800
SET
S_1_1 TO >=
1 AT
3, BND= -1050.
TWIN=-0.1000E+31
SET
S_2_1 TO >=
1 AT
4, BND= -1066.
TWIN=-0.1000E+31
SET
Z_2 TO >=
1 AT
5, BND= -2006.
TWIN=-0.1000E+31
DELETE
Z_2 AT LEVEL
5
DELETE
S_2_1 AT LEVEL
4
DELETE
S_1_1 AT LEVEL
3
DELETE
S_3_1 AT LEVEL
2
DELETE
Z_1 AT LEVEL
1
RELEASE FIXED VARIABLES
SET
Z_1 TO >=
1 AT
1, BND= -1009.
TWIN=-0.1000E+31
SET
S_3_1 TO >=
1 AT
2, BND= -1047.
TWIN= -1012.
72
80
86
86
92
94
95
143
151
19
SET
Z_2 TO >=
1 AT
3,
DELETE
Z_2 AT LEVEL
3
FLIP
S_3_1 TO <=
0 AT
SET
S_1_1 TO >=
1 AT
3,
SET
S_2_1 TO >=
1 AT
4,
SET
Z_2 TO >=
1 AT
5,
DELETE
Z_2 AT LEVEL
5
DELETE
S_2_1 AT LEVEL
4
DELETE
S_1_1 AT LEVEL
3
DELETE
S_3_1 AT LEVEL
2
DELETE
Z_1 AT LEVEL
1
ENUMERATION COMPLETE. BRANCHES=
BND=
-2007.
2 WITH BND=
BND= -1051.
BND= -1067.
BND= -2007.
12 PIVOTS=
TWIN=-0.1000E+31
159
-1012.2800
TWIN=-0.1000E+31
TWIN=-0.1000E+31
TWIN=-0.1000E+31
172
174
175
175
LAST INTEGER SOLUTION IS THE BEST FOUND
RE-INSTALLING BEST SOLUTION...
OBJECTIVE FUNCTION VALUE
1)
VARIABLE
MO_1
MO_2
E_1_1
E_1_2
E_1_3
E_2_1
E_2_2
E_2_3
O_1_1
O_1_2
O_1_3
O_2_1
O_2_2
O_2_3
S_1_1
S_1_2
S_2_1
S_2_2
S_3_1
S_3_2
Z_1
Z_2
ROW
2)
3)
4)
5)
6)
7)
8)
9)
10)
11)
12)
13)
14)
15)
16)
17)
18)
19)
20)
21)
2006.000
VALUE
0.000000
1.000000
0.000000
1.000000
1.000000
1.000000
0.000000
0.000000
1.000000
0.000000
0.000000
0.000000
1.000000
0.000000
0.000000
1.000000
0.000000
1.000000
1.000000
0.000000
1.000000
1.000000
SLACK OR SURPLUS
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
48.000000
0.000000
48.000000
48.000000
0.000000
0.000000
0.000000
0.000000
47.000000
48.000000
0.000000
0.000000
0.000000
NO. ITERATIONS=
175
BRANCHES=
12 DETERM.=
1.000E
REDUCED COST
1.000000
1.000000
1.000000
1.000000
1.000000
1.000000
1.000000
1.000000
1.000000
1.000000
1.000000
1.000000
1.000000
1.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
1000.000000
1000.000000
DUAL PRICES
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0
20
A questo punto dal prompt di matlab occorre lanciare la funzione ‘leggidalindo.m’ che chiede il
percorso, il numero di posti e il numero di transizioni:
>> [Pre Post M0]=leggidalindo('c:\risult.ltx',2,3)
Adesso nel work space di Matlab abbiamo la RdP rappresentata come matrici Pre Post e la
marcatura iniziale. In questo caso abbiamo:
Pre= [ 0 1 1 ; 1 0 0]
Post=[1 0 0; 0 1 0]
M0=[0 ; 1]
Per verificare che il linguaggio generato da questa rete corrisponde a quello dato in ingresso sino
alla lunghezza k=2, si può lanciare la funzione ‘langfind.m’ che chiede in ingresso le matrici Pre,
Post , M0 e la lunghezza della parola più lunga e restituisce il linguaggio sino alla lunghezza k :
>> [linguaggio]=langfind(Pre,Post,M0,2)
linguaggio =
e0
t1
t1t2
t1t3
E questo verifica la correttezza dell’ algoritmo.
Nota bene:
E’ possibile eseguire la stessa procedura evitanto di usare lo script ‘interfaccia.m’ ed usare
direttamente la funzione ‘pnetfind.m’ a cui però vanno passati per argomento tutti i parametri
necessari nel formato corretto. E’ possibile utilizzare l’ help su ‘pnetfind.m’ per avere su schermo la
corretta sintassi della funzione.
21