Prolog: get all possible values of a variable - prolog

I'm Following Prolog Tutorial 2.1.
Program
adjacent(1, 2).
adjacent(1, 3).
adjacent(1, 4).
main:-
adjacent(1, R),
write(R).
prints 2.
But it supposes to print a list of possible values according to the tutorial:
?- adjacent(1,2).
yes
?- adjacent(1,3).
no
?- adjacent(1,R).
R = 2 ;
R = 3 ;
R = 4 ;
no
I try again in repl only to get the same result:
?- adjacent(1, R).
R = 2 .
How could I get/print a list of possible values of a variable?

In swipl, library(apply) is - by default - autoloaded, so you can write
main:-
forall(adjacent(1, R), (write(R),nl)).
note: Action is a conjuction, just for to illustrate the proper syntax required. For any practical purpose, main :- forall(adjacent(1, R), writeln(R)). could be better.

You need a failure-loop:
adjacent(1, 2).
adjacent(1, 3).
adjacent(1, 4).
main :-
adjacent(1, R),
write(R), nl,
fail.
main.
This is a basic programming technique in Prolog. fail/0 will force backtracking, so next adjacent/2 solution is explored (and so on). Second clause to main/0 prevents the loop itself from failure.

after Prolog prints R = 2;, you can press "r", "n", [TAB] or [SPACE] to show the next results.
I don't know how that works with write(R). but that is not in the code from the tutorial so I think that's supposed to be the trick

Related

Why doesn't prolog stop on cut?

I would like to get this result:
?- numberMatrixLines(1,[[1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1]],X).
X = [machinePenalty(1,[1,1,1,1,1,1,1,1]),
machinePenalty(2 [1,1,1,1,1,1,1,1]),
machinePenalty(3,[1,1,1,1,1,1,1,1])]
I try the following code:
numberMatrixLines(X,[],ResultMatrix):-
writeln('should end here'),
reverse(ResultMatrix,ResultMatrixTemp),
initWith(ResultMatrixTemp,ResultMatrix),
!.
numberMatrixLines(X,[H|T],ResultMatrix):-
append_in_front(machinePenalty(X,H),ResultMatrix,ResultMatrixTemp),
writeln(ResultMatrixTemp),
incr(X,X1),
numberMatrixLines(X1,T,ResultMatrixTemp).
incr(X, X1) :-
X1 is X+1.
append_in_front(X,[],[X]).
append_in_front(X,L1,[X|L1]).
The result is correct when numberMatrixLines(X,[],ResultMatrix) is reached. HOWEVER, the predicate won't stop there and return X , as it's supposed to.
What can be done to make it stop in that line?
A straight-forward solution would be (I moved the input list to the first argument to take advantage of Prolog first-argument indexing to avoid spurious choice-points and the need of cuts):
% number_matrix_lines(+list, +integer, -list)
number_matrix_lines([], _, []).
number_matrix_lines([Line| Lines], I, [machine_penalty(I,Line)| NumberLines]) :-
J is I + 1,
number_matrix_lines(Lines, J, NumberLines).
Sample call:
| ?- number_matrix_lines([[1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1]], 1, NumberLines).
NumberLines = [machine_penalty(1,[1,1,1,1,1,1,1,1]), machine_penalty(2,[1,1,1,1,1,1,1,1]), machine_penalty(3,[1,1,1,1,1,1,1,1])]
yes
P.S. Note that Prolog coding guidelines advise using underscores in predicate names instead of CamelCase.

Prolog - Backtracking through a set of dynamic options

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

Prolog. Difficult beginnings

At the beginning: I am beginner in Prolog but I have to admit, the language is curious because of the fact other paradigm.
find_kth_e(X, [X|_], 1).
find_kth_e(X, [_|T], K) :- K > 1, K1 is K-1, find_kth_e(X, T, K1).
?- find_kth_e(X, [1,2,3,4,5], 3).
X = 3 ;
false.
What is find_kth_e? Function? Relation? ( Yeah, I know that a function is a relation).
The result is 3. And it is ok. But why the second result is false?
Let's consider a modified version:
find_kth_e(X, [X|_], 1).
find_kth_e(X, [_|T], K) :- K > 1, K1 is K-1, find_kth_e(_, T, K1).
?- find_kth_e(X, [1,2,3,4,5], 3).
X = 3 ;
false.
The only difference is in line: find_kth_e(X, [_|T], K) :- K > 1, K1 is K-1, find_kth_e(_, T, K1).. I replaced X with _. And now:
?- find_kth_e(X, [1,2,3,4,5], 3).
true ;
false.
The answer is true and false. Why there is no 3? After all, the result should be returned by first version of function- I mean find_kth_e(X, [X|_], 1). So, the fact that I replaced X with _ should doesn't matter.
Please explain .
As #EugeneSh. says, Prolog has predicates. A predicate may have one or more predicate clauses (yours has two). A predicate defines a relation between its arguments.
?- find_kth_e(X, [1,2,3,4,5], 3).
X = 3 ;
false.
In this example, you queried whether X is the 3rd argument of list [1,2,3,4,5]. Prolog succeeded with X = 3. But there was a choice point in your predicate, meaning Prolog encountered a place in the code before it succeeded where an alternative decision could be explored. When you pressed ;, you told Prolog to explore that alternative (Prolog backtracks). Prolog found there were no more solutions after X = 3, so Prolog says "false".
When you replaced X with _ you indicated that you didn't care what the first argument is:
?- find_kth_e(_, [1,2,3,4,5], 3).
true ;
false.
As in the first query, Prolog succeeded in finding a 3rd element, but you indicated that you didn't care what that element is. So Prolog succeeds and says only "true". And, as before, the choice point is there. Your ; tells Prolog to backtrack to the choice point and it found no more solutions, so ultimately shows "false".
Here's another little test you can do to show success versus failure:
?- find_kth_e(X, [a,b,c,d,e], 3), write('Success!'), nl.
Success!
X = c ;
false.
Since the find_kth_e/3 succeeded, Prolog continued to the write/1 statement which wrote "Success!" and then showed X = c (Prolog shows all the variables that result in success after the entire clause finishes executing).
Here's a failure case:
?- find_kth_e(X, [a,b,c,d,e], 6), write('Success!'), nl.
false.
?-
find_kth_e/3 could not find a 6th element, so it failed. Prolog did not continue and do the write/1 due to the failure of the prior statement, and you can see "Success!" was not displayed.

