In sostanza si sta scrivendo un programma il controllo per un implicazione globale:
forall N, if N < 10 then N > 5
e volete sapere per quale dominio di N
che contiene.
Ora è riscrivere correttamente che nel prologo come:
\+ (N < 10, \+ (N > 5)).
Ma se si tenta di dare quel query per l'interprete Prolog, il risultato sarà l'errore:
?- \+ (N < 10, \+ (N > 5)).
ERROR: </2: Arguments are not sufficiently instantiated
perché gli argomenti di <
non sono istanziati. Succede la stessa cosa con una semplice query come N < 3
. Naturalmente, se si crea un'istanza prima la query, il problema scompare:
?- N=5, \+ (N < 10, \+ (N > 5)).
false.
(la dichiarazione non vale per N = 5)
?- N=6, \+ (N < 10, \+ (N > 5)).
N = 6.
(ma vale per N = 6) .
Si potrebbe anche mettere un predicato che genera più assegnazioni per N
via backtracking, al posto di quella N=6
:
?- between(1, 12, N), \+ (N < 10, \+ (N > 5)).
N = 6 ;
N = 7 ;
N = 8 ;
N = 9 ;
N = 10 ;
N = 11 ;
N = 12.
ma per un grande dominio, che sta per essere altamente inefficiente (che richiederà backtracking per ogni elemento del dominio).
Se si desidera ragionare su domini finiti (cioè numeri interi), è possibile utilizzare la libreria CLPFD come suggerito da @lurker. Questo approccio è più efficiente, perché ha regole per il ragionamento su intervalli, intersezioni su intervalli e molte altre.
si deve sostituire <
, >
, ,
, \+
con gli operatori CLP #<
, #>
, #/\
, #\
. Proviamo:
?- use_module(library(clpfd)).
?- #\ (N #< 10 #/\ #\ (N #> 5)).
N+1#=_G11193,
N#>=6#<==>_G11205,
10#>=_G11193#<==>_G11217,
_G11217 in 0..1,
_G11217#/\_G11244#<==>0,
_G11244 in 0..1,
#\_G11205#<==>_G11244,
_G11205 in 0..1.
che potrebbe essere un po 'difficile da leggere, ma tra le tante altre cose, che ti sta dicendo la risposta che state cercando, che è il dominio di N: N #>= 6
.
Il '2' and '>/2' operatori richiedono che tutti gli argomenti hanno valori specifici (sono istanziati), al fine di lavorare. Quindi se 'N' non ha un valore (non è * istanziato *) allora' N <10' genererà quell'errore. Se stai cercando di generare valori con determinati vincoli, potresti voler usare la libreria CLPFD, quindi puoi usare 'N # <10', ecc. – lurker
@lurker Ok, capisco. Come cambierei il codice in modo che produca tutti i numeri interi possibili? E non solo controlla se l'argomento soddisfa la condizione? È possibile? – akalikin
ok @lurker, grazie mille – akalikin