Using Pattern Matching in Prolog to Find Submultisets - list

I am new to prolog and I was wondering if anyone could help me with this problem. The problem: given the integers 1,2,3,4, and the predicates mult/2, div/2, div/2, minus/2, and minus/2, and eval/2, I need to write a predicate solutions/1 that, when called like this:
?- solutions(L).
it should terminate with the variable L unified to a list of expressions with value 6. Expressions are of the form:
X, Y, exp/2
But my code is not working. I have two versions. The first freezes up SWI-Prolog, not returning any answer after I type a period, and not letting me evaluate anything else afterward:
eval(1,1.0).
eval(2,2.0).
eval(3,3.0).
eval(4,4.0).
eval(mult(X,Y),Z) :-
eval(X,A),
eval(Y,B),
Z is A*B.
eval(div(X,Y),Z) :-
eval(X,A),
eval(Y,B),
Z is A/B.
eval(minus(X,Y),Z) :-
eval(X,A),
eval(Y,B),
Z is A-B.
solutions(L) :-
setof(X,eval(X,6),L),
print(L).
The second version just returns false when I type ?- solutions(L).:
solutions(L) :-
setof([exp,X,Y],eval(exp(X,Y),6),L),
print(L).
Thank you so much for taking the time to help!

Maybe you're looking for something like
solutions(L) :-
Ns = [1,2,3,4],
Ex = [*,/,-],
findall((X,Y,E),
(member(X,Ns),member(Y,Ns),member(E,Ex),F=..[E,X,Y],6=:=F),
L).
that yields
?- solutions(L).
L = [(2, 3, (*)), (3, 2, (*))].
Expressions are usually recursive, that is, arguments could be expressions instead of plain numbers. But then, in my opinion your problem is underspecified, as we need criteria to stop the infinite flow of solutions resulting - for instance - by repeated application of operations that don't change the value. Like multiply or divide by 1.

The problem is that your code is going in infinite recursion with eval/2 predicate.
You can try this solution:
num(1).
num(2).
num(3).
num(4).
eval(mult(A,B),Z) :-
num(A),
num(B),
Z is A*B.
eval(div(A,B),Z) :-
num(A),
num(B),
Z is A/B.
eval(minus(A,B),Z) :-
num(A),
num(B),
Z is A-B.
test(L) :-
setof(X,eval(X,6),L),
print(L).
Which yields:
?- test(L).
[mult(2,3),mult(3,2)]
L = [mult(2, 3), mult(3, 2)].

Related

Prolog: compare list elements and sum

