How to convert a list of list to a list of tuples in prolog? - prolog

ex [[a,b],[b,c]] to [(a,b),(b,c)].
% Define a predicate that takes a list of lists and returns a list of tuples
convert_list_to_tuple(ListOfLists, ListOfTuples) :-
% Base case: if the input list is empty, return an empty list
ListOfLists = [],
ListOfTuples = [].
convert_list_to_tuple(ListOfLists, ListOfTuples) :-
[Head|Tail] = ListOfLists,
Head =.. Tuple,
convert_list_to_tuple(Tail, TailTuples),
ListOfTuples = [Tuple|TailTuples].
How to convert a list of list to a list of tuples in prolog?
Ex [[a,b],[c.d]]---> [(a,b),(c,d)]

Can just use maplist:
conv([A,B], (A,B)).
?- maplist(conv, [[a,b],[b,c]], L).
L = [(a, b), (b, c)].
Such tuples ("comma lists") are a bad (i.e. confusing) choice. Better to use named atoms:
conv_term(Lst, Term) :-
Term =.. [v|Lst].
?- maplist(conv_term, [[a,b],[c,d,e]], L).
L = [v(a, b), v(c, d, e)].

Why would you use something like (a,b)? It works fine for arity 2, but add more elements — (a,b,c,d,e) — and it gets ugly:
','( a , ','( b , ','( c , ','( d , e ) ) ) )
Prolog's lists are simple syntactic sugar on top of the term ./2, with the atom [] representing the empty list. Hence, the list [a,b] is actually the term .(a,.(b,[])). Congratulations! — you've just reinvented Prolog's list in a clumsy way.
Use a term instead.
Turning a list into such a tuple is trivial — just prepend the list with the desired functor (name) you want to use for the tuple and use the in-built =../2 to map between the list and the tuple:
list_tuple( L , T ) :- T =.. [ tuple | L ] .
Once you have that, turning a list of lists into a list of tuples is likewise trivial:
lists_tuples( [] , [] ) .
lists_tuples( [L|Ls] , [T|Ts] ) :- list_tuple(L,T), lists_tuples(Ls,Ts) .
Evaluating
?- lists_tuples( [ [] , [a] , [a,b] , [a,b,c] , [a,b,c,d], [a,b,c,d,e] ] , Ts ) .
Yields the expected
Ts = [
tuple,
tuple(a),
tuple(a,b),
tuple(a,b,c),
tuple(a,b,c,d),
tuple(a,b,c,d,e)
]
And evaluating
?- lists_tuples( L, [tuple,tuple(a),tuple(a,b),tuple(a,b,c),tuple(a,b,c,d),tuple(a,b,c,d,e)] ).
Similarly yields the expected
L = [[], [a], [a,b], [a,b,c], [a,b,c,d], [a,b,c,d,e]]
You can fiddle with it at https://swish.swi-prolog.org/p/JDhVptgN.pl

Related

Equality of sets

