Prolog - Backtracking through a set of dynamic options - prolog

I'm trying to trigger backtracking on a goal but in a dynamic way, if it's possible. To better exemplify my issue let's say we have the following PROLOG code:
num(1).
num(2).
num(3).
num(4).
num(5).
Then I head to SWI-Prolog and call: num(X). This triggers backtracking looking for all solutions, by typing ; .
What I would like is to remove those facts (num(1),num(2), etc) and replace that code with something thata generates those facts dynamically. Is there any way in which I can achieve this? Someting of the sorts,maybe?
num(X):- for X in 1..5
that yields the same solutions as the code above?
As far as I know, the findall predicate returns a list, which is not what I'm looking for. I would like to backtrack through all answers and look through them using ; in the console.

Yes there is, and you were already very close!
:- use_module(library(clpfd)).
num(X) :-
X in 1..5.
?- num(X).
X in 1..5.
?- num(X), X #>3.
X in 4..5.
?- num(X), labeling([], [X]).
X = 1
; X = 2
; X = 3
; X = 4
; X = 5.

SWI-Prolog has the (non-ISO) predicate between/3 for that:
num(X) :- between(1, 5, X).
You can implement the predicate (for other Prologs and for further tweaking) like this:
between2(A, A, A) :- !. % green cut
between2(A, B, A) :- A < B.
between2(A, B, C) :-
A < B,
A1 is A + 1,
between2(A1, B, C).
The signature for both between/3 and between2/3 is (+From,+To,?X). It means that the From and To must be bound and X can be either bound or not. Also note that From and To must be integers such that From <= To. (Oh, and these integers must be written using Arabic numerals with an optional plus or minus sign before. And using ASCII. Is something non-obvious still missed? And the integers must not be too large or too small, although SWI-Prolog is usually compiled with unbounded integer support, so both between(1, 100000000000000000000000000000000000000000000, X) and between2(1, 100000000000000000000000000000000000000000000, X) usually work.)

Related

Prolog unification broken when argument order is changed

I can’t seem to wrap my head around this. Consider the following dummy predicate:
foo(X, a) :- X < 10.
foo(X, b) :- X > 20.
When consulting:
?- foo(1, a).
true;
false.
I am not sure I completely understand how the choice point is created anyway (Perhaps because the two possible foo predicates are in a kind of or relationship and Prolog just tries to unify with both? Based on this line in the trace: Redo: (24) test:foo(8, a) and the subsequent fail, I suppose this is the case), but what really confuses me is why it works when the argument order is changed:
foo(a, X) :- X < 10.
foo(b, X) :- X > 20.
?- foo(a, 1).
true.
No choice point. What am I missing here?
TL;DR: read the documentation of the Prolog you are using. Pay attention to "clause indexing" or something of the kind.
You are missing that whichever Prolog implementation you are using is just clever enough to do indexing on the first argument in your second example. So when you pose the query ?- foo(a, Something). it never considers the other clause.
But this is really a matter of Prolog implementation, and not a matter of Prolog as a language. Maybe there are Prologs that can also avoid the choice point in the first example. Or maybe it provides a different mechanism to achieve the same. For example SWI-Prolog (among other Prologs) has something called "tabling". With it, you can do it like this:
:- table foo/2.
foo(X, a) :- X < 10.
foo(X, b) :- X > 20.
bar(a, X) :- X < 10.
bar(b, X) :- X > 20.
Now neither foo/2 nor bar/2 has the unexpected choice point:
?- foo(1, a).
true.
?- bar(a, 1).
true.

Prolog addition on wrapped values

