How to compare a list of constants to a list of variables - prolog

The predicate needs to compare two lists (one of variables, one of constants) like this :
?- test([A,B,B],[1,2,3]).
false.
?- test([A,B,B],[1,2,2]).
true.
?- test([A,B,C],[1,2,2]).
false.
First i associate each variable to its constant with this predicate :
set([],[]).
set([X],[Y]):-X is Y.
set([H1|T1],[H2|T2]):-H1 is H2, set(T1,T2).
It works for the first two exemples above however it doesn't write "true". Also it doesn't work for the third one :
?- set([A,B,C],[1,2,2]).
A = 1,
B = C, C = 2
How do can I modify this predicate so it checks if T1 was already used and in that case if it was associated to a different variable (and therefore return false)?

You can add a dif/2 constraint between every two different variables variables.
We can obtain the list of variables with term_variables/2, and then we can for example design a predicate all_diff/1 that applies dif between every two different variables by making use of maplist/2, like:
all_diff([]).
all_diff([H|T]) :-
maplist(dif(H), T),
all_diff(T).
So we can define our set/2 as:
set(V, W) :-
term_variables(V, VV),
all_diff(VV),
maplist(is, V, W).
The original set/2 can thus be written as maplist/3 with is/2 as goal.
For example:
?- set([A,B,B], [1,2,2]).
A = 1,
B = 2.
?- set([A,B,C], [1,2,2]).
false.
If the second list contains only terms, and you do not want to evaluate expressions, we can - like #DanielLyons says - just use V = W:
set(V, W) :-
term_variables(V, VV),
all_diff(VV),
V = W.
Since the unification algorithm will "peal" the functors, and thus eventually unfiy all elements in the left list with the values in the right list.

Related

Predicate about a list of lists

I'm trying to create a predicate that receives a list of lists and returns a list of lists containing all the unitary lists (lists whose length is 1) from the first list, however it is not working. This is what I created:
elimina_listas_nao_unitarias_lista_de_listas([[A]|T],N_List):-
length([A], 1),
N_List is [H|N_List_T],
elimina_listas_nao_unitarias_lista_de_listas(T, N_List_T).
elimina_listas_nao_unitarias_lista_de_listas([[A]|T], N_List):-
length([A], X),
X > 1,
elimina_listas_nao_unitarias_lista_de_listas(T, N_List2).
Thi is what it should do:
elimina_listas_nao_unitarias_lista_de_listas([[1,2],[1,2,3],[3]], [3])
elimina_listas_nao_unitarias_lista_de_listas([[1,2],[1,2,3],[3,4,5]], [])
It is retuning false currently everytime
Let's take a look at your first rule. The first goal always succeeds, since you are asking if a list with a single element is of length 1. Just try it at the prompt:
?- length([A], 1).
true
Instead, you probably want to have a variable without the brackets in the head of the first list (e.g. [L|Ls]) and ensure that it is a list of length 1:
?- length(L,1).
L = [_A]
The same goes for the first list in the head of your second rule and its first goal. In your second goal you are trying to evaluate [H|N_List_T] as an arithmetic expression with is/2 such that N_List holds the value. Besides the fact that this doesn't make sense, you can try that at the prompt and see how this goal can't succeed:
?- N_List is [H|N_List_T].
ERROR!!
TYPE ERROR- string must contain a single character to be evaluated as an arithmetic expression: expected evaluable term, got [_131245|_131246]
Instead, you want to unify the two terms:
?- N_List = [H|N_List_T].
N_List = [H|N_List_T]
However, you can get rid of this goal entirely if you write [H|N_List_T] as the second argument in the head of the rule. Additionally, you might want the unitary list L in the head of the second list instead of the variable H. Furthermore you are missing a case, namely the first list being []. In that case the second list is empty as well, since the empty list clearly does not contain any unitary lists. Finally, I would note that it might enhance the readability of your code if you picked a somewhat simpler and more declarative name, say listas_unitarias/2. Putting all this together, you might end up with a predicate like this:
listas_unitarias([],[]).
listas_unitarias([L|Ls],[L|Ss]) :-
length(L,1),
listas_unitarias(Ls,Ss).
listas_unitarias([L|Ls],Ss) :-
length(L,X),
dif(X,1),
listas_unitarias(Ls,Ss).
Your second example query yields the desired result
?- listas_unitarias([[1,2],[1,2,3],[3,4,5]],U).
U = []
For your first example query the result is slightly different:
?- listas_unitarias([[1,2],[1,2,3],[3]], U).
U = [[3]] ? ;
no
The only unitary list is in a list itself. That would make more sense, since the first argument might contain more than one such list. Consider the following case:
?- listas_unitarias([[1],[2,3],[4],[]],U).
U = [[1],[4]] ? ;
no
However, if you meant to get the unitary lists one at a time, the predicate would look slightly different:
listas_unitarias2([L|_Ls],L) :-
length(L,1).
listas_unitarias2([_L|Ls],U) :-
listas_unitarias2(Ls,U).
As would the results of the queries:
?- listas_unitarias2([[1,2],[1,2,3],[3]], U).
U = [3] ? ;
no
?- listas_unitarias2([[1],[2,3],[4],[]],U).
U = [1] ? ;
U = [4] ? ;
no
Especially your second example query: It would fail instead of producing the empty list as a solution:
?- listas_unitarias2([[1,2],[1,2,3],[3,4,5]],U).
no
?- listas_unitarias2([[1,2],[1,2,3],[3,4,5]],[]).
no
EDIT: As pointed out by #false in the comments the combined use of length/2 and dif/2 in the third rule doesn't terminate for [_,_|_] so the query
?- listas_unitarias([[1],[_,_|_],[2],[3,4]],U).
U = [[1],[2]] ? ;
U = [[1],[2]] ? ;
...
does not terminate as well. However, it is reasonable to expect termination in this case, since a list headed by two elements certainly can't be unitary. So, instead of using length/2 you might consider describing the four cases that cover all possibilities. 1) If the first list is empty so is the second list. 2) If the head of the first list is [] it's not in the second list. 3) If the head of the first list is [A] it is in the second list. 4) If the head of the first list has at least two elements it's not in the second list.
listas_unitarias([],[]). % case 1)
listas_unitarias([[]|Ls],Ss) :- % case 2)
listas_unitarias(Ls,Ss).
listas_unitarias([[A]|Ls],[[A]|Ss]) :- % case 3)
listas_unitarias(Ls,Ss).
listas_unitarias([[_,_|_]|Ls],Ss) :- % case 4)
listas_unitarias(Ls,Ss).
With this version the above query terminates after finding the only solution:
?- listas_unitarias([[1],[_,_|_],[2],[3,4]],U).
U = [[1],[2]]
The other queries from above yield the same results:
?- listas_unitarias([[1,2],[1,2,3],[3,4,5]],U).
U = []
?- listas_unitarias([[1,2],[1,2,3],[3]], U).
U = [[3]]
?- listas_unitarias([[1],[2,3],[4],[]],S).
S = [[1],[4]]

