Prolog printing all solutions and wanting to get yes/no output - prolog

I just started learning Prolog and my task is to write a predicate poklapanje(M,V) which returns yes if all the elements of list M are the first elements of list V, for example poklapanje([1,2],[1,2,3]) should return yes. The first question I have is what is the difference between true and yes, because I am getting true in my solution? Second, when I type poklapanje(X,[1,2,3]) I should get:
X = [];
X = [1];
X = [1,2];
X = [1,2,3];
no
and I get:
X = [];
false
Why? I guess it has something to do with my implementation and printing true/false instead of yes/no.
Here is my code:
poklapanje([],[_|_]).
poklapanje([A|B],[C|D]):- A == C, poklapanje(B,D).

There is no difference between yes and true. It's just difference between Prolog implementations. For example, we get true in SWI-Prolog, and yes in GNU Prolog.
I'm not sure how you posed your query. Here's the output from running your code:
?- poklapanje(X,[1,2,3]).
X = [] ;
X = [1] ;
X = [1, 2] ;
false.
It's missing [1, 2, 3] because poklapanje([],[_|_]). fails for poklapanje([],[]).
I would implement it like this:
poklapanje([], _).
poklapanje([A|B],[A|D]) :- poklapanje(B,D).

Since I cannot add a comment (not enough reputation), i'm putting this here. I'll try to explain why your code doesn't work and why Fabricator's code works.
First problem you have, is
A == C
which is not doing what you wanted to achieve. Instead, you want to unify variables, so use
A = C
or even better, as suggested in the correct answer
poklapanje([A|B],[A|D])
If you do it with A == C, in the second step you would have 1 == C, and this will fail as C is not equal to 1.
Second issue, which is already explained, is
poklapanje([],[_|_]).
which will fail in the last step, where D is an empty list. Empty list doesn't have any members, so it will not unify with [ _ | _ ]. You might be tempted to use [ _ ] to fix this problem, but that would unify only with the list which has one member. That's why you have to use _, which will unify with any list:
poklapanje([], _).
Hope it clears it up for you a bit. :-)

Related

Prolog nth1 anonymous variables