New to prolog and trying to implement the following function that takes 3 lists:
True if lists are the same length
True if elements of third list is sum of the two lists
Example: fn([1,2,3],[4,5,6],[5,7,9]) returns true. Note that the sum is element-wise addition.
This is what I have so far:
fn([],[],[]).
fn([_|T1], [_|T2], [_|T3]) :-
fn(T1,T2,T3), % check they are same length
fn(T1,T2,N1), % check that T3=T1+T2
N1 is T1+T2,
N1 = T3.
From what I understand, the error is due to the base case (it has empty lists which causes error with evaluation of addition?)
Thanks for any help and explanations!
In addition to #GuyCoder's answer, I would point out that it is worthwhile to consider using one of the maplist predicates from library(apply) when modifying all elements of lists. You can use a predicate to describe the relation between three numbers...
:- use_module(library(apply)). % for maplist/4
num_num_sum(X,Y,S) :-
S is X+Y.
... and subsequently use maplist/4 to apply it to entire lists:
fn(X,Y,Z) :-
maplist(num_num_sum,X,Y,Z).
This predicate yields the desired results if the first two lists are fully instantiated:
?- fn([1,2,3],[4,5,6],X).
X = [5,7,9]
However, due to the use of is/2 you get instantiation errors if the first two lists contain variables:
?- fn([1,A,3],[4,5,6],[5,7,9]).
ERROR at clause 1 of user:num_num_sum/3 !!
INSTANTIATION ERROR- X is _+B: expected bound value
?- fn([1,2,3],[4,5,A],[5,7,9]).
ERROR at clause 1 of user:num_num_sum/3 !!
INSTANTIATION ERROR- X is A+B: expected bound value
If you only want to use the predicate for lists of integers, you can use CLP(FD) to make it more versatile:
:- use_module(library(apply)).
:- use_module(library(clpfd)). % <- use CLP(FD)
int_int_sum(X,Y,S) :-
S #= X+Y. % use CLP(FD) constraint #=/2 instead of is/2
fnCLP(X,Y,Z) :-
maplist(int_int_sum,X,Y,Z).
With this definition the previously problematic queries work as well:
?- fnCLP([1,A,3],[4,5,6],[5,7,9]).
A = 2
?- fnCLP([1,2,3],[4,5,A],[5,7,9]).
A = 6
Even the most general query yields results with this version:
?- fnCLP(X,Y,Z).
X = Y = Z = [] ? ;
X = [_A],
Y = [_B],
Z = [_C],
_A+_B#=_C ? ;
X = [_A,_B],
Y = [_C,_D],
Z = [_E,_F],
_A+_C#=_E,
_B+_D#=_F ? ;
.
.
.
Since the numbers in the above answers are not uniquely determined, you get residual goals instead of actual numbers. In order to get actual numbers in the answers, you have to restrict the range of two of the lists and label them subsequently (see documentation for details), e.g. to generate lists containing the numbers 3,4,5 in the first list and 6,7,8 in the second list, you can query:
label the lists
restrict the domain | |
v v v v
?- fnCLP(X,Y,Z), X ins 3..5, Y ins 6..8, label(X), label(Y).
X = Y = Z = [] ? ;
X = [3],
Y = [6],
Z = [9] ? ;
X = [3],
Y = [7],
Z = [10] ? ;
.
.
.
X = [3,4],
Y = [6,7],
Z = [9,11] ? ;
X = [3,4],
Y = [6,8],
Z = [9,12] ? ;
.
.
.
On an additional note: there are also clp libraries for booleans (CLP(B)), rationals and reals (CLP(Q,R)) that you might find interesting.
From what I understand, the error is due to the base case.
I don't see it that way.
The first problem I see is that you are trying to process list which leads to thinking about using DCGs, but since you are new I will avoid that route.
When processing list you typically process the head of the list then pass the tail back to the predicate using recursion.
e.g. for length of list you would have
ln([],N,N).
ln([_|T],N0,N) :-
N1 is N0+1,
ln(T,N1,N).
ln(L,N) :-
ln(L,0,N).
The predicate ln/2 is used to set up the initial count of 0 and the predicate ln/3 does the work using recursion. Notice how the head of the list is taken off the front of the list and the tail of the list is passed recursively onto the predicate again. When the list is empty the predicate ln([],N,N). unifies, in this case think copies, the intermediate count from the second position into the third position, which it what is passed back with ln/2.
Now back to your problem.
The base case is fine
fn([],[],[]).
There are three list and for each one look at the list as [H|T]
fn([H1|T1],[H2|T2],[H3|T3])
and the call to do the recursion on the tail is
fn(T1,T2,T3)
all that is left is to process the heads which is
H3 is H1 + H2
putting it all together gives us
fn([],[],[]).
fn([H1|T1], [H2|T2], [H3|T3]) :-
H3 is H1 + H2,
fn(T1,T2,T3).
and a quick few checks.
?- fn([],[],[]).
true.
?- fn([1],[1],[2]).
true.
?- fn([1,2],[3,4],[4,6]).
true.
?- fn([1,2],[3,4,5],[4,6,5]).
false.
With regards to the two conditions. When I look at exercises problems for logic programming they sometimes give a condition like True if lists are the same length or some other condition that returns true. I tend to ignore those at first and concentrate on getting the other part done first, in this case elements of third list is sum of the two lists then I check to see if the other conditions are correct. For most simple classroom exercises they are. I sometimes think teacher try to give out these extra conditions to confuse the student, but in reality the are there just to clarify how the code should work.

List - counting atoms related to their previous term

