"Obvious" is not a word lightly bandied about, but why does SWI-Prolog's CLPFD correctly solve this:
?- A+1 #= A*2.
A = 1.
but not this:
?- B #= A + 1, B #= A * 2.
A+1#=B,
A*2#=B.
(label and indomain yield Arguments are not sufficiently instantiated.)
Is it just...the solver doesn't catch that case? (I'd sure have expected it to apply transitivity.) Or is it a symptom of some deeper syntactic conundrum, or something?
It tries to solve the constraint from the values in the domain of each variable! As the domain of B and A is infinite and not bound, backtracking over a constraint satisfaction will be delayed and the program is stopped.
It means it tries to find some solution for the constraint B #= A + 1, but it finds many (infinite values for A and B) and also the same for the second constraint. Hence it will be stopped here as the possible values of A and B are infinite. However, the result is not No. It is Yes with 2 delayed goals.
B = B{-1.0Inf .. 1.0Inf}
A = A{-1.0Inf .. 1.0Inf}
There are 2 delayed goals.
To solve this, you need to bound at least one of the A or B. For example, if you run this query A::1..1000, B#=A+1, B #= A*2., you will get the same result as for the first query in your examples. And also, there is not any deduction in clpfd to resolve the transitivity as it uses from the backtracking method.
In sum, it is one of the shortcomings of the library that you are using, as it will be stopped when the domain of a constraint with more than one variable has an infinite domain and you can solve it by setting a bounded domain for at least one of the variables.
Related
I have this basic code.
list_length([], 0).
list_length([_|Tail], L) :-
L #= L0+1,
L #> 0,
list_length(Tail,L0).
I cannot figure out where L0 comes from. How could we ever deduce what L equals? In order to know what L equals we must know the value of L0. Is this because we are reasoning inductively instead of deductively?
I feel like once I understand this code I will begin to understand Prolog as a whole much better.
How could we could ever deduce what L equals? In order to know what L equals we must know the value of L0.
The #=/2 predicate [swi-doc] comes from the clpfd library [swi-doc]. This is a constraint logic programming library. It offers a set of constraints. These constraints are not just aliasses for is/2 or =:=/2, but work often in both directions, and furthermore also allows to enforce the constraints when the variables are grounded. It thus can postpone evaluation.
In this specific case it thus means that if L0 takes a value, L will take the value L0+1. If L has a value, for example because you made a query length([1,4,2,5], 5). It will also check the constraint and thus fail if 5 #= 3+1 is evaluated.
I'm an absolute beginner to prolog. I've just read a basic tutorial and tried to solve a quick problem on my own. The problem is this, find possible number combinations that lead to a sum. I'm expecting something like this:
sum(A,B,11).
This should result in values for A and B that would sum them upto 10.
My initial code was this:
sum(A,B,C):-
C is A + B.
But I do not get any results with this. I get the following.
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [9] 11 is _3302+_3304
ERROR: [7] <user>
ERROR:
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.
What am I missing in my understanding of Prolog?
The standard is/2 predicate requires an evaluable arithmetic expression for second argument. Thus, in your case, you will need to generate possible values for A and B so that A + B can be computed. To make it practical, you will need to restrict the range of possible values. For example:
?- between(1,7,A), between(1,7,B), sum(A,B,11).
A = 4,
B = 7 ;
A = 5,
B = 6 ;
A = 6,
B = 5 ;
A = 7,
B = 4 ;
false.
As you progress on your learning of Prolog, you may eventually be interested in learning about constraint solvers.
This should result in values for A and B that would sum them upto 10.
If you consider negative numbers as well, there are infinite possible results: .. -100+111, -2+13, -1+12, 0+11, 1+10, 2+9, 150+-139 ...
Your program will confirm the sum, and perform the calculation given the inputs for A and B:
?- sum(2,9,11).
true
?- sum(2,9,C).
C = 11
but even if you leave out one of them, it can't solve it.
?- sum(A,9,11).
is/2: Arguments are not sufficiently instantiated
You are hoping Prolog will intuit that you mean "numbers between 0 and 11 which sum to 11" but Prolog sees a potentially infinite search space, and nowhere to start searching, and no way to narrow it down.
Paulo Moura's answer will generate the numbers in the range, and test them all, and show which pairs satisfy A + B = C. He mentions constraint solvers, which are libraries available for popular Prolog implementations and they have a more general way of solving problems like this. Constrain the solution space in some way ("A and B are positive integers"), as many constraints as you know, and then they apply those rules to reason about numbers, apply more techniques to find the answers without searching every imaginable number:
% load the 'clpfd' code
:- use_module(library(clpfd)).
% define a sum using the imported #= instead of "is"
mysum(A, B, C) :-
C #= A + B.
% declare that A and B are positive,
% and solve for A and B values.
?- mysum(A, B, 11), A in 0..sup, B in 0..sup, label([A,B]).
In this case it ends up being more code, but if you're generally hoping for Prolog to solve numeric calculations for you, you will likely have to go in this direction rather than using between() and making all the number lists yourself.
In SWI-Prolog, the following query gives this result:
?- X mod 2 #= 0, X mod 2 #= 0.
X mod 2#=0,
X mod 2#=0.
While correct, there is obviously no need for the second constraint
Similarly:
?- dif(X,0), dif(X,0).
dif(X, 0),
dif(X, 0).
Is there no way to avoid such duplicate constraints? (Obviously the most correct way would be to not write code that leads to that situation, but it is not always that easy).
You can either avoid posting redundant constraints, or remove them with a setof/3-like construct. Both are very implementation specific. The best interface for such purpose is offered by SICStus. Other implementations like YAP or SWI more or less copied that interface, by leaving out some essential parts. A recent attempt to overcome SWI's deficiencies was rejected.
Avoid posting constraints
In SICStus, you can use frozen/2 for this purpose:
| ?- dif(X,0), frozen(X,Goal).
Goal = prolog:dif(X,0),
prolog:dif(X,0) ? ;
no
| ?- X mod 2#=0, frozen(X, Goal).
Goal = clpfd:(X in inf..sup,X mod 2#=0),
X mod 2#=0,
X in inf..sup ? ;
no
Otherwise, copy_term/3 might be good enough, provided the constraints are not too much interconnected with each other.
Eliminate redundant constraints
Here, a setof-like construct together with call_residue_vars/1 and copy_term/3 is probably the best approach. Again, the original implementation is in SICStus....
For dif/2 alone, entailment can be tested without resorting to any internals:
difp(X,Y) :-
( X \= Y -> true
; dif(X, Y)
).
Few constraint programming systems implement contraction also related to factoring in resolution theorem proving, since CLP labeling is not SMT. Contraction is a structural rule, and it reads as follows, assuming constraints are stored before the (|-)/2 in negated form.
G, A, A |- B
------------ (Left-Contraction)
G, A |- B
We might also extend it to the case where the two A's are derivably equivalent. Mostlikely this is not implemented, since it is costly. For example Jekejeke Minlog already implements contraction for CLP(FD), i.e. finite domains. We find for queries similar to the first query from the OP:
?- use_module(library(finite/clpfd)).
% 19 consults and 0 unloads in 829 ms.
Yes
?- Y+X*3 #= 2, 2-Y #= 3*X.
3*X #= -Y+2
?- X #< Y, Y-X #> 0.
X #=< Y-1
Basically we normalize to A1*X1+..+An*Xn #= B respectively A1*X1+..+An*Xn #=< B where gcd(A1,..,An)=1 and X1,..,Xn are lexically ordered, and then we check whether there is already the same constraint in the constraint store. But for CLP(H), i.e. Herbrand domain terms, we have not yet implemented contraction. We are still deliberating an efficient algorithm:
?- use_module(library(term/herbrand)).
% 2 consults and 0 unloads in 35 ms.
Yes
?- neq(X,0), neq(X,0).
neq(X, 0),
neq(X, 0)
Contraction for dif/2 would mean to implement a kind of (==)/2 via the instantiation defined in the dif/2 constraint. i.e. we would need to apply a recursive test following the pairing of variables and terms defined in the dif/2 constraint against all other dif/2 constraints already in the constraint store. Testing subsumption instead of contraction would also make more sense.
It probably is only feasible to implement contraction or subsumption for dif/2 with the help of some appropriate indexing technique. In Jekejeke Minlog for example for CLP(FD) we index on X1, but we did not yet realize some indexing for CLP(H). What we first might need to figure out is a normal form for the dif/2 constraints, see also this problem here.
This is probably the most trivial implementation of a function that returns the length of a list in Prolog
count([], 0).
count([_|B], T) :- count(B, U), T is U + 1.
one thing about Prolog that I still cannot wrap my head around is the flexibility of using variables as parameters.
So for example I can run count([a, b, c], 3). and get true. I can also run count([a, b], X). and get an answer X = 2.. Oddly (at least for me) is that I can also run count(X, 3). and get at least one result, which looks something like X = [_G4337877, _G4337880, _G4337883] ; before the interpreter disappears into an infinite loop. I can even run something truly "flexible" like count(X, A). and get X = [], A = 0 ; X = [_G4369400], A = 1., which is obviously incomplete but somehow really nice.
Therefore my multifaceted question. Can I somehow explain to Prolog not to look beyond first result when executing count(X, 3).? Can I somehow make Prolog generate any number of solutions for count(X, A).? Is there a limitation of what kind of solutions I can generate? What is it about this specific predicate, that prevents me from generating all solutions for all possible kinds of queries?
This is probably the most trivial implementation
Depends from viewpoint: consider
count(L,C) :- length(L,C).
Shorter and functional. And this one also works for your use case.
edit
library CLP(FD) allows for
:- use_module(library(clpfd)).
count([], 0).
count([_|B], T) :- U #>= 0, T #= U + 1, count(B, U).
?- count(X,3).
X = [_G2327, _G2498, _G2669] ;
false.
(further) answering to comments
It was clearly sarcasm
No, sorry for giving this impression. It was an attempt to give you a synthetic answer to your question. Every details of the implementation of length/2 - indeed much longer than your code - have been carefully weighted to give us a general and efficient building block.
There must be some general concept
I would call (full) Prolog such general concept. From the very start, Prolog requires us to solve computational tasks describing relations among predicate arguments. Once we have described our relations, we can query our 'knowledge database', and Prolog attempts to enumerate all answers, in a specific order.
High level concepts like unification and depth first search (backtracking) are keys in this model.
Now, I think you're looking for second order constructs like var/1, that allow us to reason about our predicates. Such constructs cannot be written in (pure) Prolog, and a growing school of thinking requires to avoid them, because are rather difficult to use. So I posted an alternative using CLP(FD), that effectively shields us in some situation. In this question specific context, it actually give us a simple and elegant solution.
I am not trying to re-implement length
Well, I'm aware of this, but since count/2 aliases length/2, why not study the reference model ? ( see source on SWI-Prolog site )
The answer you get for the query count(X,3) is actually not odd at all. You are asking which lists have a length of 3. And you get a list with 3 elements. The infinite loop appears because the variables B and U in the first goal of your recursive rule are unbound. You don't have anything before that goal that could fail. So it is always possible to follow the recursion. In the version of CapelliC you have 2 goals in the second rule before the recursion that fail if the second argument is smaller than 1. Maybe it becomes clearer if you consider this slightly altered version:
:- use_module(library(clpfd)).
count([], 0).
count([_|B], T) :-
T #> 0,
U #= T - 1,
count(B, U).
Your query
?- count(X,3).
will not match the first rule but the second one and continue recursively until the second argument is 0. At that point the first rule will match and yield the result:
X = [_A,_B,_C] ?
The head of the second rule will also match but its first goal will fail because T=0:
X = [_A,_B,_C] ? ;
no
In your above version however Prolog will try the recursive goal of the second rule because of the unbound variables B and U and hence loop infinitely.
I need to know if variable is instantiated in a given rule, yet I'm not allowed to use var(X), and have no clue on how to do so.
To be specific, my rule gets 4 parameter (P, A, B, C).
If P, A, B, C are instantiated then my rule should "return" true iff (A+B)mod(P)=C(mod(P)).
If one of A B and C isn't isntantiated I should return what value of it will guarantee that (A+B)mod(P)=C(mod(P)). so for example if C isn't instantiated the rule should "return" (A+B)mod(P) as C, and similar behavoir if A or B are not instantiated. Writing each rule is easy, but how can I know which of the cases I'm at if I don't know whther a variable is instantiated or not? as mentioned before, I can't use var(X) or number(X) and so on, I can only assume that P is always instantiated.
Thanks in advance!
I think #mat answer is definitely the way to go to solve your problem.
However, if you want to check whether a variable is not instantiated without using builtin predicate var/1 which does exactly that (due to some restriction, e.g. your teacher explicitly prohibited it) you may use double negation twice to test for the ability to bound a variable without really instantiating it if it is not bound:
not_inst(Var):-
\+(\+(Var=0)),
\+(\+(Var=1)).
Test cases:
?- not_inst(X).
true.
?- not_inst(a).
false.
Testing manually whether or not something is instantiated makes it very hard to correctly handle all cases that can arise in practice. Almost invariably, your resulting code will behave incorrectly for certain instantiation patterns you have not thought about.
Luckily, there is a declarative solution for such problems: Constraints work correctly in all cases, no matter what is instantiated and what is not.
For example, use your Prolog system's CLP(FD) constraints to solve your task:
:- use_module(library(clpfd)).
same_sum_mod(A, B, C, P) :-
(A+B) mod P #= C mod P.
It works correctly in all directions, for example:
?- same_sum_mod(1, 2, 3, 3).
true.
?- same_sum_mod(1, B, 3, 2).
1+B#=_G823,
_G823 mod 2#=1.
?- same_sum_mod(1, 2, 3, P).
P in inf..-1\/1..sup,
3 mod P#=_G855,
3 mod P#=_G855.
And also check out the following case, where B is initially not instantiated, but its domain is known, and the constraint solver can deduce the single admissible solution:
?- B in 0..1, same_sum_mod(1, B, 3, 2).
B = 0.
Such cases cannot be handled by simple instantiation checks, but require reasoning about constraints.
See clpfd for more information about CLP(FD) constraints.