CLP Prolog - Logic Programming

we have a list of list think an example ?- solve([[40,A,B],[30,B],[60,A,B,C]]),label([A,B,C]). will succeed with replacing B=30,A=10 and C=20.
The constraint with this example is A+B=40, A+B+C=60 and generally every variable are in between 0 and 100. Every list must begin with a constant and it includes at least one variable.
:- use_module(library(clpfd)).
sum([],0). % if the list is empty.
sum([X|XS],Z) :-
sum(XS,Z1),
X in 0..100,
Z #= X+Z1.
solveOne([Const|Var]) :-
sum(Var,Const).
solve([]). % if the list of list is also empty
solve([First|Others]) :-
solveOne(First),
solve(Others).
I am a bit skeptic the idea of base case,facts. Because every list must include at list one variable according to constraints, on the other hand we think about the "empty list" situation.?
First, the obvious problem: you define both a solve/2 and a solve/1 predicate (solve([],0)). The ",0" is probably unwanted.
Apart from that, if you have only a constant, like [X], then solveOne succeeds only if X is zero; otherwise, it fails according to sum([],0). So, in a sense, you indirectly check that you can have at least one variable if you assume your sum is always strictly positive.
In order to explicitely check that there is effectively at least one variable, then you can modify solveOne as follows:
solveOne([Const,V1|Vars]) :-
sum([V1|Vars], Const).
#coredump answer should put you on right track. If you are interested in writing lean code, consider this more succint definition (tested in SWI-Prolog)
solve(L) :- maplist(solveOne, L).
solveOne([C|Vs]) :- Vs ins 0..100, sum(Vs, #=, C).
?- solve([[40,A,B],[30,B],[60,A,B,C]]).
A = 10,
B = 30,
C = 20.

Prolog assigning values to elements of a list

I am new to Prolog and the problem I am dealing with is the following: Given a list of variables, I want to assign a value for each element of that list, and then check if a restriction containing some of those variables is true. This is an example of how I thought it should work:
predicate(L1, Restriction) :-
foreach(member(Var,L1), Var = 1),
Restriction.
But when I write in the console:
? - predicate([A,B,C], A==1).
or
? - predicate([A,B,C], B==1).
or
? - predicate([A,B,C], A==B).
they all return false.
Shouldn't A, B, and C be all equivalent to 1 after the foreach loop?
Paulo explained well what the problem is (+1). Maybe you should correct your code like
predicate(L1, Restriction) :-
maplist(=(1), L1),
Restriction.
that yields the expected output
?- predicate([A,B,C], A==1).
A = B, B = C, C = 1.
The problem is the way the foreach/2 predicate works. The first argument works as a generator and the second argument works as a test for each solution of the generator. But the predicate creates a conjunction where each element is a copy of the second argument. Because of this copying, the variables in the generator never get instantiated (as you're instantiating the copies). This semantics can be illustrated by the following query:
?- foreach(member(Var, [A,B,C]), Var = 1), var(A), var(B), var(C).
true.
As your restriction is the predicate/2 calls is an equality test and a variable is not equal to an integer, all the calls fail.
If your intention is to create a list of a given length with all elements equal to a given term, there are several ways of accomplishing it. For example, using only standard built-in predicates:
?- findall(1, between(1, 3, _), List).
List = [1, 1, 1].

Prolog - how to understand lists

I don't know much, how to understand that fact p([H|T], H, T). I know C/C++/Java etc.. but this looks diferrent. So when i pass first argument to "function" p, it separates it into H and T and makes it accessible through this vars? I don't know how to logically understand this.
http://www.doc.gold.ac.uk/~mas02gw/prolog_tutorial/prologpages/lists.html
p([H|T], H, T).
Lets see what happens when we ask some simple queries.
?- p([a,b,c], X, Y).
X=a
Y=[b,c]
yes
In Prolog we have relations, in a way similar to relationals DBs.
Then p/3 it's a relation among a list (first argument), its head H and its tail T.
Appropriately the tutorial' author used descriptive and synthetic symbols as Variables.
Syntactically, variables are symbols starting Uppercase and can get any value, but only one time (that is, cannot be 'reassigned').
The page you refer to says, "Consider the following fact.
p([H|T], H, T)."
So we must treat this as a fact. That means, it's like having a predicate
p([H|T], H, T):- true. % or, p(L,H,T) :- L=[H|T].
Now, when you query p([a,b,c], X, Y)., one is put besides the other:
p([a,b,c], X, Y). % a query
p([H|T], H, T) :- true. % a rule's clause: _head_ :- _body_.
the equivalences are noted: [a,b,c] = [H|T], X = H, Y = T and treated as unification equations. The first gets further translated into
a = H % list's head element
[b,c] = T % list's tail
because [A|B] stands for a list with A the head element of the list, and B the list's tail, i.e. all the rest of its elements, besides the head. H and T are common mnemonic names for these logical variables.
So on the whole, we get X = H = a, Y = T = [b,c].
This process is what's known as unification of a query and a rule's head (the two things starting with a p "functor", and both having the 3 "arguments").
Since the query and the head of a rule's "clause" matched (had same functor and same number of arguments), and their arguments were all successfully unified, pairwise, using the above substitution, we only need to prove the body of that rule's clause (that was thus selected).
Since it is true, we immediately succeed, with the successful substitution as our result.
That's how Prolog works.
TL;DR: yes, when you call p(L,H,T) with a given list L, it will be destructured into its head H and tail T. But you may call it with a given list T, a value H, and a variable L, and then a new list will be constructed from the head and the tail. And if L is given as well, it will be checked whether its head is H, and its tail is T.
This is because Prolog's unification is bi-directional: A = B is the same as B = A. Unification with a variable is like setting that variable, and unification with a value is like checking the (structural) equality with that value.
Calling p(L,H,T) is really equivalent to the unification L = [H|T].

Prolog: Doubling the value of each element in a list of lists and returning a single list

I need write a set of clauses that take a list of integer lists and return a single list with all the elements doubled.
For example:
?- double([[1,2],[3]], X).
Yes
X = [2,4,6]
I have a set of clauses called mega_append that return a single list from a list of lists.
For example:
?- mega_append([[1,2],[3]], X).
Yes
X = [1,2,3]
Here is my progress (m_a is short for mega_append):
double([],[]).
double(List,[H1|T1]) :-
m_a(List,[H2|T2]),
H1 is 2 * H2,
double(T2, T1).
I'll try to explain how I thought it would work. I flatten the first list and split it up into a head and a tail (H2 and T2). I split the second list into a head and a tail (H1 and T1). I check to make sure that H1 (the doubled value) is equal to 2 times H2 (the original value). If it is then I check the rest of the list. Eventually if they all match correctly I should be left with two empty lists which should match the first clause and return yes.
It works when there is only a single value (for example: double([[1]], X)). Can anyone offer any insight into what I am doing wrong? Is my logic or code incorrect?
Your problem is that T2 is a single list so List after the recursive call is not a list of lists.
To solve this you can first use mega_append to flatten the list and then use an auxiliary predicate to work on the flattened list.
I.e. the double will look like this:
double([],[]).
double(List,X) :-
m_a(List,FList),
double_aux(List, FList).
Edit:
Here is a way to only use one clause since you want to see one.
I recommend using an auxiliary predicate.
double([],[]).
double([[]],[]).
double(List,[H1|T1]) :-
mega_append(List,[H2|T2]),
H1 is 2 * H2,
double([T2], T1).
Using clpfd, we define the dcg nonterminal double//1 like this:
:- use_module(library(clpfd)).
double([]) --> [].
double([D|Ds]) --> {DD #= D*2}, [DD], double(Ds).
Let's run some queries—using phrase/2,
apply:foldl/4, and nonterminal double//1:
:- use_module(library(apply)).
?- phrase(foldl(double,[[1,2],[3]]),Xs).
Xs = [2,4,6].
?- phrase(foldl(double,[[A,B],[C]]),[2,4,6]).
A = 1, B = 2, C = 3.
Want more examples using phrase/[2,3]?
Read this SICStus Prolog manual page!

Resources