Why doesn't prolog stop on cut? - prolog

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.

Related

Prolog - How to separate atoms from expression involving predicates?

If I’ve an expression:
x + y * (-z)
How to I separate them to form a list of [x,y,z]?
My idea:
split2(X, [X]) :-
X \= +(_,_),
*(_,_),
-(_).
split2(X + Y, [H|T]) :-
split2(X,[H]),
split2(Y, T).
(Repeat for * and -).
Somehow it only works for simple case(involving 2 terms or only one predicate), but not complicated one.
Can someone tells me what’s wrong with my idea?
Follows a solution using DCGs that doesn't require a grammar rule per arithmetic operator and that takes full advantage of first-argument indexing (thus avoiding spurious choice-points or ugly cuts in the grammar rules):
split(Expression, Atomics) :-
Expression =.. [Functor| Args],
phrase(split_atomics(Args, Functor), Atomics).
split_atomics([], Atomic) -->
[Atomic].
split_atomics([Head| Tail], _) -->
split_list([Head| Tail]).
split_list([]) -->
[].
split_list([Head| Tail]) -->
{Head =.. [Functor| Args]},
split_atomics(Args, Functor),
split_list(Tail).
Sample calls:
| ?- split((x + y * (-z)), Atomics).
Atomics = [x, y, z]
yes
| ?- split((x + 3 * (-2)), Atomics).
Atomics = [x, 3, -2]
yes
Your predicates are pretty mixed up. For starters, you're using X \= _+_ to prevent the other rule from matching; instead you should use atomic(X). You're then saying _*_, -_ which is not clearly saying anything in particular except that certain anonymous variables... exist? Anyway, the rest of the first clause is erroneous for one reason or another.
Your second clause is off to a decent start, but I think you are avoiding a use of append/3 here for no particular reason. In the head, you are expecting H to be an atom, but then with the first term in the body you're forcing H to be a singleton list. What if X = a*b? You'd expect split2(a*b,[a,b]) to unify.
You're not far from where you need to be though. This is probably your general pattern:
split2(X, [X]) :- atomic(X).
split2(-X, Result) :- split2(X, Result).
split2(X+Y, Result) :-
split2(X, XVars),
split2(Y, YVars),
append(XVars, YVars, Result).
Continue the pattern for your other operators.
Can someone tells me what's wrong with my idea?
What you are doing is too complicated, that's what's wrong. If you really have as input a valid compound term, and what you need to get out of it is a list of the atomic sub-terms, then, here is what you might want to try:
expression_atoms(E) -->
{ compound(E),
E =.. [_Name|Args]
},
!,
expression_list_atoms(Args).
expression_atoms(E) -->
{ atomic(E)
},
!,
[E].
expression_list_atoms([E|Es]) -->
expression_atoms(E),
expression_list_atoms(Es).
expression_list_atoms([]) --> [].
(Ninja edit: see the solution by Paulo Moura for a cleaner implementation of the same idea.)
The only reason why this is a DCG and not a normal predicate is that I am too lazy to figure out how to do the appends properly.
Here is a small test:
?- X = x + y * (-z).
X = x+y* -z.
?- X = x + y * (-z), write_canonical(X).
+(x,*(y,-(z)))
X = x+y* -z.
?- X = x + y * (-z), write_canonical(X), phrase(expression_atoms(X), Atoms).
+(x,*(y,-(z)))
X = x+y* -z,
Atoms = [x, y, z].
In the last query, you can see the atoms extracted from the expression.
As you see, this solution doesn't care about the names of the compound terms. This happens in line 3 of the listing:
E =.. [_Name|Args]
So you can throw anything at it and it will still "work":
?- phrase(expression_atoms(
the(naked, truth(about(our(waitresses))), is(that(they(only(flirt, with, you))), to(get(a(better(tip('!')))))))),
Atoms).
Atoms = [naked, waitresses, flirt, with, you, !].
If you want this to fail for anything else but a predefined list of operators with a given arity, then you'd have to put a bit more code in there.

How to parsing list in prolog until not fail

