I am a novice in prolog programming, i use swi-prolog. Now I'm stucked by some math problems
as we know the predicate :A is 3+3.works well,the answer is A=6.
but if I want to find two digits (A and B) from 0~9 that a+b=6
6 is A+B does't work. so I want to know if there is a easy way to do this? And what if I want to find 3 digits (A,B and C)from 0~9 that A+B+C=13 how to do this ?
the simpler way, working in every Prolog implementation: declare a predicate digit/1 (the notation predicate/N means that predicate has N arguments)
digit(D) :- member(D, [0,1,2,3,4,5,6,7,8,9]).
then you can ask
?- digit(A),digit(B),6 is A+B.
A = 0,
B = 6 ;
A = 1,
B = 5 ;
...
since sum is symmetric, maybe you want to reduce the duplicate solution with
?- digit(A),digit(B),A=<B,6 is A+B.
Using library(clpfd) you can avoid defining your digit/1 predicate, and gain a lot of functionality:
?- [library(clpfd)].
true.
?- [A,B,C] ins 0..9, A+B+C #= 13, label([A,B,C]).
A = 0,
B = 4,
C = 9 ;
A = 0,
B = 5,
C = 8
...
note that now the incognite can stay to the left of the 'assignment'...
My advice to you as a Prolog novice is this:
First things first!
Use clpfd! You can start right now by reading the tag information section on tag clpfd.
Pick up the habit of starting new file with extension .pl with the following line:
:- use_module(library(clpfd)).
Use clpfd everytime you want to express Prolog relations over integers: Every. Single. Time.
Witness that clpfd is already widely available and that it is still gaining ground.
Realize that you will profit the most if you learn clpfd first—not 1970's style (is)/2!
Why? (is)/2 is a low-level feature best used by constraint solver implementors.
Doing math with prolog is interesting.
This looks like an assignment and I would not like to solve it, but I will try to help you find the answer yourself.
Given the restricted range of your problem you could probably define every integer from 0 to 9 by creating a simple prolog programm.
Keep in mind that you can define also functions like:
add3(A, B, C,SUM) :- SUM is A + B + C.
You could try to solve the problem by an Equation Solver.
See this answer:
Equation solver in SWI-Prolog
Or using Constraint Logic Programming.
http://www.swi-prolog.org/man/clpqr.html
Related
Firstly, the clp(fd) documentation mentions:
In modern Prolog systems, arithmetic constraints subsume and supersede low-level predicates over integers. The main advantage of arithmetic constraints is that they are true relations and can be used in all directions. For most programs, arithmetic constraints are the only predicates you will ever need from this library.
Secondly, on a previously asked question, it was mentioned that include/3 is incompatible with clp(fd).
Does that mean that only clp(fd) operators and clp(fd) predicates can be used when writing prolog with the clp(fd) library?
Furthermore, for example, why is include/3 incompatible with clp(fd)? Is it because it does not use clp(fd) operators? To use include/3 in clp(fd) code, would one need to rewrite a version that uses clp(fd) operators and constraints?
why is include/3 incompatible with clp(fd)?
?- X = 1, include(#\=(1),[0,X,2],Xs), X = 1.
X = 1,
Xs = [0,2]. % looks good
?- include(#\=(1),[0,X,2],Xs), X = 1.
false, unexpected.
?- include(#\=(1),[0,X,2],Xs). % generalization
Xs = [0,X,2],
X in inf..0\/2..sup
; unexpected. % missing second answer
So, (#\=)/2 works in this case only if it is sufficiently instantiated. How can you be sure it is? Well, there is no direct safe test. And thus you will get incorrect results in certain cases. As long as these examples fit on a single line, it is rather easy to spot the error. But with a larger program, this is practically impossible. Because of this, constraints and include/3 are incompatible.
A way out would be to produce instantiation errors in cases with insufficient instantiation, but this is pretty hairy in the context of clpfd. Other built-in predicates like (=\=)/2 do this, and are limited in their applicability.
?- X = 1, include(=\=(1),[0,X,2],Xs), X = 1.
X = 1,
Xs = [0,2].
?- include(=\=(1),[0,X,2],Xs), X = 1.
instantiation_error. % much better than an incorrect answer
A safe variant of include/3 is tfilter/3 of library(reif). But before using it, I recommend you read this.
include/3 doesn't have to be incompatible with clpfd (or any other use of attributed variables) - depends on the safe (for the purposes of the program, rather than necessarily "logically pure") usage of the attributed variables. E.g.:
:- use_module(library(clpfd)).
test_include(F) :-
L = [N1, N2, N3, N4],
N1 #< 2,
N2 #> 5,
N3 #< 3,
N4 #> 8,
include(gt_3_fd, L, F).
gt_3_fd(I) :-
I #> 3.
Result in swi-prolog:
?- test_include(F).
F = [_A, _B],
_A in 6..sup,
_B in 9..sup.
The above code is safe, because the variables being used with clpfd are being used consistently with clpfd, and the specified constraints result in reification of gt_3_fd being unnecessary.
Once the variables are nonvar/ground depending on the use-case (clpfd deals with integers, rather than e.g. compound terms, so nonvar is good enough), then the variables can also be used outside of clpfd. Example:
?- I = 5, I > 4, I #> 4, I #> 4.
I = 5.
An operator such as > uses the actual value of the variable, and ignores any attributes which might have been added to the variable by e.g. clpfd.
Logical purity, e.g. adding constraints to the elements in list L after the include/3 rather than before, is a separate issue, and applies to non-attributed variables also.
In summary: A program may be using some integers with clpfd, and some integers outside of clpfd, i.e. a mixture. That is OK, as long as the inside-or-outside distinction is consistently applied, while it is relevant (because e.g. labeling will produce actual values).
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.
Playing with Prolog for the first time and while I thought I knew what it basically is good for, I find it hard to get anything done in it. So, I tried to find the easiest possible task and even fail to accomplish that.
I think it is due to me not knowing how prolog data types (numbers) are supposed to work or they have special syntax.
So, my first attempt to classify even numbers was:
even(0).
even(X) :- even(X-2).
Result: stack overflow for the query: even(2).
So I thought well if this is not it, then maybe it is:
even(0).
even(X+2) :- even(X).
Result of even(2): false.
So my simple question is: How to write such simple things in prolog? Is it all not working because i use numbers?
Why not do it the normal way:
is_even(X) :-
X /\ 0x1 =:= 0.
If you want to enumerate non-negative even numbers upon backtracking when the argument is not bound, this is a different thing altogether. It is probably easy to just say:
even(X) :-
between(0, infinite, X),
is_even(X).
You can use the second definition like this:
?- even(X).
X = 0 ;
X = 2 ;
X = 4 ;
X = 6 . % and so on
There are some differences between is_even/1 and even/1:
is_even/1 will work for any integer, positive or negative
is_even/1 will, surprisingly enough, work for expressions that evaluate to integers, too, for example, X = 3, ..., is_even(X + 1). This is because =:= accepts an arithmetic expression on either side.
even/1 uses between/3, so the domain of X and error conditions are the same as for the third argument of between/3.
As a consequence, even/1 does not work with negative integers or arithmetic expressions.
But wait, there's more!
Apparently, between(0, infinite, X) is not something you can do in almost any Prolog apart from SWI. So, instead, you can use another predicate that will enumerate positive integers (list lengths):
even_f(X) :-
length(_, X),
is_even(X).
(Thank you to #false for this)
Use is/2 to force the arithmetic evaluation. On their own, Prolog terms are just structural symbolic entities, X-2 is a compound term of arity 2, -(X,2):
3 ?- write_canonical( X-2 ).
-(_,2)
true.
But is is for arithmetic expressions:
4 ?- Z is 5-2.
Z = 3.
Your definition should thus be
even(X):- X=:=0 -> true
; X > 0 -> Y is X-2, even(Y).
The drawback of such definition is that it can't be called in a generative fashion, like even(X) to get all the evens generated one after the other.
It is only good for checking a given number. For simplicity, it ignores the negative numbers and always fails for them.
I'm trying to do something very simple while learning Prolog. However I'm confused why this works:
?- length( L, 3 ),
maplist( member, L, [[1,2,3], [1,2,3], [1,2,3]] ),
sort( L, L ).
L = [1, 2, 3] ;
But this seemingly equivalent variation using clpfd doesn't:
?- use_module(library(clpfd)).
?- length( L, 3 ), L ins 1..3, sort( L, L ).
L = [_G5891, _G5894, _G5897],
_G5891 in 1..3,
_G5894 in 1..3,
_G5897 in 1..3.
This works:
?- length( L, 3 ), L ins 1..3, chain( L, #< ).
L = [1, 2, 3].
But this doesn't:
?- length( L, 3 ), L ins 1..3, chain( L, #=< ), all_different( L ).
L = [_G6519, _G6522, _G6525],
_G6519 in 1..3,
all_different([_G6519, _G6522, _G6525]),
_G6522#>=_G6519,
_G6522 in 1..3,
_G6525#>=_G6522,
_G6525 in 1..3.
Can anyone explain why the non-working examples don't give me the outcome I'm expecting?
As a side question, is there a more concise way to rewrite my maplist expression in the first example above?
CLP in Prolog
The system you are using (SWI-Prolog + library(clpfd)) is one example of the embedding of an integer finite-domain constraint solver into a Prolog system (some others are CHIP, ECLiPSe+fd/ic, B-Prolog, SICStus+clpfd). Such an embedding is very natural in the sense that many Prolog concepts map directly to concepts in Constraint Programming, giving us Constraint Logic Programming (CLP).
However, there are number of features of plain Prolog that should be avoided when using it for CLP. Among those are cuts (including the hidden ones in the if-then-else construct and the \+/2 negation), but also meta-logical operations as in your case. For our purposes, meta-logical means any primitive that treats variables as objects (rather than just as placeholders for values). Examples of these are var/1, ==/2, #</2, and indeed also sort/2.
Meta-logical primitives can already cause ugly effects in plain Prolog, e.g.
?- X\==Y, X=3, Y=3, X==Y.
Yes
but Prolog programmers have learned to use them correctly and avoid such problems. With CLP however, it is easier to fall into these traps because the execution control flow is much less obvious.
As to your examples, the first one works because sort/2 sorts lists of integers, no problem there. In the second case, sort/2 sorts a list of domain variables, resulting in a list of domain variables in an arbitrary, system-defined order. Once this is done, sort/2 considers its job done. If you later assign integer values to those ostensibly "sorted" variables, the sortedness of the list will not be checked again, and your program can now return unsorted integer lists as results.
The correct alternative is to use a sortedness check that involves only pure logical Prolog primitives and/or the constraint predicates defined by the CLP solver. You have already done that by using the chain/2 constraint in your third example.
Local Propagation and Search
In your last example you can observe the typical behaviour of a constraint solver based on local propagation: The answer you get is correct, but not very satisfactory. By analyzing the constraints more deeply, it is actually possible to infer that the only correct solution is [1,2,3], but the solver doesn't do that because it could be computationally expensive. But look what happens if you add just a little bit of information:
?- L=[_,Y,_], L ins 1..3, chain(L, #=<), all_different(L), Y=2.
L = [1, 2, 3],
Y = 2
Ass soon as the solver knows that Y is 2, the problem becomes easy enough for the solver to solve completely.
A solution for the general case is to systematically break down the problem into simpler sub-problems, making sure you cover everything. In other words, you add search, and the Prolog way to do search is with a disjunction. In the example, this could be a simple member(Y,[1,2,3]). Typically, you want to do the same for all the domain variables in your problem, just to be on the safe side. A CLP solver will give you a convenient primitive for this, e.g. in the case of clpfd
?- L=[_,_,_], L ins 1..3, chain(L, #=<), all_different(L), label(L).
L = [1, 2, 3] ;
false.
This is a general structure for CLP programs: first constraint setup, then search.
The built-in predicate sort/2 effectively sorts a list based on the term order defined over all terms including variables. For this reason this predicate cannot be considered to implement a concrete relation. Only in special cases like when the first argument is variable free (that is, ground(L) succeeds) and the term is acyclic (acyclic_term(L) succeeds), the built-in corresponds to the obvious relation.
Here is another such strange case sort([X,1],[1,1]) which succeeds, unifying X = 1.
I've got a very large number of equations which I am trying to use PROLOG to solve. However, I've come a minor cropper in that they are not specified in any sort of useful order- that is, some, if not many variables, are used before they are defined. These are all specified within the same predicate. Can PROLOG cope with the predicates being specified in a random order?
Absolutely... ni (in Italian, Yes and Not)
That is, ideally Prolog requires that you specify what must be computed, not how, writing down the equations controlling the solution in a fairly general logical form, Horn clauses.
But this ideal is far from reach, and this is the point where we, as programmers, play a role. You should try to topologically sort formulae, if you want Prolog just apply arithmetic/algorithms.
But at this point, Prolog is not more useful than any other procedural language. It just make easier to do such topological sort, in sense that formulas can be read (this builtin it's a full Prolog parser!), variables identified and quantified easily, terms transformed, evaluated, and the like (metalanguages features, a strong point of Prolog).
Situation changes if you can use CLP(FD). Just an example, a bidirectional factorial (cool, isn't it?), from the documentation of the shining implementation that Markus Triska developed for SWI-Prolog:
You can also use CLP(FD) constraints as a more declarative alternative for ordinary integer arithmetic with is/2, >/2 etc. For example:
:- use_module(library(clpfd)).
n_factorial(0, 1).
n_factorial(N, F) :- N #> 0, N1 #= N - 1, F #= N * F1, n_factorial(N1, F1).
This predicate can be used in all directions. For example:
?- n_factorial(47, F).
F = 258623241511168180642964355153611979969197632389120000000000 ;
false.
?- n_factorial(N, 1).
N = 0 ;
N = 1 ;
false.
?- n_factorial(N, 3).
false.
To make the predicate terminate if any argument is instantiated, add the (implied) constraint F #\= 0 before the recursive call. Otherwise, the query n_factorial(N, 0) is the only non-terminating case of this kind.
Thus if you write your equations in CLP(FD) you get much more chances to have your 'equation system' solved as is. SWI-Prolog has dedicated debugging for the low level details used to solve CLP(FD).
HTH