Prolog assigning values to elements of a list - prolog

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

Related

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

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.

Using a univ operator in Prolog

I am trying to develop a prolog procedure that will convert numbers in any given list to a list of their square roots, using the univ (=..). So far I have
convert(X,Y): number(X), Y is X^2.
use([],_,[]).
use([_|X],convert,L):-
convert(X,Y),
L =..[convert,X,Y].
This evaluates false, what could be wrong in my logic or execution?
You could also use maplist/3 to define use/2 with convert/2 as defined in your post:
use(X,Y) :- maplist(convert, X, Y).
?- use([1,2,3],L).
L = [1,4,9]
Note that use/2 is simply failing for lists that contain anything but numbers:
?- use([1,2,3,a],L).
no
There are multiple errors:
why passing the name of the predicate convert/2?
Most important I see no recursive call!!
You ignore head element of the list by writing [_|X] which means a list with a head element and a tail X.
You try to use convert on X which is a list and assign the atom convert(X,Y) to L. Note that prolog is not a procedural language, convert(X,Y) will work only by just calling convert(X,Y) and the result will be in Y, you can't make assignments like: L = convert(X,Y) this will only assign the atom convert(X,Y) to L.
You don't need the operator =.., as a simple solution would be:
convert(X,Y):- number(X), Y is X^2.
use([],[]).
use([H|T],[Y|T1]):-
convert(H,Y),
use(T,T1).

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.

Appending lists in Prolog with functor

I am trying to use Prolog's append and length predicates for the first time in order to split a list, and I believe it requires a recursive solution. I am new to Prolog, and would like some help with this starter problem! :)
Here is the expected code output:
?- splits([1,2,3],S).
S = [1]/[2, 3] ;
S = [1, 2]/[3] ;
false.
It takes a list and splits it, but it does so by creating a structure with the functor /, this is what confuses me so far... I know that I need to use append for this, but how would one do so?
Here is my code so far:
splits([H | T], S) :-
length(T, len), len > 0,
It will run until the tail of the list is empty, and then stop, but I can't quite figure out how to add in the append function or make it recursive... Could someone give me a tip? :)
I would say that you are almost at a working implementation with your remark that append/3 can be used for splitting lists. This is indeed what append/3 in the instantiation (-,-,+) does.
The only added requirement that seems to occur in your question is to exclude cases in which either of the splits is empty. This can be achieved by checking for inequivalence between terms using \==/2.
This results in the following code:
splits(List, X/Y):-
append(X, Y, List),
X \== [],
Y \== [].
PS: Notice that your use of len in your code snippet is wrong, since len is not a Prolog variable but an atom. Handing an atom to the second argument of length/2 produces a type error, and an arithmetic error in len > 0 (provided that len is not defined as a function). (Both observations relate to SWI-Prolog.)
Hope this helps!
Here is a recursive approach:
splits([A,B|T], [A]/[B|T]).
splits([A|T], [A|R]/S) :-
splits(T, R/S).
The first clause provides the base case of splitting a list with at least 2 elements ([A,B|T]) into [A]/[B|T] (it just splits out the first element).
The second clause says that [A|R]/S is the split of [A|T] if R/S is the split of T. So it will "generate" the other solutions recursing down to the base case. If the first list has only two elements, the base case will be successful, and backtrack to the recursive case will fail on the first try (which is what you want - no more solutions to that case) because the recursive case only succeeds when the first list has 3 or more elements (A plus the two enforced on T in the recursive query).
| ?- splits([1], S).
no
| ?- splits([1,2], S).
S = [1]/[2] ? ;
no
| ?- splits([1,2,3], S).
S = [1]/[2,3] ? ;
S = [1,2]/[3] ? ;
no
...

Resources