I am trying to parse a list, for example:
[1,3,3,2,2,7,2,9]
Let's say I have the following code, where isTwo will print No and fail if it is anything other than two. I WANT it to fail if it is anything other than two. If it is a two, it will print Yes and succeed.
isTwo(2) :-
write('Yes'), !.
isTwo(_) :-
write('No'), fail.
My issue is that I have something along the lines of an iterator defined, and I want to parse an entire list to find the first success.
iter([]).
iter([Head|Tail]) :-
isTwo(Head),
iter(Tail).
This works fine but will stop parsing the rest of the list as soon as failure is found. If we go back to the original list, [1,3,3,2,2,7,2,9], we get false as our output.
My question here is: how can I continue to parse in prolog while still ensuring that isTwo(_) (where it is not equal to two) will still fail, so that I can get an output of something such as NoNoNoYesYesNoYesNo in this case. Preferably without using an if-then-else clause.
This may help:
expected output: NoNoNoYesYesNoYesNo
observed output: No
Well an easy solution would be to use a second variable in iter that will help you understand if an number different than 2 is found:
isTwo(2, X, X) :-
write('Yes').
isTwo(_, _, 0) :-
write('No').
iter([], 0):- fail,!.
iter([], 1).
iter([Head|Tail], X) :-
isTwo(Head, X, Y),
iter(Tail, Y).
iter(L) :- iter(L, 1).
If you want a more concise solution, using maplist/2 you can do something like:
isTwo(2) :- write('Yes'), !.
isTwo(_):- write('No').
test(L):-
maplist(isTwo,L).
?- test([1,3,3,2,2,7,2,9]).
NoNoNoYesYesNoYesNo
true
test/1 is not mandatory, i've added it only for sake of clarity...
The other answers are both fine but the haphazard mixing in of side effects makes me a bit nervous. Also, you have a problem if the list you are "parsing" has a free variable (it will become 2 silently).
Why not like this:
is_two(X) :- X == 2, !, format("Yes").
is_two(X) :- X \== 2, !, format("No").
and then:
?- forall(member(X, [1,3,3,2,2,7,2,9]), is_two(X)).
NoNoNoYesYesNoYesNo
true.
?- forall(member(X, [Y, 2, Z]), is_two(X)).
NoYesNo
true.
Use == and \== to compare without unifying. Use forall and member to make it clear that you are doing it for the side effect. Traversing a list (or using maplist) is a bit deceiving.
forall is just a clearer way to do a failure-driven loop using negation instead of cuts and fails. The query above is identical to:
?- \+ ( member(X, [1,3,3,2,2,7,2,9]), \+ is_two(X) ).

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 - count occurrence of number

