Prolog - no arguments are created

I am trying to understand how Prolog works. I am using SWI-Prolog. Here is some code:

forall(C1,C2) :- \+ (C1, \+ C2). foo(N) :- N < 10. bar(N) :- N > 5. foobar(N) :- forall(foo(N),bar(N)). 

It produces the desired result if I do something like:

 ?- foobar(5). false. 

But when I try to see all the possible values, I get an error message:

 ?- foobar(N). ERROR: </2: Arguments are not sufficiently instantiated 

What's going on here?

+6
source share
2 answers

Basically you write a program to test global implication:

 forall N, if N < 10 then N > 5 

and you want to know for which domain domain N

Now you correctly rewrite this in the prolog as:

 \+ ( N < 10, \+ ( N > 5 ) ). 

But if you try to pass this request to the prolog interpreter, it will throw an error:

 ?- \+ ( N < 10, \+ ( N > 5 ) ). ERROR: </2: Arguments are not sufficiently instantiated 

because the arguments < not created. The same thing happens with a simple query, for example N < 3 . Of course, if you create an instance before the request, the problem goes away:

 ?- N=5, \+ ( N < 10, \+ ( N > 5 ) ). false. 

(statement does not hold for N = 5)

 ?- N=6, \+ ( N < 10, \+ ( N > 5 ) ). N = 6. 

(but this is true for N = 6).

You can also put a predicate that generates multiple assignments for N using backtracking instead of N=6 :

 ?- between(1, 12, N), \+ ( N < 10, \+ ( N > 5 ) ). N = 6 ; N = 7 ; N = 8 ; N = 9 ; N = 10 ; N = 11 ; N = 12. 

but for a large area this will be extremely inefficient (reverse tracking will be required for each domain element).

If you want to talk about destination domains (i.e. integers), you can use the CLPFD library, as @lurker suggested. This approach is more effective because it has rules for reasoning about intervals, intersection at intervals, and many others.

You must replace < , > ,,, \+ the CLP operators #< , #> , #/\ , #\ . Let's try:

 ?- 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. 

which may be a little hard to read, but among many other things, it tells you the answer you are looking for, that is, area N: N #>= 6 .

+3
source

TL DR. A prologue has good algebraic properties if you stick to its logically clean kernel.


For more information, see the following excellent answers to Prolog's StackOverflow questions:

+2
source

Source: https://habr.com/ru/post/983976/


All Articles