I wrote a test program with bindings (facts) between atoms and numbers.
bind(a, 3).
bind(b, 4).
bind(c, 5).
As part of a toy interpreter, I want to be able to perform additions on these atoms using Prolog's native arithmetic operators. For instance, I want to be able to run this query:
% val(X) is the value bound to X
?- X is val(a) + val(b).
X = 7.
However, I'm struggling to find a way to allow this addition. My first approach would have been this one:
% val(X, Y): Y is the value bound to X
val(X, Y) :- bind(X, Y).
% Make val an arithmetic function
:- arithmetic_function(val/1).
However, arithmetic_function/1 is no longer part of Prolog (or at least SWI-Prolog says it's deprecated), so I can't use it. Then I believed the best solution would be to overload the + operator to take this into account:
% val(X, Y): Y is the value bound to X
val(val(X), Y) :- bind(X, Y).
% Overload the + operator
+(val(_X, XVal), val(_Y, YVal)) :- XVal + YVal.
But here I've got my syntax all messed up because I don't really know how to overload a native arithmetic operation. When I type in the sample query from before, SWI-Prolog says ERROR: Arithmetic: ``val(a)' is not a function.
Would you have hints about a possible solution or a better approach or something I missed?
From the docs, I tought you should use function_expansion/3.
But I'm unable to get it to work, instead, goal_expansion could do, but isn't very attractive... for instance, if you save the following definitions in a file bind.pl (just to say)
:- module(bind, [test/0]).
:- dynamic bind/2.
bind(a, 3).
bind(b, 4).
bind(c, 5).
% :- multifile user:goal_expansion/2.
user:goal_expansion(val(X), Y) :- bind(X, Y).
user:goal_expansion(X is Y, X is Z) :- expand_goal(Y, Z).
user:goal_expansion(X + Y, U + V) :- expand_goal(X, U), expand_goal(Y, V).
test :-
X is val(a) + val(b), writeln(X).
and consult it, you can run your test:
?- test.
7
edit
after Paulo suggestion, here is an enhanced solution, that should work for every binary expression.
user:goal_expansion(X is Y, X is Z) :- expr_bind(Y, Z).
expr_bind(val(A), V) :- !, bind(A, V).
expr_bind(X, Y) :-
X =.. [F, L, R], % get operator F and Left,Right expressions
expr_bind(L, S), % bind Left expression
expr_bind(R, T), % bind Right expression
Y =.. [F, S, T]. % pack bound expressions back with same operator
expr_bind(X, X). % oops, I forgot... this clause allows numbers and variables
having defined user as target module for goal_expansion, it works on the CLI:
?- R is val(a)*val(b)-val(c).
R = 7.
edit
now, let's generalize to some other arithmetic operators, using the same skeleton expr_bind uses for binary expressions:
user:goal_expansion(X, Y) :-
X =.. [F,L,R], memberchk(F, [is, =<, <, =:=, >, >=]),
expr_bind(L, S),
expr_bind(R, T),
Y =.. [F, S, T].
and unary operators (I cannot recall no one apart minus, so I show a simpler way than (=..)/2):
...
expr_bind(-X, -Y) :- expr_bind(X, Y).
expr_bind(X, X).
Now we get
?- -val(a)*2 < val(b)-val(c).
true.
One way to do it is using Logtalk parametric objects (Logtalk runs on SWI-Prolog and 11 other Prolog systems; this makes this solution highly portable). The idea is to define each arithmetic operation as a parametric object that understands an eval/1 message. First we define a protocol that will be implemented by the objects representing the arithmetic operations:
:- protocol(eval).
:- public(eval/1).
:- end_protocol.
The basic parametric object understands val/1 and contains the bind/2 table:
:- object(val(_X_), implements(eval)).
eval(X) :-
bind(_X_, X).
bind(a, 3).
bind(b, 4).
bind(c, 5).
:- end_object.
I exemplify here only the implementation for arithmetic addition:
:- object(_X_ + _Y_, implements(eval)).
eval(Result) :-
_X_::eval(X), _Y_::eval(Y),
Result is X + Y.
:- end_object.
Sample call (assuming the entities above are saved in an eval.lgt file):
% swilgt
...
?- {eval}.
% [ /Users/pmoura/Desktop/eval.lgt loaded ]
% (0 warnings)
true.
?- (val(a) + val(b))::eval(R).
R = 7.
This can be an interesting solution if you plan to implement more functionality other than expression evaluation. E.g. a similar solution but for symbolic differentiation of arithmetic expressions can be found at:
https://github.com/LogtalkDotOrg/logtalk3/tree/master/examples/symdiff
This solution will also work in the case of runtime generated expressions (term-expansion based solutions usually only work at source file compile time and at the top-level).
If you're only interested in expression evaluation, Capelli's solution is more compact and retains is/2 for evaluation. It can also be made more portable if necessary using Logtalk's portable term-expansion mechanism (but note the caveat in the previous paragraph).
This is perhaps not exactly what I was looking for, but I had an idea:
compute(val(X) + val(Y), Out) :-
bind(X, XVal),
bind(Y, YVal),
Out is XVal + YVal.
Now I can run the following query:
?- compute(val(a) + val(c), Out).
Out = 8.
Now I need to define compute for every arithmetic operation I'm interested in, then get my interpreter to run expressions through it.

A Prolog programme getting ERROR: >/2: Arguments are not sufficiently instantiated

I have created a program, list(X,Y) to check whether all the elements in list Y are smaller than X.
The codes are as follows.
list(X,[]).
list(X,[Y|Z]):-X>Y,list(X,Z).
It works fine when I type list(3,[1,2]). However, if I type list(3,Y) in order to find lists which only contain elements smaller than 3, there is an error.
?- list(3,[1,2]).
true .
?- list(3,Y).
Y = [] ;
ERROR: >/2: Arguments are not sufficiently instantiated
I have read some posts which got the same error, but I still don't understand which part of my codes goes wrong.
Here comes a similar example found from internet.
greater(X,Y,Z) returns the part Z of Y that is greater than X.
greater(X,[],[]).
greater(X,[H|Y],[H|Z]) :- H>X, greater(X,Y,Z).
greater(X,[H|Y],Z) :- H=<X, greater(X,Y,Z).
?- greater(2,[1,2,3], Y).
Y = [3].
The question is, what is the difference between the codes of greater(X,Y,Z) and list(X,Y) so that there is no error when calling greater(2,[1,2,3], Y)..
Thanks for any help provided.
Since - judging from your comment - you seem to be reasoning over integers: That's a textbook example for using finite domain constraints, which are available in almost all modern Prolog implementations and generalize integer arithmetic so that you can use it in all directions.
Your code works exactly as expected with, among others, B-Prolog, GNU Prolog, SICStus, SWI and YAP if you just use the finite domain constraint (#>)/2 instead of the lower-level arithmetic primitive (>)/2:
:- use_module(library(clpfd)).
list(X, []).
list(X, [Y|Z]):- X#>Y, list(X,Z).
Constraints allow you to use this predicate, which you can also express with maplist/2 as in the queries below, in all directions:
?- maplist(#>(3), [1,2]).
true.
?- maplist(#>(X), [1,2]).
X in 3..sup.
?- maplist(#>(3), [A,B]).
A in inf..2,
B in inf..2.
?- maplist(#>(X), [Y,Z]).
Z#=<X+ -1,
Y#=<X+ -1.
Even the most general query, where none of the arguments is instantiated, gives useful answers:
?- maplist(#>(X), Ls).
Ls = [] ;
Ls = [_G1022],
_G1022#=<X+ -1 ;
Ls = [_G1187, _G1190],
_G1190#=<X+ -1,
_G1187#=<X+ -1 ;
etc.
EDIT: Also the example you now added can be made much more general with finite domain constraints:
:- use_module(library(clpfd)).
greater(_, [], []).
greater(X, [H|Y], [H|Z]) :- H #> X, greater(X, Y, Z).
greater(X, [H|Y], Z) :- H #=< X, greater(X, Y, Z).
You can now use it in all directions, for example:
?- greater(X, [E], Ls).
Ls = [E],
X#=<E+ -1 ;
Ls = [],
X#>=E.
This is not possible with the original version, whose author may not have been aware of constraints.

How do return both a variable result and a true/false in Prolog?

It sounds silly, but lets say my predicate largest/2 returns the largest element in a list...the output should look like this:
?- largest([1,2,3,4,5], X).
X = 5.
false.
I implemented largest, and it works like above except it doesn't output "false". How do I make it so it also outputs this "false." value? This is for an annoying assignment I have to finish. :(
That extra false. or No just means that the person running the program asked to get all possible solutions for X, not just the first possible solution.
On most interactive Prolog interpreters, you check to see if there is another solution by pressing the semicolon (;) key.
sounds like impossible, as if predicate fails, no binding of free variables happens, see
?- A=5.
A = 5.
?- A=5,false.
false.
however
?- A=5;false.
A = 5 ;
false.
To achieve this you should make your predicate "largest" non-deterministic. But to me this seems pretty silly.
If this was part of an assignment, it probably means that your predicate should not yield a second (possibly different) result after backtracking. Backtracking occurs if the user wants the next solution, often by pressing ;. The interpreter often indicates that another solution is possible when it knows there are still paths not fully evaluated.
Suppose you had a predicate foo/1 as follows:
foo(1).
foo(Bar) :-
foo(Baz),
Bar is Baz + 1.
If you ask foo(Bar), the interpreter will respond with Bar = 1. After repeatedly pressing ;, the interpreter will come back with Bar = 2, Bar = 3 and so on.
In your example, finding the largest of a list, should be deterministic. Backtracking should not yield a different answer.
It's up to you to interpret the assignment to mean that you have to allow backtracking but have it fail, or that it would be all right to not even have it backtrack at all.
There is something to the previous answers by #aschepler, #Xonix, and #SQB.
In this answer, we use clpfd for expressing declarative integer arithmetics.
:- use_module(library(clpfd)).
We define largest/2 using the built-in predicate member/2, library meta-predicate maplist/2, and the finite-domain constraint (#>=)/2:
largest(Zs, X) :-
member(X, Zs), % X is a member of the list Zs
maplist(#>=(X), Zs). % all Z in Zs fulfill X #>= Z
Sample queries:
?- largest([1,2,3,4,5], X).
X = 5.
?- largest([1,2,3,4,5,4], X).
X = 5 ;
false.
?- largest([1,2,3,4,5,5], X).
X = 5 ;
X = 5.
?- largest([1,2,3,4,5,5,4], X).
X = 5 ;
X = 5 ;
false.
?- largest([A,B,C,D], X).
A = X, X#>=D, X#>=C, X#>=B ;
B = X, X#>=A, X#>=D, X#>=C ;
C = X, X#>=A, X#>=D, X#>=B ;
D = X, X#>=A, X#>=C, X#>=B.

Prolog Beginner: How to unify with arithmetic comparison operators or how to get a set var to range of values

I am new to Prolog. I need to write an integer adder that will add numbers between 0-9 to other numbers 0-9 and produce a solution 0-18. This is what I want to do:
% pseudo code
add(in1, in2, out) :-
in1 < 10,
in2 < 10,
out < 18.
I would like to be able to call it like this:
To check if it is a valid addition:
?- add(1,2,3).
true.
?- add(1,2,4).
false.
With one missing variable:
?- add(X,2,3).
X = 1.
?- add(1,4,X).
X = 5.
With multiple missing variables:
?- add(X,Y,Z).
% Some output that would make sense. Some examples could be:
X=1, Y=1, Z=2 ;
X=2, Y=1, Z=3 ......
I realize that this is probably a pretty simplistic question and it is probably very straightforward. However, according to the Prolog tutorial I am using:
"Unlike unification Arithmetic Comparison Operators operators cannot be used to give values to a variable. The can only be evaluated when every term on each side have been instantiated."
All modern Prolog systems provide finite domain constraints, which are true relations that can (in contrast to more low-level arithmetic predicates like is/2 and >/2) be used in all directions. In SWI-Prolog:
:- use_module(library(clpfd)).
plus(X, Y, Z) :-
[X,Y] ins 0..9,
X + Y #= Z.
Results for your examples:
?- plus(1,2,3).
true.
?- plus(1,2,4).
false.
?- plus(X,2,3).
X = 1.
?- plus(1,4,X).
X = 5.
?- plus(X,Y,Z).
X in 0..9,
X+Y#=Z,
Y in 0..9,
Z in 0..18.
Since the predicate can be used in all directions, it does no longer make sense to call it "add/3", as that would imply a direction, but the predicate truly describes when the relation holds and is thus more general.
What about this?:
add(X,Y,Z) :-
Z is X + Y,
X < 10,
Y < 10,
Z < 19.
Problem: this works nicely for queries of the form add(1,1,X) because Z's instantiated before the < calls, but fails when you ask add(X,1,2). You could use var/1 to distinguish the kind of query (var/1 tells you whether a variable's uninstantiated or not), but that sounds like a lot of pain.
Solution:
lessThanTen(9).
lessThanTen(8).
lessThanTen(7).
lessThanTen(6).
lessThanTen(5).
lessThanTen(4).
lessThanTen(3).
lessThanTen(2).
lessThanTen(1).
lessThanTen(0).
addSimple(Add1,Add2,Sol) :-
lessThanTen(Add1),
lessThanTen(Add2),
Sol is Add1+Add2.

Resources