What problem can occur when we use append with cut operator?
append2([],L,L):-!.
append2([H|T],L,[H|TL]):-append2(T,L,TL).
I have tried several different inputs, but it always succeeds.
?- append2([1,2],[5],L).
L = [1, 2, 5].
?- append2([1,2],[1,2],L).
L = [1, 2, 1, 2].
?- append2([],[1,2],L).
L = [1, 2].
?- append2([1,2],[],L).
L = [1, 2].
It sometimes really makes sense to introduce green cuts — even into append/3, but care must be taken that such a cut remains a green cut. That is, a cut that does improve efficiency (on a certain level) and does not affect answers.
There is a very simple rule-of-thumb for introducing green cuts: If you add a cut into a pure, monotonic program without any guard, you can be pretty sure that it will be a red cut which destructs the meaning of your program.
There are very few exceptions to this rule-of-thumb. For example, you may add a cut after a variable free goal, provided there is no further rule etc. It is definitely a good training to try to figure out cases that are affected by a cut.
But back to your program append2/3. Currently, the cut always cuts, even if the alternate rule does apply, in which case the cut removes answers which is what we want to avoid.
So when will the first clause be the only one of relevance?
If the first argument is [], thus append2([], Xs, Ys). - but also if the last argument is [] (there are even more cases which are more complex). Lets try both cases with the original cut-free definition:
?- append([], Ys, Zs).
Ys = Zs.
?- append(Xs, Ys, []).
Xs = Ys, Ys = []
; false.
So in the first case, the system was able to determine that there is a single solution immediately, while producing the answer. In the second case, however, the Prolog system was not sure whether or not another answer will be necessary — it "left a choicepoint open" so to speak. This is a pity, since it is fairly trivial to determine that also in this case, only a single answer exists. A cut would have been ideal here to help. But an unguarded cut does more harm than it helps.
The cut may cut, provided the third argument is a []:
append3(Xs, Ys, Zs) :-
( Zs == [] -> ! ; true ),
Xs = [],
Ys = Zs.
append3([X|Xs], Ys, [X|Zs]) :-
append3(Xs, Ys, Zs).
This program is now more efficient in the sense that it does not leave a choicepoint open, if only the 3rd argument is known.
?- append(Xs,Ys,[1]).
Xs = [], Ys = [1]
; Xs = [1], Ys = []
; false.
?- append3(Xs,Ys,[1]).
Xs = [], Ys = [1]
; Xs = [1], Ys = [].
The program is not necessarily faster, since the test itself might be expensive. Ideally, a Prolog system would be able to do such things internally, but sometimes the programmer has to help a bit.
There are two kinds of cuts; green cuts and red cuts. Green cuts are inserted just to improve efficiency and don't change the semantics of the program. Red cuts, on the other hand, do. By definition, green cuts do not cause any problems.
So, is there any way that the behaviour would change if the cut wasn't there?
Lets see; for the first clause to match, L1 should be unifiable with [], L2 with L and L3 with L or, in other words, L2 unifiable with L3.
When L1 is [] the second clause cannot match; so the cut doesn't have any effect
When L1 is not instantiated:
if the length of L2 and L3 are known at this point, then they must be equal otherwise the first clause wouldn't match; thus, the second clause cannot match since at each step the length of L3 is decreased by 1 and the only way to terminate requires L2=L3
if the length of L3 or L2 is not known:
then we have a problem since the second clause may produce solutions.
Indeed:
3 ?- append2(L1,L2,[1,2,3]).
L1 = [],
L2 = [1, 2, 3].
4 ?- append2(L1,[1,2,3],L3).
L1 = [],
L3 = [1, 2, 3].
5 ?- append2(L1,L2,L3).
L1 = [],
L2 = L3.
6 ?- append2(L1,[E1,E2],L3).
L1 = [],
L2 = [E1, E2].
7 ?- append2(L1,L2,[E1,E2]).
L1 = [],
L2 = [E1, E2].
while we expect:
8 ?- append(L1,L2,[1,2,3]).
L1 = [],
L2 = [1, 2, 3] ;
L1 = [1],
L2 = [2, 3] ;
L1 = [1, 2],
L2 = [3] ;
L1 = [1, 2, 3],
L2 = [] ;
false.
9 ?- append(L1,[1,2,3],L3).
L1 = [],
L3 = [1, 2, 3] ;
L1 = [_G24],
L3 = [_G24, 1, 2, 3] ;
L1 = [_G24, _G30],
L3 = [_G24, _G30, 1, 2, 3] ;
L1 = [_G24, _G30, _G36],
L3 = [_G24, _G30, _G36, 1, 2, 3] ;
L1 = [_G24, _G30, _G36, _G42],
L3 = [_G24, _G30, _G36, _G42, 1, 2, 3] ;
...
10 ?- append(L1,L2,L3).
L1 = [],
L2 = L3 ;
L1 = [_G22],
L3 = [_G22|L2] ;
L1 = [_G22, _G28],
L3 = [_G22, _G28|L2] ;
....
11 ?- append(L1,[E1,E2],L3).
L1 = [],
L3 = [E1, E2] ;
L1 = [_G78],
L3 = [_G78, E1, E2] ;
L1 = [_G78, _G84],
L3 = [_G78, _G84, E1, E2] ;
L1 = [_G78, _G84, _G90],
L3 = [_G78, _G84, _G90, E1, E2] ;
...
12 ?- append(L1,L2,[E1,E2]).
L1 = [],
L2 = [E1, E2] ;
L1 = [E1],
L2 = [E2] ;
L1 = [E1, E2],
L2 = [] ;
false.
Try for example the most general query:
?- append2(X, Y, Z).
It won't work when the first two arguments are variable:
?- append(X, Y, [1, 2, 3]).
X = [],
Y = [1, 2, 3] ;
X = [1],
Y = [2, 3] ;
X = [1, 2],
Y = [3] ;
X = [1, 2, 3],
Y = [] ;
false.
?- append2(X, Y, [1, 2, 3]).
X = [],
Y = [1, 2, 3].
Related
I have a written a functional function that tells the user if a list is ordered or not, given the list inputted. However, if a user inputs a variable as the input instead of a list, I would like to output an infinite list. How can I go about this? Here is the current code
ordered([]).
ordered([_]).
ordered([X,Y|Ys]) :- X =< Y , ordered( [Y|Ys] ).
Here is some input
? ordered([1,2,3]).
true
? ordered([1,5,2]).
false
I also want for variables to creat infinite list like so
? ordered(L).
L = [];
L = [_1322] ;
L = [_1322, _1323] ;
L = [_1322, _1323, _1324] ;
L = [_1322, _1323, _1324, _1325].
The list should increase until the user exits as shown.
The list should increase until the user exits as shown.
Solution:
ordered([]).
ordered([_]).
ordered([X,Y|Ys]) :- X #=< Y , ordered( [Y|Ys] ).
EDIT:
SWI Prolog doc
The arithmetic expression X is less than or equal to Y. When reasoning over integers, replace (=<)/2 by #=</2 to obtain more general relations. See declarative integer arithmetic (section A.9.3).
What properties should the list of variables have? The currently accepted answer by Anton Danilov says that [3, 2, 1] is not an ordered list:
?- List = [A, B, C], List = [3, 2, 1], ordered(List).
false.
but it also says that [3, 2, 1] is an instance of an ordered list:
?- List = [A, B, C], ordered(List), List = [3, 2, 1].
List = [3, 2, 1],
A = 3,
B = 2,
C = 1 ;
false.
Viewed logically, this is a contradiction. Viewed procedurally, it is fine, but also the #=< relationship between the variables in the list is meaningless. The comparison of the unbound variables does not say anything about the relationship of the list elements if they are bound to values at some point.
You can use constraints to exclude future unordered bindings:
:- use_module(library(clpfd)).
ordered([]).
ordered([_]).
ordered([X, Y | Xs]) :-
X #=< Y,
ordered([Y | Xs]).
This way you cannot bind the variables in the list to incorrect numbers later on:
?- List = [A, B, C], List = [3, 2, 1], ordered(List).
false.
?- List = [A, B, C], ordered(List), List = [3, 2, 1].
false.
But later correct ordered bindings are still allowed:
?- List = [A, B, C], ordered(List), List = [1, 2, 3].
List = [1, 2, 3],
A = 1,
B = 2,
C = 3 ;
false.
This may not be the best solution, but I believe it can give you some idea of how to do what you need. In SWI-Prolog, the predicate freeze(+Var,:Goal) delays the execution of Goal until Var is bound.
ordered([]).
ordered([_]).
ordered([X,Y|R]) :-
freeze( X,
freeze( Y,
( X #=< Y,
ordered([Y|R]) ) ) ).
Here are some examples with finite lists:
?- ordered([1,2,3]).
true.
?- ordered([1,2,3,0]).
false.
?- ordered(L), L=[1,2,3].
L = [1, 2, 3] ;
false.
?- ordered(L), L=[1,2,3,0].
false.
For an infinite list, you will need to "take" its prefix:
take([]).
take([_|R]) :- take(R).
Here is an example with infinite list:
?- ordered(L), take(L).
L = [] ;
L = [_375396] ;
L = [_376366, _376372],
freeze(_376366, freeze(_376372, (_376366#=<_376372, ordered([])))) ;
L = [_377472, _377478, _377484],
freeze(_377472, freeze(_377478, (_377472#=<_377478, ordered([_377484])))) ;
L = [_378590, _378596, _378602, _378608],
freeze(_378590, freeze(_378596, (_378590#=<_378596, ordered([_378602, _378608])))) ;
L = [_379720, _379726, _379732, _379738, _379744],
freeze(_379720, freeze(_379726, (_379720#=<_379726, ordered([_379732, _379738, _379744]))))
Examples: ([1,2,3,7,6,9], 6). should print True, as 1+2+3=6.
([1,2,3,7,6,9], 5). should print False as there are no three numbers whose sum is 5.
([],N) where N is equal to anything should be false.
Need to use only these constructs:
A single clause must be defined (no more than one clause is allowed).
Only the following is permitted:
+, ,, ;, ., !, :-, is, Lists -- Head and Tail syntax for list types, Variables.
I have done a basic coding as per my understanding.
findVal([Q|X],A) :-
[W|X1]=X,
[Y|X2]=X,
% Trying to append the values.
append([Q],X1,X2),
% finding sum.
RES is Q+W+Y,
% verify here.
(not(RES=A)->
% finding the values.
(findVal(X2,A=)->
true
;
(findVal(X,A)->
% return result.
true
;
% return value.
false))
;
% return result.
true
).
It does not seem to run throwing the following error.
ERROR:
Undefined procedure: findVal/2 (DWIM could not correct goal)
Can someone help with this?
You can make use of append/3 [swi-doc] here to pick an element from a list, and get access to the rest of the elements (the elements after that element). By applying this technique three times, we thus obtain three items from the list. We can then match the sum of these elements:
sublist(L1, S) :-
append(_, [S1|L2], L1),
append(_, [S2|L3], L2),
append(_, [S3|_], L3),
S is S1 + S2 + S3.
Well, you can iterate (via backtracking) over all the sublists of 3 elements from the input list and see which ones sum 3:
sublist([], []).
sublist([H|T], [H|S]) :- sublist(T, S).
sublist([_|T], S) :- sublist(T, S).
:- length(L, 3), sublist([1,2,3,7,6,9], L), sum_list(L, 6).
I'm giving a partial solution here because it is an interesting problem even though the constraints are ridiculous.
First, I want something like select/3, except that will give me the tail of the list rather than the list without the item:
select_from(X, [X|R], R).
select_from(X, [_|T], R) :- select_from(X, T, R).
I want the tail, rather than just member/2, so I can recursively ask for items from the list without getting duplicates.
?- select_from(X, [1,2,3,4,5], R).
X = 1,
R = [2, 3, 4, 5] ;
X = 2,
R = [3, 4, 5] ;
X = 3,
R = [4, 5] ;
X = 4,
R = [5] ;
X = 5,
R = [] ;
false.
Yeah, this is good. Now I want to build a thing to give me N elements from a list. Again, I want combinations, because I don't want unnecessary duplicates if I can avoid it:
select_n_from(1, L, [X]) :- select_from(X, L, _).
select_n_from(N, L, [X|R]) :-
N > 1,
succ(N0, N),
select_from(X, L, Next),
select_n_from(N0, Next, R).
So the idea here is simple. If N = 1, then just do select_from/3 and give me a singleton list. If N > 1, then get one item using select_from/3 and then recur with N-1. This should give me all the possible combinations of items from this list, without giving me a bunch of repetitions I don't care about because addition is commutative and associative:
?- select_n_from(3, [1,2,3,4,5], R).
R = [1, 2, 3] ;
R = [1, 2, 4] ;
R = [1, 2, 5] ;
R = [1, 3, 4] ;
R = [1, 3, 5] ;
R = [1, 4, 5] ;
R = [2, 3, 4] ;
R = [2, 3, 5] ;
R = [2, 4, 5] ;
R = [3, 4, 5] ;
false.
We're basically one step away now from the result, which is this:
sublist(List, N) :-
select_n_from(3, List, R),
sumlist(R, N).
I'm hardcoding 3 here because of your problem, but I wanted a general solution. Using it:
?- sublist([1,2,3,4,5], N).
N = 6 ;
N = 7 ;
N = 8 ;
N = 8 ;
N = 9 ;
N = 10 ;
N = 9 ;
N = 10 ;
N = 11 ;
N = 12 ;
false.
You can also check:
?- sublist([1,2,3,4,5], 6).
true ;
false.
?- sublist([1,2,3,4,5], 5).
false.
?- sublist([1,2,3,4,5], 8).
true ;
true ;
false.
New users of Prolog will be annoyed that you get multiple answers here, but knowing that there are multiple ways to get 8 is probably interesting.
I want to write a predicate split/2 that generates all consecutive lists found inside another list.
Example: split([1,2,3,4],X) should return
X = [4], X = [2,3],X = [1,2], X = [1,2,3] etc.
So far I only have a predicate that returns all possible sublists of a list:
sublist([],[]).
sublist([H|T], [H|R]) :-
sublist(T,R).
sublist([_|T], R) :-
sublist(T,R).
However, with the query from the example this predicate includes unwanted answers like X = [2,4] and X = [1,3] that aren't found consecutively in [1,2,3,4].
Usually a problem is easier if you split it in subproblems. We can first construct a predicate that will construct all suffixes for a given list.
We can construct such predicate as follows:
suffix(_, []).
suffix([H|T], [H|T2]) :-
suffix(T, T2).
So for each point in the list, we can decide to stop (with the empty list), or emit the next item. For the given sample list, we thus get:
?- suffix([1,2,3,4],X).
X = [] ;
X = [1] ;
X = [1, 2] ;
X = [1, 2, 3] ;
X = [1, 2, 3, 4].
Now we only need to decide when we start the suffix. For each item in the list, we can decide to start at that point, and enumerate over all suffixes that we then append to that item:
split([H|T], [H|S]) :-
suffix(T, S).
split([_|T], S) :-
split(T, S).
For example:
?- split([1,2,3,4],X).
X = [1] ;
X = [1, 2] ;
X = [1, 2, 3] ;
X = [1, 2, 3, 4] ;
X = [2] ;
X = [2, 3] ;
X = [2, 3, 4] ;
X = [3] ;
X = [3, 4] ;
X = [4] ;
false.
The nice thing is that we got a second predicate "for free": we can also obtain all suffixes for a list.
We might want to include the empty list as well. I leave this as an exercise.
I have a problem. I want to implement a replace(E1, L1, E2, L2) predicate.
This holds when L1 and L2 are the same lists,except that in one place where L1 has the value E1, L2 has E2. In addition, only one occurrence is replaced and it must work in any mode.
For example:
replace(2,[1,2,3,4],5,X) should have only the solution X = [1,5,3,4].
replace(2,[1,2,3,2,1],5,X) should backtrack over the solutions X =
[1,5,3,2,1] and X = [1,2,3,5,1].
replace(2,X,5,[1,5,3,5,1]) should backtrack over the solutions X =
[1,2,3,5,1] and X = [1,5,3,2,1].
replace(X,[a,b,c,d],Y,[a,e,c,d]) should have only the solution X = b,
Y = e.
replace(X,[1,2,3,2,1],Y,[1,5,3,5,1]) should have no solutions (it
should fail).
My implementation:
replace(E1, L1, E2, L2) :-
append(X, [E1|L_Tail], L1),
append(X, [E2|L_Tail], L2).
This code is fine. However when replace(2,X,5,[1,5,3,5,1]), it should return X = [1,2,3,5,1] and X = [1,5,3,2,1] and false. It only return the first 2 results, and the false didn't came up. The program end up with ERROR: Out of global stack.
This question has been asked and it has two answers: the one you used and a better one. However, I will answer the question "why does this solution not work and how to fix it?".
When the third argument to append/3 is a variable or a partial list, it gives infinitely many solutions:
?- append(X, Y, [a|Z]).
X = [],
Y = [a|Z] ;
X = [a],
Y = Z ;
X = [a, _1860],
Z = [_1860|Y] ;
X = [a, _1860, _1872],
Z = [_1860, _1872|Y] ;
X = [a, _1860, _1872, _1884],
Z = [_1860, _1872, _1884|Y] . % and so on
So, when the first list L1 is a partial list, the call to append(X, [E1|Y], L1) will keep "hallucinating" longer and longer lists. The second call to append/3 will fail every time, Prolog will backtrack, make an even longer list with the first append/3, and so on. This is why you are caught in an infinite loop and will eventually run out of memory (when the lists get too long).
One cheap way to avoid this is to make sure that both lists are proper lists of the same length before giving them to the two appends. For example:
same_length([], []).
same_length([_|A], [_|B]) :- same_length(A, B).
If you are using SWI-Prolog you could do this with maplist and a yall lambda:
maplist([_,_]>>true, L1, L2)
The example query:
?- L2 = [1,5,3,5,1],
maplist([_,_]>>true, L1, L2),
append(X, [2|Y], L1),
append(X, [5|Y], L2).
L2 = [1, 5, 3, 5, 1],
L1 = [1, 2, 3, 5, 1],
X = [1],
Y = [3, 5, 1] ;
L2 = [1, 5, 3, 5, 1],
L1 = [1, 5, 3, 2, 1],
X = [1, 5, 3],
Y = [1] ;
false.
I'm having trouble trying to debug this code of mine to find the intersection between two lists...
For Example:
List1 = [3, 4, 5, 6] and
List2 = [5, 1, 0, 2, 4].
So, the intersecting lines would be stored into List3 would be [4, 5].
So here's the code for Prolog.
Any help would be appreciated!!!
setIntersection([], [], []).
setIntersection([], _, []).
setIntersection([X|Xs], Y, [Z|W]) :-
keepDuplicates(X, Y, [Z|Zs]),
setIntersection(Xs, Y, W).
keepDuplicates(_, [], []).
keepDuplicates([], _, []).
keepDuplicates([], [], []).
% Check if the head of the first list is not a match to the
% first head of the second list
keepDuplicates(G, [H|Hs], Line) :-
G \= H,
keepDuplicates(G, Hs, Line).
% Check if the head of the first list
% Does match to the head of the second list
keepDuplicates(G, [G|Gs], [G|NewLine]) :-
keepDuplicates(G, Gs, NewLine).
You can find a couple of logically pure, monotone implementations of list intersection and union in my answer to the related question "Intersection and union of 2 lists".
Let's see a sample query:
?- list_list_intersection([3,4,5,6],[5,1,0,2,4],Intersection).
Intersection = [4,5]. % succeeds deterministically
As the proposed implementation is monotone, you can also use it in more general ways and still get logically sound answers:
?- L2 = [_,_,_], list_list_intersection([3,4,5,6],L2,[4,5]).
L2 = [ 4, 5,_A], dif(_A,6), dif(_A,3) ;
L2 = [ 4,_A, 5], dif(_A,6), dif(_A,5), dif(_A,3) ;
L2 = [ 5, 4,_A], dif(_A,6), dif(_A,3) ;
L2 = [_A, 4, 5], dif(_A,6), dif(_A,5), dif(_A,4),dif(_A,3) ;
L2 = [ 5,_A, 4], dif(_A,6), dif(_A,4), dif(_A,3) ;
L2 = [_A, 5, 4], dif(_A,6), dif(_A,5), dif(_A,4),dif(_A,3) ;
false.
Usually sets in Prolog are represented with sorted lists, then avoiding the ambiguity of the representation that arises in presence of duplicate elements. Let's ignore this problem...
This fact setIntersection([], [], []). is subsumed by setIntersection([], _, [])., then can (should!) be deleted.
The same for keepDuplicates([], [], []). (why do you invert clauses order here ?)
You have a singleton Zs: ...,keepDuplicates(X, Y, [Z|Zs]),... and you should pay attention to that warning (of course, if your compiler display it), since it's often symptom of a true mistake.
Also, that predicate cannot cover all the cases: when X is not in Y, what do you associate to Z ?
To be true, I think you're doing it more complicated than required. Ignoring duplicates, the whole could be easy as
?- L1=[3,4,5,6],L2=[5,1,0,2,4],findall(C, (member(C,L1),memberchk(C,L2)), I).