I want to write predicate which can count all encountered number:
count(1, [1,0,0,1,0], X).
X = 2.
I tried to write it like:
count(_, [], 0).
count(Num, [H|T], X) :- count(Num, T, X1), Num = H, X is X1 + 1.
Why doesn't work it?
Why doesn't work it?
Prolog is a programming language that often can answer such question directly. Look how I tried out your definition starting with your failing query:
?- count(1, [1,0,0,1,0], X).
false.
?- count(1, Xs, X).
Xs = [], X = 0
; Xs = [1], X = 1
; Xs = [1,1], X = 2
; Xs = [1,1,1], X = 3
; ... .
?- Xs = [_,_,_], count(1, Xs, X).
Xs = [1,1,1], X = 3.
So first I realized that the query does not work at all, then I generalized the query. I replaced the big list by a variable Xs and said: Prolog, fill in the blanks for me! And Prolog did this and reveals us precisely the cases when it will succeed.
In fact, it only succeeds with lists of 1s only. That is odd. Your definition is too restricted - it correctly counts the 1s in lists where there are only ones, but all other lists are rejected. #coder showed you how to extend your definition.
Here is another one using library(reif) for
SICStus|SWI. Alternatively, see tfilter/3.
count(X, Xs, N) :-
tfilter(=(X), Xs, Ys),
length(Ys, N).
A definition more in the style of the other definitions:
count(_, [], 0).
count(E, [X|Xs], N0) :-
if_(E = X, C = 1, C = 0),
count(E, Xs, N1),
N0 is N1+C.
And now for some more general uses:
How does a four element list look like that has 3 times a 1 in it?
?- length(L, 4), count(1, L, 3).
L = [1,1,1,_A], dif(1,_A)
; L = [1,1,_A,1], dif(1,_A)
; L = [1,_A,1,1], dif(1,_A)
; L = [_A,1,1,1], dif(1,_A)
; false.
So the remaining element must be something different from 1.
That's the fine generality Prolog offers us.
The problem is that as stated by #lurker if condition (or better unification) fails then the predicate will fail. You could make another clause for this purpose, using dif/2 which is pure and defined in the iso:
count(_, [], 0).
count(Num, [H|T], X) :- dif(Num,H), count(Num, T, X).
count(Num, [H|T], X) :- Num = H, count(Num, T, X1), X is X1 + 1.
The above is not the most efficient solution since it leaves many choice points but it is a quick and correct solution.
You simply let the predicate fail at the unification Num = X. Basically, it's like you don't accept terms which are different from the only one you are counting.
I propose to you this simple solution which uses tail recursion and scans the list in linear time. Despite the length, it's very efficient and elegant, it exploits declarative programming techniques and the backtracking of the Prolog engine.
count(C, L, R) :-
count(C, L, 0, R).
count(_, [], Acc, Acc).
count(C, [C|Xr], Acc, R) :-
IncAcc is Acc + 1,
count(C, Xr, IncAcc, R).
count(C, [X|Xr], Acc, R) :-
dif(X, C),
count(C, Xr, Acc, R).
count/3 is the launcher predicate. It takes the term to count, the list and gives to you the result value.
The first count/4 is the basic case of the recursion.
The second count/4 is executed when the head of the list is unified with the term you are looking for.
The third count/4 is reached upon backtracking: If the term doesn’t match, the unification fails, you won't need to increment the accumulator.
Acc allows you to scan the entire list propagating the partial result of the recursive processing. At the end you simply have to return it.
I solved it myself:
count(_, [], 0).
count(Num, [H|T], X) :- Num \= H, count(Num, T, X).
count(Num, [H|T], X) :- Num = H, count(Num, T, X1), X is X1 + 1.
I have decided to add my solution to the list here.
Other solutions here use either explicit unification/failure to unify, or libraries/other functions, but mine uses cuts and implicit unification instead. Note my solution is similar to Ilario's solution but simplifies this using cuts.
count(_, [], 0) :- !.
count(Value, [Value|Tail],Occurrences) :- !,
count(Value,Tail,TailOcc),
Occurrences is TailOcc+1.
count(Value, [_|Tail], Occurrences) :- count(Value,Tail,Occurrences).
How does this work? And how did you code it?
It is often useful to equate solving a problem like this to solving a proof by induction, with a base case, and then a inductive step which shows how to reduce the problem down.
Line 1 - base case
Line 1 (count(_, [], 0) :- !.) handles the "base case".
As we are working on a list, and have to look at each element, the simplest case is zero elements ([]). Therefore, we want a list with zero elements to have no instances of the Value we are looking for.
Note I have replaced Value in the final code with _ - this is because we do not care what value we are looking for if there are no values in the list anyway! Therefore, to avoid a singleton variable we negate it here.
I also added a ! (a cut) after this - as there is only one correct value for the number of occurrences we do not want Prolog to backtrack and fail - therefore we tell Prolog we found the correct value by adding this cut.
Lines 2/3 - inductive step
Lines 2 and 3 handle the "inductive step". This should handle if we have one or more elements in the list we are given. In Prolog we can only directly look at the head of the list, therefore let us look at one element at a time. Therefore, we have two cases - either the value at the head of the list is the Value we are looking for, or it is not.
Line 2
Line 2 (count(Value, [Value|Tail],Occurrences) :- !, count(Value,Tail,TailOcc), Occurrences is TailOcc+1.) handles if the head of our list and the value we are looking for match. Therefore, we simply use the same variable name so Prolog will unify them.
A cut is used as the first step in our solution (which makes each case mutually exclusive, and makes our solution last-call-optimised, by telling Prolog not to try any other rules).
Then, we find out how many instances of our term there are in the rest of the list (call it TailOcc). We don't know how many terms there are in the list we have at the moment, but we know it is one more than there are in the rest of the list (as we have a match).
Once we know how many instances there are in the rest of the list (call this Tail), we can take this value and add 1 to it, then return this as the last value in our count function (call this Occurences).
Line 3
Line 3 (count(Value, [_|Tail], Occurrences) :- count(Value,Tail,Occurrences).) handles if the head of our list and the value we are looking for do not match.
As we used a cut in line 2, this line will only be tried if line 2 fails (i.e. there is no match).
We simply take the number of instances in the rest of the list (the tail) and return this same value without editing it.

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.

Resources