Recuperare tutte le risposte
Gestione di input-output
Fabio Massimo Zanzotto
(slides di Andrea Turbati)
University of Rome “Tor Vergata”
Ricordando
!
fail
true
assert
retract
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Trovare tutte le soluzioni
• Talvolta potrebbe essere utile avere tutte le
risposte ad una query su una lista.
Esempio:
/*padre(PADRE,FIGLIO)*/
padre(gino,pino).
padre(gino,rino).
padre(gino,dino).
…
Scrivere un predicato:
/*figli(PADRE,FIGLI)*/
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Possibile soluzione
figli(X,Y):assert(figli_appoggio([])),
figli_w(X,Y).
figli_w(X,_):padre(X,F),
figli_appoggio(Y),
assert(figli_appoggio([F|Y])),
retract(figli_appoggio(Y)),
fail.
figli_w(X,Y):!,
figli_appoggio(Y),
retract(figli_appoggio(Y)).
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
bagof, setof, findall
Il prolog fornisce queste built-in:
• bagof(+Template, :Goal, -Bag)
• setof(+Template, +Goal, -Set)
• findall(+Template, :Goal, -Bag)
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Analizziamo il bagof
bagof(+Template, :Goal, -Bag)
Unify Bag with the alternatives of Template, if
Goal has free variables besides the one sharing
with Template bagof will backtrack over the
alternatives of these free variables, unifying Bag
with the corresponding alternatives of Template.
The construct +Var^Goal tells bagof not to bind
Var in Goal. bagof/3 fails if Goal has no solutions.
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Esempio
foo(a, b, c).
foo(a, b, d).
foo(b, c, e).
foo(b, c, f).
foo(c, c, g).
© A.Turbati, F.M.Zanzotto
3 ?- bagof(C, foo(A, B, C), Cs).
A = a, B = b, C = G308, Cs = [c, d] ;
A = b, B = c, C = G308, Cs = [e, f] ;
A = c, B = c, C = G308, Cs = [g] ;
4 ?- bagof(C, A^foo(A, B, C), Cs).
A = G324, B = b, C = G326, Cs = [c, d] ;
A = G324, B = c, C = G326, Cs = [e, f, g] ;
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Analizziamo il setof
setof(+Template, +Goal, -Set)
Equivalent to bagof/3, but sorts the result using
sort/2 to get a sorted list of alternatives without
duplicates.
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Gestione dell’input/output
• Predicati base per gestire standard input/standard
output
Basic
put(CHAR).
get(CHAR).
nl.
For atoms and predicates.
write(ATOM). writeq(ATOM).
read(ATOM).
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
input/output stream
• Durante l’esecuzione di un programma Prolog
sono sempre attivi due stream di dati, uno di input
e uno di output:
– Current input stream
– Current output stream
• Di norma questi due stream coincidono con la
console utente
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Input/output stream
• È possibile cambiare i due stream da utilizzare
• see(Filename). setta il nuovo input stream
• seen. chiude l’input stream corrente
• tell(filename). setta il nuovo output stream
• told. chiude l’output stream corrente
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Apertura di uno stream
• È possibile avere più stream aperti, ma solo 2 sono
gli stream correnti di input e di output
• Per aprire uno stream:
open(+SrcDest, +Mode, ?Stream)
• La variabile Stream conterrà lo stream aperto e
verrà passata ai predicati che hanno bisogno di
interagire con esso (lettura o scrittura)
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Open
• open(+SrcDest, +Mode, ?Stream)
• SrcDest è l’identificativo dello stream da aprire (di
solito il path di un file)
• Mode:
–
–
–
–
© A.Turbati, F.M.Zanzotto
read
write
append (scrittura dalla fine del file)
update (scrittura dall’inizio del file)
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
read e write
• Per leggere dall’input stream un termine si può
usare read/1 o read/2
– read(-Term)
– read(+Stream, -Term)
• La read legge dei termini che finiscono con il
punto (ma in Term non mette il punto )
• Per scrivere un termine sull’output stream si può
usare write/1 o write/2
– write(+Term)
– write(+Stream, +Term)
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Esempio open/read/write
• Vedere l’esempio contenuto in prolog-5.pl
• Il file di input deve contenere dei termini, senza
spazi, che terminano con dei punti
• Il file di output conterrà la lista dei termini trovati
nel primo file (esclusi i punti alla fine) e tale lista
viene messa un termine per riga
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Esempio read/write console
cube:write('Next number, please:'),
read(X),
process(X).
process(stop):!.
process(N):C is N**3,
write('Cube of '), write(N),write(' is '),
write(C), nl,
cube.
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Eseguire delle query da un file
processFile(File):see(File),
processFile,
seen.
processFile :read(Query),
process(Query).
process(end_of_file):!.
process(Query):Query,
write(Query),
nl,
processFile.
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Manipolare i singoli caratteri
• In Prolog, oltre a leggere/scrivere i termini
completi, è possibile leggere/scrivere un carattere
alla volta
• In alcuni casi questo è preferibile, perché permette
di avere una maggiore libertà sul tipo di input da
analizzare
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Manipolare i singoli caratteri
• Per leggere i singoli caratteri esistono i seguenti
predicati:
–
–
–
–
get/1 -> get(-Char)
get/2 -> get(+Stream, -Char)
get0/1 -> get0(-Char) legge anche gli spazi
get0/2 -> get0(+Stream, -Char)
• Per scrivere
– put/1 -> put(+Char)
– put/2 -> put(+Stream, +Char)
• ATTENZIONE: tutte queste funzioni lavorano con il
codice ASCII dei caratteri (0-127)
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Esempio: copiare un file
• Per copiare interamente un file generico non si
può usare la read, perché si aspetta dei termini con
il punto finale
• La get0 invece non ha questa limitazione, lavora
sui singoli caratteri
• Vedere nel file prolog-5.pl la regola cloneFile
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Costruire e scomporre gli atomi
• In certi casi è richiesto di trasformare una
sequenza di caratteri in un atomo
• Il predicato name fa proprio questo:
– name(?AtomOrInt, ?String)
– String è la lista di caratteri (codici ASCII) che uniti
insieme danno l’atomo AtomOrInt
• Es:
– name(zx232, [122,120,50,51,50]).
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Costruire e scomporre gli atomi
• Usando la name è possibile creare dei nuovi atomi
a partire da atomi già esistenti, scomponendoli nei
caratteri ASCII corrispondenti e poi riunendoli
newAtom(Atom1, Atom2, NewAtom):name(Atom1, List1),
name(Atom2, List2),
append(List1, List2, NewList),
name(NewAtom, NewList).
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Dividere le parole in una frase
Prelevando da input, generare il predicato:
/*getsentence( Wordlist)*/
vero se in input c’è una sequenza di caratteri che
termina col punto e questa sequenza è messa in una
lista di parole.
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Dividere le parole in una frase
getsentence( Wordlist) :- get0( Char), getrest( Char, Wordlist).
getrest( 46, [] ) :- !.
% End of sentence: 46 = ASCII for '.'
getrest( 32, Wordlist) :- !, % 32 = ASCII for blank
getsentence( Wordlist).
% Skip the blank
getrest( Letter, [Word | Wordlist] ) :getletters( Letter, Letters, Nextchar), % Read letters of current word
name( Word, Letters),
getrest( Nextchar, Wordlist).
getletters( 46, [], 46) :- !. % End of word: 46 = full stop
getletters( 32, [], 32) :- !. % End of word: 32 = blank
getletters( Let, [Let | Letters], Nextchar) :- get0( Char),getletters( Char, Letters,
Nextchar).
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Esercizi
• Scrivere una regola che, presa una lista i cui elementi
sono a loro volta delle liste, stampi su ogni riga gli
elementi delle liste interne.
– ?- stampaLista([[1,a], [2,b]]).
– 1a
– 2b
• Scrivere un programma che data una stringa in input
(magari leggendola da un file) rimuova gli spazi
multipli trasformandoli in spazi singoli. Farne due
versioni:
– Una sia con get che get0
– Una solo con get0
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Esercizi
• Scrivere una regola che preso un nome al
singolare lo converta nel suo plurale. Usare solo i
nome che hanno un plurale regolare, come ad
esempio:
– rosa->rose
– gatto -> gatti
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
University of Rome “Tor Vergata”
Esercizio
Realizzare
/*duplicates(ListWithDuplicates,ListWithoutDuplicates).*/
© A.Turbati, F.M.Zanzotto
Logica per la Programmazione e la Dimostrazione Automatica
Scarica

Recuperare tutte le risposte. Gestione di input