How to store the first returned value of a function in prolog?

I have a function like this:
myFunction(V1, V2, Result) :-
Result is V1/V1cover + V2/V2cover,
write(Result).
myFunction(0,0,0).
keepValue(V1,V2,V1cover,V2cover) :-
V1cover is V1,
V2cover is V2.
There are other functions that call myFunction many times and get the Result back. However, I would like to get the first Result that myFunction is called first time and keep it to use for calls later(In this case, it is V1cover and V2cover). For example, first time, myFunction(4,4,A) is called. Then it returns A = 2. After that I would like to keep the value of V1cover(4) and V2cover(4) to use for next called times. How I can do that? I tried to apply a cached techonology like and apply it into myFunction:
:- dynamic(cachedGoal_sol/2).
reset :-
retractall(cachedGoal_sol(_, _)).
eq(A, B) :-
subsumes_term(A, B),
subsumes_term(B, A).
cached_call(Goal) :-
\+ (cachedGoal_sol(First,_), eq(First, Goal)),
copy_term(Goal, First),
catch(
( Goal,
assertz(cachedGoal_sol(First, Goal)),
fail
),
Pat,
(reset, throw(Pat))).
cached_call(Goal) :-
cachedGoal_sol(First, Results),
eq(First, Goal),
Results = Goal.
myFunction(V1, V2, Result) :-
**cached_call(keepValue(V1,V2,V1cover,V2cover),**
Result is V1/V1cover + V2/V2cover,
write(Result).
but it doesn't work, when I try to run the second time myFunction(2,3,A) and trace the program, it actually stores solution of the first call but I couldn't get the first values of V1cover, V2cover since eq() in the second cached_call() fails. Is there a way to only get values of V1cover, V2cover without touching to V1,V2 since they are input? Thanks very much for your answer.
Your code has some errors and it's a bit too complicated. I'll try to give you an answer that might be useful to others too.
Let's suppose we need a predicate to store information about the context in which a goal was first satisfied.
I'll use a simple example. Let's say we have a rule to find pairs of numbers between 1 and 4 that add to 6.
sum_to_six(X, Y) :- between(1, 4, X), between(1, 4, Y), X + Y =:= 6.
Trying to find all pairs that satisfy the above rule, one gets the following answer:
?- findall(pair(X,Y), sum_to_six(X, Y), All).
All = [pair(2, 4), pair(3, 3), pair(4, 2)].
Now, let's return to your question. Let's suppose we need the first pair that satisfied the goal. We should modify the rule for predicate sum_to_six/2.
sum_to_six(X, Y):-
between(1, 4, X), between(1, 4, Y), X + Y =:= 6,
store_first(pair(X,Y)).
The subgoal store_first(pair(X,Y)) succeeds every time, but asserts pair(X,Y) just the first time (if there is no other pair(_,_) in the dynamic memory). So, the answer you need might be something similar to this:
store_first(Goal):-
Goal =.. [Name | Args], %% Name is the name of the predicate
length(Args, N), %% N represents its arity
length(NVars, N),
Test =.. [Name | NVars], %% Test is a goal like p(_, _, _, ...)
(
Test, !
;
assertz(Goal)
).
Now, to get the stored information:
?- retractall(pair(_,_)), findall(_, sum_to_six(_,_), _), pair(FirstX, FirstY).
FirstX = 2,
FirstY = 4.
If you want only the first answer, simply write
..., cached_call(once(Goal)), ....
using this definition.

Simple Arithmetic in prolog

I am trying to write a program that gives a list and back a newer list that have even numbers in the first list, as below:
evennom([1,3,2,4,3,2,1,2],out)
out = [2,4,2,2]
My Code is as below:
evennom([],[]).
evennom(H1|T1],[H2|T2):- H2 is H1 mod 2.
You are close - there needs to be something that removes the first element when the mod 2 operation fails. Also, your "copy" rule was not entirely correct.
Try this:
evennom([], []).
evennom([H|T1], [H|T2]) :- H rem 2 =:= 0, !, evennom(T1, T2).
evennom([_|T1], T2) :- evennom(T1, T2).
Prolog does the recursion for you..
evennom(ListIn, ListOut) :-
findall(Even, (nth0(_, ListIn, Even), 0 is (Even mod 2)), ListOut).

Resources