I want to count the number of elements in a list which have a relation with the element following.
The predicate I have works by using an accumulator variable which it increments if the predicate related returns true.
The following example code is to check the number of times an element is greater than it's previous element.
So for example
count_list([1,2,3,2,1,3,2],Count).
should return 3.
The code almost works. It increments the accumulator variable correctly. However, the function returns false, when it tries to compare the final 2 at the end with the non-existent next term.
listofitems([],N,N).
%count number of items which are related to the previous
listofitems([A,B|T],Acc,N) :-
write(A),write(' '), write(B),
( related(A,B) -> Acc1 is Acc+1 ; Acc1 = Acc ),
write(Acc1),write('\n'),
listofitems([B|T],Acc1,N).
count_list(L,N):-
listofitems(L,0,N).
%define the relationship to be counted
related(A,B):-
B>A.
Does anyone have any suggestions as to how to create an elegant terminating condition so I can return the accumulated value?
Does anyone have any suggestions as to how to create an elegant terminating condition so I can return the accumulated value?
The problem you have is that your query fails. Try first to minimize the query as much as possible. Certainly, you expect it to work for:
?- listofitems([], Count).
Count = 0.
Yet, it already fails for:
?- listofitems([1], Count).
false.
So let's try to dig into the reason for that.
And since your program is pure (apart from those writes), it is possible to diagnose this a little better by considering a generalization of your program. I prefer to look at such generalizations as I do not want to read too much (eye strain and such):
:- op(950, fy, *).
*_.
listofitems([], N,N).
listofitems([A,B|T], Acc,N) :-
* ( related(A,B) -> Acc1 is Acc+1 ; Acc1 = Acc ),
* listofitems([B|T], Acc1,N).
count_list(L,N):-
listofitems(L,0,N).
?- count_list([1], Count).
false.
Even this generalization fails! So now in desperation I try to ask the most general query. It's like when I ask one thing after the other and get a noe after a no. Good this is Prolog, for we can ask: "Say me just everything you know".
?- count_list(Es,Count).
Es = [], Count = 0
; Es = [_,_|_].
So it is only the case for the empty list and lists with at least two elements. But there is no answer for one-elemented lists! You will thus have to generalize the program somehow.
A natural way would be to add a fact
listofitems([_], N, N).
As a minor remark, this isn't called a "terminating condition" but rather a "base case".
And if you really want to trace your code, I recommend these techniques instead of adding manual writes. They are much too prone to error.
If the all list items are integers and your Prolog system supports clpfd, you can proceed like this:
:- use_module(library(clpfd)).
:- use_module(library(lists), [last/3]).
:- use_module(library(maplist), [maplist/4]).
To relate adjacent items, look at two sublists of [E|Es], Es and Fs. If, say,
[E|Es] = [1,2,3,2,1,3,2] holds ...
... then Fs lacks the last item (Fs = [1,2,3,2,1,3,2]) ...
... and Es lacks the first item (Es = [1,2,3,2,1,3,2]).
maplist/4 and i0_i1_gt01/3 map corresponding list items in Fs and Es to 0 / 1:
i_j_gt01(I, J, B) :- % if I #< J then B #= 1
I #< J #<=> B. % if I #>= J then B #= 0
?- maplist(i_j_gt01, [1,2,3,2,1,3], [2,3,2,1,3,2], Bs).
Bs = [1,1,0,0,1,0].
Last, sum up [1,1,0,0,1,0] using sum/3:
?- sum([1,1,0,0,1,0], #=, N).
N = 3.
Let's put it all together!
count_adj_gt([E|Es], N) :-
last(Fs, _, [E|Es]), % or: `append(Fs, [_], [E|Es])`
% or: `list_butlast([E|Es], Fs)`
maplist(i_j_gt01, Es, Fs, Bs),
sum(Bs, #=, N).
Sample query using SICStus Prolog 4.3.2:
?- count_adj_gt([1,2,3,2,1,3,2], N).
N = 3. % succeeds deterministically
not sure about
an elegant terminating condition
my whole code would be
?- Vs=[1,2,3,2,1,3,2], aggregate_all(count, (append(_,[X,Y|_], Vs), X<Y), Count).
That's all...
If you need something more complex, remember that library(clpfd) has more to offer.

Using the printlist/1 predicate in Prolog to sum up all numbers in a list

I am trying to use the printlist/1 predicate to sum up all the numbers in a list but kind of got stuck.... tried to come up with the code for this but I keep getting false.
Here is what I've come up with:
printlist([]).
printlist([H|T], Totalsum) :-
print (H+Totalsum),
nl,
printlist(T, Totalsum).
I know it's wrong and it's probably the last part. Any help is appreciated!
I query it this way:
?- printlist([1,2,3]).
false.
As Paulo already said, you are defining two predicates here, which is incorrect.
Here is the solution:
printlist([], 0).
printlist([H|T], Sum) :-
printlist(T, Subsum),
Sum is Subsum + H.
Sample query:
?- printlist([1,2,3,5], L).
L = 11.
# Paulo requested), a tail recursive version:
printlist(L, Sum) :-
sumac(L, 0, Sum).
sumac([], Acc, Acc).
sumac([H|T], Acc, Sum) :-
Nacc is Acc + H,
sumac(T, Nacc, Sum).
You're defining not one but two predicates: printlist/1 and printlist/2. Likely a typo. The printlist/2 predicate is a recursive rule but there isn't a base case. Change the printlist/1 clause to:
printlist([], _).
But there are other errors in your code. Hint: Prolog is not a functional language.

Prolog, permutation code understanding

I'm trying to understand how this program works.
Code from Daniel Lyons' solution(from the link above)
takeout(X,[X|R],R).
takeout(X,[F |R],[F|S]) :- takeout(X,R,S).
perm([X|Y],Z) :- perm(Y,W), takeout(X,Z,W).
perm([],[]).
I'm trying ti understand how it works with this list [1,2,3]
So, I have perm([1,2,3],X).
It's easy to understand at first, Y = [2,3] then Y = [3] and then Y = []
After that perm([],[]). is called and it gives us W = []
Now, takeout is called for the first time - takeout(3, Z, []).
It returns Z = [3]
Now, we are going back, where perm([],[]). gives us W = [3], (because Y was [3] at this point)
Same as above, takeout(2, Z, [3]) and Z = [2, 3].
Again perm([], []). and W = [2, 3].
And takeout(1, Z, [2, 3]), which gives us first answer Z = [1, 2, 3]
Here I don't know why program don't end , recursion is done, so why takeout and perm are working again ?
After that takeout is called takeout(1, [2,3]).
Which now works with takeout(X,[F |R],[F|S]) and not with takeout(X,[X|R],R). and that's my second question, why?
In Prolog, a predicate's behavior is quite unlike that of a function in procedural languages. A function is called to perform a task, it executes, and then comes back returning some values or having performed some side effects, or both.
A predicate defines a relation and/or set of facts that establish a logical connection between it's arguments. When a query is made to a predicate in Prolog, Prolog will attempt to find every instantiation of the argument variables that will make that predicate succeed (be true).
In a very simple case, I might have the following facts:
likes(tom, mary). % Tom likes Mary
likes(fred, mary). % Fred likes Mary
Here I have one predicate or fact, likes, which defines a relation between two people. We call the above facts because they each specify a precise, concrete relation with fully instantiated arguments. I can make a query to determine Who likes Mary? as follows:
| ?- likes(Person, mary).
Person = tom ? ;
Person = fred
yes
The query first comes back with Person = tom but indicates it has more options to check once it has found that Person = tom satisfies the query. Entering ; tells Prolog to continue with the next solution (if there is one), and it finds it: Person = fred.
Now let's consider takeout/3. This is a predicate which defines a relation between a set of variables.
takeout(X,[X|R],R).
takeout(X,[F|R],[F|S]) :- takeout(X,R,S).
The takeout/3 predicate has two predicate clauses or rules for the relation. It's helpful to try to read them:
R is what you get if you take X out of [X|R].
[F|S] is what you get if you take X out of [F|R] if S is what you get when you take X out of R.
Prolog looks at multiple clauses in a disjunctive way. That is, a query or call to the predicate will succeed if any one of the rules can hold true. When a query on takeout/3 is made, Prolog will look for instantiations of the given variables in the query which will make it true, and it will attempt to find every such instantiation that does so. In other words, if there's more than one way to satisfy the condition, it will backtrack and attempt to find those variables instantiations that do so.
Consider the query:
?- takeout(X, [1,2,3], R).
Prolog is able to match this to the first predicate clause: takeout(X, [X|R], R) as takeout(1, [1,2,3], [2,3]) by instantiating X = 1 and R = [2,3]. So this query will succeed with the following result:
R = [2,3]
X = 1 ?
But we see that Prolog is indicating there are more options to explore. That's because there's another clause: takeout(X,[F|R],[F|S]) which matches the query, takeout(X, [1,2,3], R). Prolog therefore backtracks and attempts the second clause, which matches:
takeout(X, [1|[2,3]], [1|S]) :- % F = 1, R = [2,3]
takeout(X, [2,3], S).
Prolog will then follow the recursive call takeout(X, [2,3], S) and start from the first clause again and attemp to match takeout(X, [2,3], S) with takeout(X, [X|R], R), which succeeds with X = 2 and S = [3] (takeout(2, [2|[3]], [3]).. The recursion unwinds or returns (as it would in any language), and the previous call head, takeout(X, [1|[2,3]], [1|S]) then ends up instantiating as: takeout(1, [1|[2,3]], [1|[3]]). So we get:
R = [2,3]
X = 1 ? ;
R = [1,3] % that is, [1|[3]]
X = 2 ?
And so on. Similar behavior applies to perm. In the context of the query perm, the calls to takeout backtrack to produce additional results, so perm produces additional results (since its calls to takeout backtrack, just like they do when you query takeout by hand).
As noted by #false, the predicate takeout/3 is implemented as a standard predicate in Prolog as select/3.

Print list of lists, Prolog

I got this grid:
tab([[s,f,f,f,s,f,f,f,s],
[f,s,f,f,f,f,f,s,f],
[f,f,s,f,f,f,s,f,f],
[f,f,f,f,f,f,f,f,f],
[s,f,f,f,m,f,f,f,s],
[f,f,f,f,f,f,f,f,f],
[f,f,s,f,f,f,s,f,f],
[f,s,f,f,f,f,f,s,f],
[s,f,f,f,s,f,f,f,s]]).
I want to print in the screen without brackets and commas.
By the way I can't print it right with or without them.
These are the print rules:
viewTab([]).
viewTab([H|T]) :-
printList(H),
viewTab(T).
printList([]) :-
nl.
printList([H|T]) :-
write(H),
write(' | '),
printList(T).
I call it in the Prolog's terminal like:
?- viewTab(X), tab(X).
I can't print a thing, and I get an infinite loop at:
printList([]) :-
nl.
Can you help me find my mistake?
Or some tips to make the code easier to work with.
Your viewTab/1 is not a purely logical predicate: it has a side effect, and it does not terminate for if its argument is a variable.
For example:
?- listing(foo).
foo([]).
foo([_|A]) :-
foo(A).
true.
?- foo(X).
X = [] ;
X = [_G256] ;
X = [_G256, _G259] ;
X = [_G256, _G259, _G262] ;
X = [_G256, _G259, _G262, _G265] ;
X = [_G256, _G259, _G262, _G265, _G268] . % and so on
So this:
?- viewTab(X), tab(X).
Puts a list in X, then tab(X) fails, and you are back at viewTab(X), ad infinitum.
You should try:
?- tab(X), viewTab(X).
Use dcg!
Definite clause grammars are a versatile, logical way of processing input/output.
For a start, read this well-written DCG primer by Markus Triska, also known as #mat on SO!
Right now, as a quick fix, use the built-in predicate format/2 like this:
?- X = [a,b,c], format('~s~n',[X]).
abc % output via side-effect
X = [a, b, c]. % query succeeds