I have a List with Integers and anonymous variables and I try to find the index of a special values. Problem is as soon I'm using nth1/3 to find the indices Prolog assigns values to the anonymous variables and therefore I find way too indices.
Example:
List = [1,\_,1], where I want as result X = 1, X = 3 from nth1(X,List,1), but as stated before I get X = 1, X = 2, X = 3.
There is a somewhat problematic issue hidden in your requirements: They violate an important declarative property called monotonicity. By this we mean that adding constraints can at most make the solution more specific, never more general.
For example, with the solution you posted, we get:
?- list_el_index([_], 1, N).
false.
Now I add a constraint by imposing an additional requirement on the hitherto free anonymous variable:
?- Var = 1, list_el_index([Var], 1, N).
Var = 1,
N = 0 .
I mean: Come on! We have added a constraint, and as a result get more solutions than before? Such a result is unfortunate and prevents us from reasoning in a logical way about this program.
The program also fails us in other respects. For example, let us ask: Which solutions are there at all?
?- list_el_index(Ls, El, I).
nontermination
Ideally, we would like the program to generate solutions in such cases! This generality is one of the foremost attractions of logic programming, and distinguishes it from more low-level paradigms.
One way to solve such issues is to symbolically distinguish the different kinds of elements that appear in your list.
For example, let us use:
u for an unknown value.
i(I) for an integer I.
With this new representation, your solution becomes:
list_el_index([i(I)|_], I, 0).
list_el_index([_|Tail], Element, Index) :-
list_el_index(Tail, Element, Index0),
Index #= Index0+1.
I have also taken the liberty to replace (is)/2 by (#=)/2, to advertise and stick to more general integer arithmetic that lets us more freely reorder the goals, if necessary. Depending on your Prolog implementation, you may have to import a library to benefit from (#=)/2.
With this representation, your initial case becomes:
?- list_el_index([i(1),u,i(1)], 1, Index).
Index = 0 ;
Index = 2 ;
false.
This works as desired!
Importantly, we can use the predicate also more generally, namely to generate possible answers:
?- list_el_index(Ls, El, I).
Ls = [i(El)|_2994],
I = 0 ;
Ls = [_2992, i(El)|_3000],
I = 1 ;
Ls = [_2992, _2998, i(El)|_3006],
I = 2 ;
Ls = [_2992, _2998, _3004, i(El)|_3012],
I = 3 .
Due to the program's monotonicity, we can fairly enumerate solutions by iterative deepening:
?- length(Ls, _), list_el_index(Ls, El, I).
Ls = [i(El)],
I = 0 ;
Ls = [i(El), _4812],
I = 0 ;
Ls = [_4806, i(El)],
I = 1 ;
Ls = [i(El), _4812, _4818],
I = 0 ;
etc.
This has become possible by using a representation that lets us distinguish the cases by pattern matching. Consider using this approach to make your programs usable in all directions, and to make logical reasoning applicable. It is quite easy to apply by using the appropriate wrapper or constant, and greatly increases the generality of your programs.
This works :
- L = [1,_,1], nth1(X, L, Y), ground(Y), Y= 1.
L = [1,_310914,1],
X = Y, Y = 1 ;
L = [1,_310914,1],
X = 3,
Y = 1.
Thanks to lurkers hint, I came up with this solution.
list_el_index([El1|_], El2, 0) :-
El1 == El2.
list_el_index([_|Tail], Element, Index) :-
list_el_index(Tail, Element, Index1),
Index is Index1+1.

How can I assert facts about all List members in Prolog?

I'd like to assert facts about all members of a List in prolog, and have any resulting unification retained. As an example, I'd like to assert that each list member is equal to five, but none of the below constructs does this:
?- L=[X,Y,Z], forall(member(E,L), E=5).
L = [_h27057686,_h27057704,_h27057722]
X = _h27057686
Y = _h27057704
Z = _h27057722
yes
?- L=[X,Y,Z], foreach(member(E,L), E=5).
L = [_h27057686,_h27057704,_h27057722]
X = _h27057686
Y = _h27057704
Z = _h27057722
yes
I would like a way to pose the query such that X=5,Y=5, and Z=5.
There is a lot of terminology that you might be getting wrong, or I am misunderstanding you.
"Equal to" is not the same as "could unify", or "unify", but it depends how you mean it.
With SWI-Prolog, from the top level:
?- X == 5.
false. % the free variable X is not the integer 5
?- unifiable(X, 5, U).
U = [X=5]. % you could unify X with 5, then X will be 5
?- X = 5.
X = 5. % X unifies with 5 (and is now bound to the integer 5)
The comment by CapelliC already has the answer that you are most likely after: given a list of variables (either free or not), make so that each variable in the list is bound to the integer 5. This is best done by unification (the third query above). The maplist simply applies the unification to each element of the list.
PS. In case you are wondering how to read the maplist(=(5), L):
These three are equivalent:
maplist(=(5), [X,Y,Z])
maplist(=, [5,5,5], [X,Y,Z])
X=5, Y=5, Z=5
And of course X=5 is the same as =(X,5).

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

Creating concatenation predicate in prolog that works with only one input instantiation

Is it possible to create a predicate in Prolog that concatenates two lists and works in any case of these:
concat(X,Y,[1,2,3,4])
concat(X,[2,3,4],[1,2,3,4])
concat([1,2,3],X,[1,2,3,4])
The best I could make so far was this:
concat([],[],[]).
concat([],X,X).
concat(X,[],X).
concat([X|Y],[A|B],[X|Z]) :- add(Y,[A],K) , add(K,B,Z) .
with the following results:
works correctly:
concat([1,2,3],X,[1,2,3,4])
gives correct answer, then enters infinite loop:
concat(X,[2,3,4],[1,2,3,4])
gives some results (edit: all results, I believe), then enters infinite loop:
concat(X,Y,[1,2,3,4])
results given:
?- concat(X,Y,[1,2,3,4]).
X = [],
Y = [1,2,3,4] ? ;
X = [1,2,3,4],
Y = [] ? ;
X = [1],
Y = [2,3,4] ? ;
X = [1,2],
Y = [3,4] ? ;
X = [1,2,3],
Y = [4] ? ;
I'm trying to make this predicate to learn more about prolog.
As stated, you're just redefining append/3. However, as a learning experience you should notice that you can do this in a simpler and more Prolog-y way:
concat([],X,X).
concat([X|Y],A,[X|Z]) :-
concat(Y,A,Z).
As you see, the definitions for empty second list are needless because in the first definition Prolog copies (or more exactly, unifies) second list to the third (or vice versa) even if it is an empty one. You need to handle an empty list only in the first list to stop the recursion. Besides, using pattern matching you don't need extra predicates to move the head items from a list to another.

Use cut in Prolog to define a once_member/2 function

Disclaimer: This is informal and non-assessed coursework to do in my own time. I have tried it myself, failed and am now looking for some guidance.
I am trying to implement a version of the member/2 function which will only return members for a list once.
For example:
| ?- member(X, [1,2,3,1]).
X = 1 ? ;
X = 2 ? ;
X = 3 ? ;
X = 1 ? ;
I would like it to only print out each number a maximum of once.
| ?- once_member(X, [1,2,3,1]).
X = 1 ? ;
X = 2 ? ;
X = 3 ? ;
no
We have been told to do this with the cut '!' operator but I have looked over the notes for my course for cut and more online and yet still can't make it click in my head!
So far I have managed to get:
once_member(E, [E | L]) :- !.
once_member(E, [_, L]) :-
once_member(E, L).
Which returns 1 and then nothing else, I feel like my cut is in the wrong place and preventing a backtrack for each possible match but I'm really not sure where to go with it next.
I have looked in my course notes and also at: http://www.cs.ubbcluj.ro/~csatol/log_funk/prolog/slides/5-cuts.pdf and Programming in Prolog (Google Books)
Guidance on how to logically apply the cut would be most useful, but the answer might help me figure that out myself.
We have also been told to do another method which uses '\+' negation by failure but hopefully this may be simpler once cut has twigged for me?
Remove redundant answers and stay pure!
We define memberd/2 based on if_/3 and (=)/3:
memberd(X, [E|Es]) :-
if_(X = E, true, memberd(X, Es)).
Particularly with meta-predicates, a different argument order may come in handy sometimes:
list_memberd(Es, X) :-
memberd(X, Es).
Sample query:
?- memberd(X, [1,2,3,1]).
X = 1 ;
X = 2 ;
X = 3 ;
false.
The solution with cut... at first it sounds quite troublesome.
Assuming that the first argument will be instantiated, a solution is trivial:
once_member(X,L):-
member(X,L),!.
but this will not have the behavior you want if the first arg is not instantiated.
If we know the domain of the lists elements (for example numbers between 1 and 42) we could instantiate the first argument:
once_member(X,L):-
between(1,42,X),
member_(X,L).
member_(X,L):-
member(X,L),!.
but this is veeery inefficient
at this point, I started to believe that it's not possible to do with just a cut (assuming that we dont use + or list_to_set/2
oh wait! < insert idea emoticon here >
If we could implement a predicate (like list_to_set/2 of swi-prolog) that would take a list and produce a list in which all the duplicate elements are removed we could simply use the normal member/2 and don't get duplicate results. Give it a try, I think that you will be able to write it yourself.
--------Spoilers------------
one_member(X,L):-
list_to_set(L,S),
member(X,S).
list_to_set([],[]).
list_to_set([H|T],[H|S]):-
remove_all(H,T,TT),
list_to_set(TT,S).
%remove_all(X,L,S): S is L if we remove all instances of X
remove_all(_,[],[]).
remove_all(X,[X|T],TT):-
remove_all(X,T,TT),!.
remove_all(X,[H|T],[H|TT]):-
remove_all(X,T,TT).
As you see we have to use a cut in remove_all/3 because otherwise the third clause can be matched by remove_all(X,[X|_],_) since we do not specify that H is different from X. I believe that the solution with not is trivial.
Btw, the solution with not could be characterized as more declarative than the solution with cut; the cut we used is typically called a red cut since it alters the behavior of the program. And there are other problems; note that, even with the cut, remove_all(1,[1,2],[1,2]) would succeed.
On the other hand it's not efficient to check twice for a condition. Therefore, the optimal would be to use the if-then-else structure (but I assume that you are not allowed to use it either; its implementation can be done with a cut).
On the other hand, there is another, easier implementation with not: you should not only check if X is member of the list but also if you have encountered it previously; so you will need an accumulator:
-------------Spoilers--------------------
once_member(X,L):-
once_member(X,L,[]).
once_member(X,[X|_T],A):-
\+once_member(X,A).
once_member(X,[H|T],A):-
once_member(X,T,[H|A]).
once_member(X, Xs) :-
sort(Xs, Ys),
member(X, Ys).
Like almost all other solutions posted, this has some anomalies.
?- X = 1, once_member(X, [A,B]).
X = A, A = 1
; X = B, B = 1.
?- X = 1, once_member(X, [A,A]).
X = A, A = 1.
Here's an approach that uses a cut in the definition of once_member/2 together with the classic member/2 predicate:
once_member(X,[H|T]) :-
member(H,T),
!,
once_member(X,T).
once_member(H,[H|_]).
once_member(X,[_|T]) :-
once_member(X,T).
Applied to the example above:
?- once_member(X,[1,2,3,1]).
X = 2 ;
X = 3 ;
X = 1 ;
no
Note: Despite the odd-appearing three clause definition, once_member/2 is last-call/tail-recursive optimization eligible due to the placement of the cut ahead of its first self-invocation.

Resources