'Se' nel prologo?
-
27-09-2019 - |
Domanda
C'è un modo per fare un caso nel prologo, per esempio se una variabile è 0, quindi fare alcune azioni (testo scrittura al terminale). Un altro non è nemmeno necessario, ma non riesco a trovare alcuna documentazione di se.
Soluzione
Un predicato prologo di serie farà questo.
isfive(5).
valuterà a true se lo si chiama con 5 e di rifiuto (return false) se lo si esegue con qualsiasi altra cosa. Per non uguale si utilizza \ =
isNotEqual(A,B):- A\=B.
Tecnicamente è non unifica, ma è simile a non uguale.
Scopri Prolog Ora è un buon sito web per l'apprendimento Prolog.
Modifica: Per aggiungere un altro esempio.
isEqual(A,A).
Altri suggerimenti
Sì, c'è un tale costrutto di controllo ISO Prolog, chiamato ->
. Si utilizza in questo modo:
( condition -> then_clause ; else_clause )
Ecco un esempio che utilizza una catena di else-if-clausole:
( X < 0 ->
writeln('X is negative. That's weird! Failing now.'),
fail
; X =:= 0 ->
writeln('X is zero.')
; writeln('X is positive.')
)
Si noti che se si omette l'altra clausola, la condizione in mancanza significa che l'intero caso-statement fallirà. Pertanto, vi consiglio sempre compreso il else-clausola (anche se è solo true
).
Prolog predicati 'Unificare' -
Quindi, in un langauge imperativo che avrei scritto
function bazoo(integer foo)
{
if(foo == 5)
doSomething();
else
doSomeOtherThing();
}
In Prolog mi piacerebbe scrivere
bazoo(5) :- doSomething.
bazoo(Foo) :- Foo =/= 5, doSomeOtherThing.
, che, quando si capisce entrambi gli stili, è in realtà molto più chiara.
"Sono bazoo per il caso speciale quando foo è 5"
"Sono bazoo per il caso normale quando foo non è 5"
Ho trovato questo utile per l'utilizzo di un se dichiarazione in una regola.
max(X,Y,Z) :-
( X =< Y
-> Z = Y
; Z = X
).
Grazie alla http: //cs.union. edu / ~ striegnk / imparare-Prolog-ora / html / node89.html
Per prima cosa, ricordano un po 'di logica classica del primo ordine:
" Se P poi Q altro R" è equivalente a "(P e Q) o (non_P e R)".
Come possiamo esprimere "if-then-else" come che in Prolog?
Facciamo il seguente esempio concreto:
Se
X
è un membro della lista[1,2]
poiX
uguale2
altroX
uguale4
.
può abbinare al di sopra del modello ( " Se P poi Q altro R"), se ...
- condizione
P
èlist_member([1,2],X)
, - negato condizione
non_P
ènon_member([1,2],X)
, - conseguenza
Q
èX=2
, e -
R
alternativa èX=4
.
Per esprimere lista (non) l'appartenenza in modo puro, definiamo:
list_memberd([E|Es],X) :- ( E = X ; dif(E,X), list_memberd(Es,X) ). non_member(Es,X) :- maplist(dif(X),Es).
assegno emise modi diversi di esprimere "if-then-else" in Prolog!
-
(P,Q ; non_P,R)
?- (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4). X = 2 ; X = 4. ?- X=2, (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=2. X = 2 ; false. ?- (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=2. X = 2 ; false. ?- X=4, (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=4. X = 4. ?- (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=4. X = 4.
Correttezza punteggio 5/5. Efficienza punteggio 3/5.
-
(P -> Q ; R)
?- (list_memberd([1,2],X) -> X=2 ; X=4). false. % WRONG ?- X=2, (list_memberd([1,2],X) -> X=2 ; X=4), X=2. X = 2. ?- (list_memberd([1,2],X) -> X=2 ; X=4), X=2. false. % WRONG ?- X=4, (list_memberd([1,2],X) -> X=2 ; X=4), X=4. X = 4. ?- (list_memberd([1,2],X) -> X=2 ; X=4), X=4. false. % WRONG
Correttezza punteggio 2/5. Efficienza punteggio 2/5.
-
(P *-> Q ; R)
?- (list_memberd([1,2],X) *-> X=2 ; X=4). X = 2 ; false. % WRONG ?- X=2, (list_memberd([1,2],X) *-> X=2 ; X=4), X=2. X = 2 ; false. ?- (list_memberd([1,2],X) *-> X=2 ; X=4), X=2. X = 2 ; false. ?- X=4, (list_memberd([1,2],X) *-> X=2 ; X=4), X=4. X = 4. ?- (list_memberd([1,2],X) *-> X=2 ; X=4), X=4. false. % WRONG
Correttezza punteggio 3/5. Efficienza punteggio 1/5.
(preliminare) sintesi:
-
(P,Q ; non_P,R)
è corretto, ma necessita di un'implementazione discreta dinon_P
. -
(P -> Q ; R)
perde semantica dichiarativa quando istanziazione è insufficiente. -
(P *-> Q ; R)
è "meno" incompleta di(P -> Q ; R)
, ma ha ancora guai simili.
Fortunatamente per noi, ci sono alternative:
Inserisci il if_/3
logicamente monotono controllo costrutto!
Possiamo usare if_/3
unitamente alla lista-membership reificata predicato di memberd_t/3
in questo modo:
?- if_(memberd_t(X,[1,2]), X=2, X=4). X = 2 ; X = 4. ?- X=2, if_(memberd_t(X,[1,2]), X=2, X=4), X=2. X = 2. ?- if_(memberd_t(X,[1,2]), X=2, X=4), X=2. X = 2 ; false. ?- X=4, if_(memberd_t(X,[1,2]), X=2, X=4), X=4. X = 4. ?- if_(memberd_t(X,[1,2]), X=2, X=4), X=4. X = 4.
Correttezza punteggio 5/5. Efficienza punteggio 4/5.
La cosa migliore da fare è quella di utilizzare il cosiddetto cuts
, che ha il !
simbolo.
if_then_else(Condition, Action1, Action2) :- Condition, !, Action1.
if_then_else(Condition, Action1, Action2) :- Action2.
Quanto sopra è la struttura di base di una funzione condizione.
Per esemplificare, ecco la funzione max
:
max(X,Y,X):-X>Y,!.
max(X,Y,Y):-Y=<X.
Suggerisco di leggere ulteriore documentazione sui tagli, ma in generale sono come punti di interruzione.
Es .: Nel caso la prima funzione max
restituisce un valore vero, la seconda funzione non è verificato.
PS: Sono abbastanza nuovo per Prolog, ma questo è quello che ho scoperto
. Ci sono essenzialmente tre diversi modi per esprimere qualcosa come if-then-else in Prolog. Per confrontare le considerano char_class/2
. Per a
e b
la classe dovrebbe essere ab
e other
per tutti gli altri termini. Si potrebbe scrivere questo maldestramente in questo modo:
char_class(a, ab).
char_class(b, ab).
char_class(X, other) :-
dif(X, a),
dif(X, b).
?- char_class(Ch, Class).
Ch = a, Class = ab
; Ch = b, Class = ab
; Class = other,
dif(Ch, a), dif(Ch, b).
Per le cose di scrittura in modo più compatto, un if-then-else è necessaria costrutto. Prolog è un built-in uno:
?- ( ( Ch = a ; Ch = b ) -> Class = ab ; Class = other ).
Ch = a, Class = ab.
Anche se questa risposta è il suono, è incompleta. Proprio la prima risposta da ( Ch = a ; Ch = b )
è dato. Le altre risposte sono tagliate via. Non molto relazionale, anzi.
Un costrutto meglio, spesso chiamato un "taglio soft" (non credo che il nome, un taglio è un taglio è un taglio), cede leggermente migliori risultati (questo è in YAP):
?- ( ( Ch = a ; Ch = b ) *-> Class = ab ; Class = other ).
Ch = a, Class = ab
; Ch = b, Class = ab.
In alternativa, SICStus ha if/3
con semantica molto simili:
?- if( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
Ch = a, Class = ab
; Ch = b, Class = ab.
Quindi l'ultima risposta è ancora soppressa. Ora inserite library(reif)
per SICStus , YAP , e SWI . Installarlo e dire:
?- use_module(library(reif)).
?- if_( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
Ch = a, Class = ab
; Ch = b, Class = ab
; Class = other,
dif(Ch, a), dif(Ch, b).
Si noti che tutte le if_/3
viene compilato via ad un selvaggiamente nidificato if-then-else per
char_class(Ch, Class) :-
if_( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
che si espande in YAP 6.3.4 a:
char_class(A,B) :-
( A\=a
->
( A\=b
->
B=other
;
( A==b
->
B=ab
)
;
A=b,
B=ab
;
dif(A,b),
B=other
)
;
( A==a
->
B=ab
)
;
A=a,
B=ab
;
dif(A,a),
( A\=b
->
B=other
;
( A==b
->
B=ab
)
;
A=b,
B=ab
;
dif(A,b),
B=other
)
).
Programma Prolog in realtà è grande condizione per "se" con "poi" che stampa "è raggiunto Goal" e "altro", che stampa "Nessun sloutions è stato trovato". A, B
means "A è vero e B è vero", la maggior parte dei sistemi di prologo non cercherà di soddisfare "B" se "A" non è raggiungibile (cioè X=3, write('X is 3'),nl
stamperà 'X è 3' quando X = 3, e lo farà nulla se X = 2).
( A == B ->
writeln("ok")
;
writeln("nok")
),
È necessario il resto parte
Si consiglia di leggere Imparare Prolog Now! Capitolo 10.2 Utilizzando Cut . Ciò fornisce un esempio:
max(X,Y,Z) :- X =< Y,!, Y = Z.
Va detto,
Z
è pari a Y
se !
è vero (che sempre è) e è X
<= Y
.