Can anyone help me with the following task: I need to define a predicate eq_set, which succeeds if the sets S1 and S2 are equal when it comes to the number of their elements.
But it works only if they are exactly the same number and order. I want to create a code that shows all varieties and doesn't take order into account. Can you help me,please?
I wrote:
eq_set([],[]).
eq_set([H|T],[H|T1]) :-
eq_set(T,T1).
But it works only if they are exactly the same number and order. I want to create a code that shows all varieties and doesn't take order into account.
The closest translation I have of the assignment, which is in Bulgarian, is: "Define the predicate eq_set, which succeeds if the sets (S1, S2) coincide.
You call them "sets" but the data structure you are using is a list. It is easiest to just sort the two lists:
eq_set(A, B) :-
% prerequisites: A and B are lists without duplicates
sort(A, S),
sort(B, S).
If you want something more complicated (for some reason) you need to be more specific.
With this definition:
?- eq_set([a,b,c], [a,b]).
false. % OK
?- eq_set([a,b,c], [a,b,c]).
true. % OK
?- eq_set([a,c,b], [a,b,c]).
true. % OK
?- eq_set([a,a,b], [a,b,b]).
true. % Not sure....
It really really depends on how the predicate is going to be used.
Assuming that a "set" is indeed a Prolog list without duplicates but not in any particular order; then two sets in that presentation "coincide" if they are permutations of each other. In other words, it would be enough to define eq_set/2 as:
eq_set(A, B) :-
my_permutation(A, B).
and just use the textbook definition of permutation/2 which uses the textbook definition of select/3 (See "The Art of Prolog (Second Edition)" by Sterling and Shapiro, pp 67-9):
my_permutation([], []).
my_permutation(Xs, [Y|Ys]) :-
my_select(Y, Xs, Xs0),
my_permutation(Xs0, Ys).
my_select(X, [X|Xs], Xs).
my_select(X, [Y|Ys], [Y|Zs]) :-
my_select(X, Ys, Zs).
(I renamed those just to make sure I am not using the standard library definitions; SWI-Prolog has both select/3 and permutation/2 in the autoloaded library(lists); the definitions are basically the same, but they do some run-time type-checking on the arguments.)
Here is how you can use it:
?- eq_set([1,2,3], [2,3,1]).
true ;
false.
?- eq_set([1,2,3], S).
S = [1, 2, 3] ;
S = [1, 3, 2] ;
S = [2, 1, 3] ;
S = [2, 3, 1] ;
S = [3, 1, 2] ;
S = [3, 2, 1] ;
false.
?- eq_set([1,2,3], [1,2]).
false.
?- eq_set(A, B).
A = B, B = [] ;
A = B, B = [_4480] ;
A = B, B = [_4480, _4492] ;
...
I am not sure how useful the last query is. You can force it to enumerate solutions in order of increasing size of the "set", like this:
?- length(S1, _), eq_set(S1, S2), numbervars(S1).
S1 = S2, S2 = [] ;
S1 = S2, S2 = [A] ;
S1 = S2, S2 = [A, B] ;
S1 = [A, B],
S2 = [B, A] ;
S1 = S2, S2 = [A, B, C] ;
S1 = [A, B, C],
S2 = [A, C, B] ;
S1 = [A, B, C],
S2 = [B, A, C] ;
S1 = [A, B, C],
S2 = [B, C, A] ;
S1 = [A, B, C],
S2 = [C, A, B] ;
S1 = [A, B, C],
S2 = [C, B, A] ;
S1 = S2, S2 = [A, B, C, D] .
(Don't worry about the numbervars, it is just there to give readable names to all the free variables in the sets. Keep in mind that unifying two free variables makes them the same variable.)
This is a starting point, but maybe it is already good enough. The most glaring omission is that it doesn't require the arguments to be lists without duplicates. One way to define this would be to require that each element is different from all other elements. Since "is different" is commutative, you can define it like this:
is_set([]).
is_set([X|Xs]) :-
all_different(Xs, X),
is_set(Xs).
all_different([], _).
all_different([Y|Ys], X) :-
dif(X, Y),
all_different(Ys, X).
This uses dif/2 which is a widely available predicate (but does your Prolog have it?).
We would have maybe used maplist for that last one:
is_set([]).
is_set([X|Xs]) :-
maplist(dif(X), Xs).
is_set(Xs).
You are pretty close in your solution.
We have two cases
1) The first list argument is bigger
2) The second list argument is bigger
If you already know which one is bigger, you can just do
%in case the left one is longer
eq_set_left(_,[]).
eq_set_left(X,[H|T]):-member(H,X), eq_set_left(X,T).
So a very simple solution and yet very optimal could be this:
%in case the right one is longer
eq_set_right([],_).
eq_set_right([H|T], X):- member(H,X), eq_set_right(T,X).
%in case the left one is longer
eq_set_left(_,[]).
eq_set_left(X,[H|T]):-member(H,X), eq_set_left(X,T).
%both cases, equal length is also included here
eq_set(X,Y):- eq_set_left(X,Y).
eq_set(X,Y):- eq_set_right(X,Y).
eq_set(X, Y) is true if either X is subset of Y, Y is subset of X or they are equal
A set is defined as a collection of distinct things where order is not important, which is to say that sets {a,b,c} and {b,a,c} are identical.
From that, one could say that two sets are identical if neither set contains an element that is not also found in the other (or conversely, two sets are not identical if either set contains an element not found in the other.
From that, one could simply say:
eq_set(Xs,Ys) :-
findall( (Xs,Ys) , ( member(X,Xs), \+ member(X,Ys) ), [] ),
findall( (Xs,Ys) , ( member(Y,Ys), \+ member(Y,Xs) ), [] )
.
Or if you don't want to use the built-in findall/3,
eq_set(Xs,Ys) :-
a_not_in_b( Xs , Ys , [] ) ,
a_not_in_b( Ys , Xs , [] ) .
a_not_in_b( [] , [] , [] ) .
a_not_in_b( [A|As] , Bs , Xs ) :- member(A,Bs) , a_not_in_b( As, Bs, Xs ) .
a_not_in_b( [A|As] , Bs , Xs ) :- a_not_in_b( As, Bs, [A|Xs] ) .
One should note that both of these has roughly O(N2) performance. If the sets in question are large, you might want to first sort each set and then merge the two sorted lists to identify those elements that are not common to both sets:
eq_set(Xs,Ys) :-
sort(Xs,X1),
sort(Ys,Y1),
X1 == Y1.

Prolog list of predicates to list of lists

I have a list like: [a([x,y]), b([u,v])] and I want my result as [[x,y], [u,v]].
Here is my code:
p(L, Res) :-
findall(X, (member(a(X), L)), A1), append([A1],[],L1),
findall(Y, (member(b(Y), L)), A2), append(L1,[A2],L2),
append(L2, Res).
This provides a partially good result but if my list is [a([x,y]), c([u,v])], I would like the result to be: [[x,y],[]] and it is [[x,y]].
More examples:
p([b([u,v]), a([x,y]), c([s,t]), d([e,f])], R)
The result I get: [[x,y],[u,v]] (as expected).
p([b([u,v]), z([x,y]), c([s,t]), d([e,f])], R)
The result I get: [[u,v]]'.
The result I want: [[],[u,v]].
EDIT: Added more examples.
Now that it's clear what the problem statement really is, the solution is a little more understood. Your current solution is a little bit overdone and can be simplified. Also, the case where you want to have a [] element when the term isn't found falls a little outside of the paradigm, so can be handled as an exception. #AnsPiter has the right idea about using =../2, particularly if you need a solution that handles multiple occurrences of a and/or b in the list.
p(L, Res) :-
find_term(a, L, As), % Find the a terms
find_term(b, L, Bs), % Find the b terms
append(As, Bs, Res). % Append the results
find_term(F, L, Terms) :-
Term =.. [F, X],
findall(X, member(Term, L), Ts),
( Ts = [] % No results?
-> Terms = [[]] % yes, then list is single element, []
; Terms = Ts % no, then result is the list of terms
).
Usage:
| ?- p([b([u,v]), z([x,y]), c([s,t]), d([e,f])], R).
R = [[],[u,v]]
yes
| ?- p([b([x,y]), a([u,v])], L).
L = [[u,v],[x,y]]
yes
| ?-
The above solution will handle multiple occurrences of a and b.
If the problem really is restricted to one occurrence of each, then findall/3 and append/3 are way overkill and the predicate can be written:
p(L, [A,B]) :-
( member(a(A), L)
-> true
; A = []
),
( member(b(B), L)
-> true
; B = []
).
Term =.. List : Unifies List with a list whose head is the atom corresponding to the principal functor of
Term and whose tail is a list of the arguments of Term.
Example :
| ?- foo(n,n+1,n+2)=..List.
List = [foo,n,n+1,n+2] ?
| ?- Term=..[foo,n,n+1,n+2].
Term = foo(n,n+1,n+2)
rely on your suggestion; you have a term contains a single argument List
so ;
p([],[]).
p([X|Xs], Result) :-
X=..[F,Y],
(%IF
\+(F='c')-> % not(F=c)
Result=[Y|Res];
%ELSE
Result = Res % Result = [Res] ==> [[x,y],[]]
),
p(Xs,Res).
Test :
| ?- p([a([x,y]), c([u,v])],R).
R = [[x,y]] ?
yes
| ?- p([a([x,y]), b([u,v])],R).
R = [[x,y],[u,v]] ?
yes

Sum and square root list elements

So I am currently trying to compute a formula using Prolog. I currently have part of the formula done, but I am having trouble implementing the next part where I need to add the elements of the list and then square root the sum. Not sure how I would do that.
What I currently have:
formula([], [], []).
formula([], [H2|T2], [L|Ls]) :-
L = H2,
formula([], T2, Ls).
formula([H1|T1], [], [L|Ls]) :-
L = H1,
formula(T1, [], Ls).
formula([H1|T1], [H2|T2], [L|Ls]) :-
L is (H1 - H2)*(H1 - H2),
formula(T1, T2, Ls).
Your original formula
formula([], [], []).
formula([], [H2|T2], [L|Ls]) :-
L = H2,
formula([], T2, Ls).
formula([H1|T1], [], [L|Ls]) :-
L = H1,
formula(T1, [], Ls).
formula([H1|T1], [H2|T2], [L|Ls]) :-
L is (H1 - H2)*(H1 - H2),
formula(T1, T2, Ls).
can be simplified to make the pattern matching more explicit:
formula( [] , [] , [] ) .
formula( [] , [Y|Ys] , [Y|Zs] ) :- formula( [] , Ys , Zs ) .
formula( [X|Xs] , [] , [X|Zs] ) :- formula( Xs , [] , Zs ) .
formula( [X|Xs] , [Y|Ys] , [Z|Zs] ) :-
L is ( X - Y ) * ( X - Y ) ,
formula(Xs,Ys,Zs)
.
I assume your instructor wants you to roll your own here and learn about recursion rather than using a built-in predicate. So, ... You could sum the elements of a list like this (the naive implementation):
sum_of( [] , 0 ) . % the sum of the empty list is zero.
sum_of( [X|Xs] , S ) :- % the sum of an empty list is computed by
sum(Xs,T) , % - computing the sum of the tail of the list
S is T+X % - and adding that to the value of the head of the list.
. %
But that will fail with a stack overflow once the list gets sufficiently long as each recursive call pushes a new frame onto the stack. Prolog has an nifty optimization (tail recursion optimization) that effectively converts recursion into iteration by recognizing when it can reuse the stack frame. To do that, the recurive call must be the very last thing done.
This introduces a common pattern in prolog programming:
a public interface predicate (here, sum_of/2),
that invokes a "private" tail-recursize worker predicate (here, sum_of/3) that uses an accumulator argument to build up its result.
Using that pattern, we get this implementation:
sum_of(Xs,Sum) :- sum_of(Xs,0,Sum) .
sum_of( [] , S , S ) . % the sum of the empty list is 0.
sum_of( [X|Xs] , T , S ) :- % the sum of a non-empty list is computed by
T1 is T+X , % incrementing the accumulator by the value of the head of the list, and
sum_of( Xs , T1 , S ) % recursing down on the tail.
. % Easy!
This will work for lists of any length.
Using the SWI-Prolog library predicate sum_list/2:
list_summed_and_square_rooted(List, Value) :-
sum_list(List, Sum),
Value is sqrt(Sum).
You probably don't need to write a separate predicate for relating a list to the square root of the sum of its elements, unless you'll be needing to use that particular relation often. Your formula/3 makes one list out of two, but ultimately you seem to be after a numerical value, so you probably do want another predicate to describe the relation between two lists and the resultant numerical value.
lists_processed_in_some_way(List1, List2, Value) :-
formula(List1, List2, CombinedList),
sum_list(CombinedList, Sum),
Value is sqrt(Sum).
By the way, you can simplify your formula/3 because you don't need L = H2:
formula([], [H2|T2], [H2|Ls]) :-
formula([], T2, Ls).
Also, it's generally good practice to name your predicates carefully, with something descriptive. It will help you reason about what your predicates do and help you communicate your programs to others.

Appending lists in prolog without repetition

I need to know how can i get all of combination of appending two lists with each other without repetition like [1,2] & [3,4] the result will be [1,3] [1,4] [2,3] [2,4]
This is the solution that does not work as desired:
(1) comb([], [], []).
(2) comb([H|T], [X|Y], [H,X]).
(3) comb([H,T|T1], [X,Y|T2], [T,Y]).
(4) comb([H|T], [X|Y], L) :-
comb(T, Y, [H|X]).
(1) says, Combining an empty list with an empty list is an empty list. This sounds logically correct.
(2) says, [H,X] is a pair of elements from [H|T] and [X|Y]. This is true (provides only one of the combinations for the solution).
(3) says, [T,Y] is a pair of elements from [H,T|T1] and [X,Y|T2]. This is also true (provides only one other combination for the solution, different to #2).
(4) says, L is a pair of elements from [H|T] and [X|Y] if [H|X] is a pair of elements from T and Y. This can't be true since L doesn't appear in the consequent of the clause, so it will never be instantiated with a value.
The above solution is over-thought and more complicated than it needs to be. It fails because it hard-codes two solutions (matching the first two elements and the second two elements). The recursive clause is then faulty since it doesn't have a logical basis, and the solution is left as a singleton variable.
To start, you need to decide what your predicate means. In this particular problem, you can think of your predicate comb(Xs, Ys, P). as being TRUE if P is a pair (say it's [X,Y]) where X is from Xs (i.e., X is a member of Xs) and Y is from Ys (Y is a member of Ys). Then, when you query your predicate, it will prompt you with each solution until all of them have been found.
This problem can be stated with one rule: [X,Y] is a combination of elements taken from Xs and Ys, respectively, if X is a member of Xs and Y is a member of Ys. That sounds like a trivially true statement, but it's all you need to solve this problem.
Translating this into Prolog gives this:
comb(Xs, Ys, [X,Y]) :- % [X,Y] is combination of elements from Xs and Ys if...
member(X, Xs), % X is a member of Xs, and
member(Y, Ys). % Y is a member of Ys
Now let's try it:
| ?- comb([1,2],[3,4],P).
P = [1,3] ? ;
P = [1,4] ? ;
P = [2,3] ? ;
P = [2,4]
(2 ms) yes
| ?-
It found all of the combinations. We let Prolog do all the work and we only had to declare what the rule was.
If you want to collect all the results in a single list, you can use a built-in predicate such as findall/3:
| ?- findall(P, comb([1,2], [3,4], P), AllP).
AllP = [[1,3],[1,4],[2,3],[2,4]]
yes
| ?-
And voilà. :)
You can also generalize the solution very easily and choose one element each from each list in a given list of lists. Here, multicomb/2 has as a first argument a list of lists (e.g., [[1,2], [3,4]]` and generates every combination of elements, one from each of these sublists:
multicomb([L|Ls], [X|Xs]) :-
member(X, L),
multicomb(Ls, Xs).
multicomb([], []).
Which gives:
| ?- multicomb([[1,2],[3,4]], P).
P = [1,3] ? a
P = [1,4]
P = [2,3]
P = [2,4]
yes
| ?-
And:
| ?- multicomb([[1,2],[a,b],[x,y,z]], P).
P = [1,a,x] ? a
P = [1,a,y]
P = [1,a,z]
P = [1,b,x]
P = [1,b,y]
P = [1,b,z]
...

SICStus Prolog Lists

Having trouble understanding how Prolog works. I'm tryig to write a rule that takes three lists of integers as input (representing sets) and puts the integers that belong to both the first and second list in the third list.
Example:
?-inter([10,20,30,40],[10,50,40,60], List3 )
List3 = [10, 40]
So far I have this, that can recognize if a list contains a certain letter:
mymember(X,[X|T]).
mymember(X,[H|T]) :- mymember(X,T).
There's actually an inbuilt library to sort that all out for you, known as ordsets.
inter(X, Y, Z) :-
list_to_ord_set(X, L1),
list_to_ord_set(Y, L2),
ord_intersection(L1, L2, Z).
Using your example input you get the following
| ?- inter([10,20,30,40],[10,50,40,60],X).
X = [10,40] ? ;
no
inter(Xs, Ys, Zs) will be true when each element in Zs also is in Xs and in Ys.
But Zs are unknown, then a more constructive approach is required.
Here it is: iterate on Xs and store in Zs each element that is in Ys.
An example of iteration is mymember/2, you can see that it requires a recursive predicate.
The other idiomatic part of the above statement is store in Zs, Prolog has a peculiar way to do such things, using pattern matching.
inter([X|Xs], Ys, [X|Zs]) :-
mymember(X, Ys), inter(Xs, Ys, Zs).
You will need to complete inter/3 with other 2 clauses: base recursion, i.e. when all Xs elements have been processed, and the case where X is not a member of Ys.
Try something like this, using the builtins member/2 and setof\3:
set_intersection( As , Bs , Xs ) :-
set_of( X , ( member(X,As) , member(X,Bs) ) , Xs )
.
One should note that this will fail if the lists As and Bs have no elements in common. An alternative would be use findall/3 rather than set_of/3. findall/3 will hand back and empty list rather than failure if the goal is not satisfied:
set_intersection( As , Bs , Xs ) :-
findall( X , ( member(X,As) , member(X,Bs) ) , Xs )
.
However findall/3 returns a bag (duplicates are allowed) rather than a set (no duplicates allowed), so if your two source lists aren't sets, you won't get a set out.
member/2 is a builtin predicate that unifies its first argument with an element of the list — the equivalent of
member(X,[X|_).
member(X,[_|Xs) :- member(X,Xs) .
And, finally, as #chac noted in his answer, you can recursively traverse the list.
set_intersection( [] , _ , [] ) . % the intersection of the empty set with anything is the empty set.
set_intersection( [A|As] , Bs , [A|Xs] ) :- % if the list is non-empty,
member(A,Bs) , % - and A is a member of the 2nd set
! , % - we cut off alternatives at this point (deterministic)
set_intersection( As , Bs , Xs ) % - and recurse down on the tail of the list.
.
set_intersection( [_|As] , Bs , Xs ) :- % if the list is non-empty, and A is NOT a embmer of the 2nd set
set_intersection( As , Bs , Xs ) % we just recurse down on the tail of the list.
.
#chac's technique builds the result list as he goes, something like:
[a|X]
[a,b|X]
[a,b,c|X]
The final unification, the special case of the empty list unifies the unbound tail of the list with [] making the list complete, so the final [a,b,c|X] becomes
[a,b,c]
A little prolog magic. An alternative that might be easier to understand is to use a worker predicate with an accumulator:
%
% set_intersection/3: the public interface predicate
%
set_intersection( As , Bs , Xs ) :-
set_intersection( As , Bc , [] , T ) % we seed our accumulator with the empty list here
.
%
% set_intersection/4: the private worker bee predicate
%
set_intersection( [] , _ , T , Xs ) :- % since our accumulator is essentially a stack
reverse(T,Xs) % we need to reverse the accumulator to
. % put things in the expected sequence
set_intersection( [A|As] , Bs , T , Xs ) :-
member( A, Bs ) ,
! ,
T1 = [A|T] ,
set_intersection( As , Bs , T1 , Xs )
.
set_intersection( [_|As] , Bs , T , Xs ) :-
set_intersection( As , Bs , T , Xs )
.

Resources