Why does these two prolog codes give back different result? - prolog

call((append(As,Bs,[1,2,3,4]),writeq(user,append(As,Bs,[1,2,3,4])))).
Result:
append([],[1,2,3,4],[1,2,3,4])
As = [],
Bs = [1,2,3,4] ? ;
append([1],[2,3,4],[1,2,3,4])
As = [1],
Bs = [2,3,4] ? ;
append([1,2],[3,4],[1,2,3,4])
As = [1,2],
Bs = [3,4] ? ;
append([1,2,3],[4],[1,2,3,4])
As = [1,2,3],
Bs = [4] ? ;
append([1,2,3,4],[],[1,2,3,4])
As = [1,2,3,4],
Bs = [] ? ;
no
But if I try this:
call((append(As,Bs,[1,2,3,4]) -> writeq(append(As,Bs,[1,2,3,4])) ; writeq('There are no solutions.\n'))).
It gives back this:
append([],[1,2,3,4],[1,2,3,4])
As = [],
Bs = [1,2,3,4] ? ;
no
What is the difference? I try to write it so that it can tell if there are 0 solutions.

Related

recursive Prolog predicate?

i am currently working on a project and i want to implement helper predicate in Prolog
break_down(N, L)
which works as follows
?- break_down(1,L).
L = [1] ;
false.
?- break_down(4,L).
L = [1, 1, 1, 1] ;
L = [1, 1, 2] ;
L = [1, 3] ;
L = [2, 2] ;
L = [4] ;
false.
and so on for any positive integer N .
i have tried and implemented a code which generates only the first result and i cannot get the rest of the results , and this is my code
break_down(1,[1]).
break_down(N,L):-
N>0,
N1 is N-1,
break_down(N1,L1),
append(L1,[1],L).
which generates only the first output result :
L = [1, 1, 1, 1] ;
any suggestion how to edit my code to get the rest ?
Here's a straight-forward recursive implementation using plain integer arithmetic and backtracking:
break_down(N,L) :-
break_ref_down(N,1,L). % reference item is initially 1
break_ref_down(0,_,[]).
break_ref_down(N,Z0,[Z|Zs]) :-
between(Z0,N,Z), % multiple choices
N0 is N-Z,
break_ref_down(N0,Z,Zs). % pass on current item as reference
Sample query:
?- break_down(8,Zs).
Zs = [1,1,1,1,1,1,1,1]
; Zs = [1,1,1,1,1,1,2]
; Zs = [1,1,1,1,1,3]
; Zs = [1,1,1,1,2,2]
; Zs = [1,1,1,1,4]
; Zs = [1,1,1,2,3]
; Zs = [1,1,1,5]
; Zs = [1,1,2,2,2]
; Zs = [1,1,2,4]
; Zs = [1,1,3,3]
; Zs = [1,1,6]
; Zs = [1,2,2,3]
; Zs = [1,2,5]
; Zs = [1,3,4]
; Zs = [1,7]
; Zs = [2,2,2,2]
; Zs = [2,2,4]
; Zs = [2,3,3]
; Zs = [2,6]
; Zs = [3,5]
; Zs = [4,4]
; Zs = [8]
; false.
Here's an implementation based on clpfd.
:- use_module(library(clpfd)).
As the predicate break_downFD/2 is non-recursive, the code is both readable and simple:
break_downFD(N,Zs) :-
length(Max,N), % multiple choices
append(_,Zs,Max),
Zs ins 1..N,
sum(Zs,#=,N),
chain(Zs,#=<), % enforce sequence is non-descending
labeling([],Zs). % multiple choices, possibly
Sample query using SWI-Prolog:
?- break_downFD(6,Zs).
Zs = [1,1,1,1,1,1]
; Zs = [1,1,1,1,2]
; Zs = [1,1,1,3]
; Zs = [1,1,2,2]
; Zs = [1,1,4]
; Zs = [1,2,3]
; Zs = [2,2,2]
; Zs = [1,5]
; Zs = [2,4]
; Zs = [3,3]
; Zs = [6]
; false.

Prolog. Fill out lists

I have to fill out a list of length n digits.
I know that n-1 is in the range from 1 to 9, and one digit can be in the range from 1 to 99.
I did it this way:
generate([First|Next],Czynniki):-
between(1,99,First),
generate2(Next).
generate2(Next):-
sublist([1,2,3,4,5,6,7,8,9],Next).
sublist([],[]).
sublist([H|T],[H|S]):-
sublist(T,S).
sublist([_|T],S):-
sublist(T,S).
Doing it this way I generate some of the same solutions.
Maybe you have some idea ​​how I can generate lists without repetition?
Edit
For the sake of clarity, I (#repeat) have added the following relevant comment by the OP:
At the entrance I have list of length N of undefined variables. And want fill out my list: N-1 numbers from the interval 1-9 and one number in the range 1-99.
Example: N=5, L=[56,2,3,4,8] ...
Use clpfd!
:- use_module(library(clpfd)).
Let's define digits10plusdigit100_n/2 like this:
digits10plusdigit100_n(Zs,N) :-
Zs = [CentDigit|DecDigits],
length(Zs,N),
CentDigit in 1..99,
DecDigits ins 1..9,
labeling([],Zs).
Sample queries:
?- digits10plusdigit100_n(Zs,1).
Zs = [1]
; Zs = [2]
; Zs = [3]
...
; Zs = [98]
; Zs = [99]
; false.
?- digits10plusdigit100_n(Zs,3).
Zs = [1,1,1]
; Zs = [1,1,2]
; Zs = [1,1,3]
...
; Zs = [1,2,1]
; Zs = [1,2,2]
...
; Zs = [1,9,8]
; Zs = [1,9,9]
; Zs = [2,1,1]
; Zs = [2,1,2]
...
; Zs = [2,1,3]
; Zs = [2,1,4]
...
; Zs = [98,9,9]
; Zs = [99,1,1]
; Zs = [99,1,2]
...
; Zs = [99,9,8]
; Zs = [99,9,9]
; false.
maybe change to between(10,99,X)
so reverse your predicates, generate numbers less then 10 and then generate last variable wich will be greater then 10
Isn't this just a variation of what #false very elegantly did in here ?
gen(Xs) :-
between(1, 9, L),
length(Xs, L),
maplist(between(1,99), Xs).
?- gen(Xs).
Xs = [1] ;
Xs = [2] ;
Xs = [3] ;
Xs = [4] ;
Xs = [5] ;
..
Xs = [99] ;
Xs = [1, 1] ;
Xs = [1, 2] ;
Xs = [1, 3] ;
Xs = [1, 4] ;
..
Xs = [1, 98] ;
Xs = [1, 99] ;
Xs = [2, 1] ;
Xs = [2, 2] ;
Xs = [2, 3] ;
Xs = [2, 4] ;
Xs = [2, 5] ;
Xs = [2, 6] ;

Get all sets of list in prolog

How can I generate all the possible sets of the elements of a list with current length?
?- get_set(X, [1,2,3]).
X = [1,1,1] ;
X = [1,1,2] ;
X = [1,1,3] ;
X = [1,2,1] ;
X = [1,2,2] ;
X = [1,2,3] ;
X = [1,3,1] ;
X = [1,3,2] ;
X = [1,3,3] ;
.....
X = [3,3,2] ;
X = [3,3,3].
UPD: there is good answer given by Sharky.
But maybe it's not the best. Here is another:
get_set(X,L) :- get_set(X,L,L).
get_set([],[],_).
get_set([X|Xs],[_|T],L) :- member(X,L), get_set(Xs,T,L).
Consider:
get_set(L0, L) :-
length(L, Len),
length(L0, Len),
apply_elem(L0, L).
apply_elem([], _).
apply_elem([X|Xs], L) :-
member(X, L),
apply_elem(Xs, L).
Explanation:
Determining the length of the input list L as Len allows us to generate a list of unique variables, L0, via length/2. Then, we simply apply elements of L to all members of L0 via member/2, which leaves choicepoints for options, should they exist (i.e., if the list L is of length > 1). Prolog will backtrack to generate all possible combinations of elements of L into the list L0, as required.
Based on library predicate same_length/2, we can make it work safely in "both" directions!
Simply define get_set/2 like this, using meta-predicate maplist/2:
get_set(Xs,Ys) :-
same_length(Xs,Ys),
maplist(list_member(Ys),Xs).
list_member(Xs,X) :-
member(X,Xs).
First, the sample query suggested by the OP:
?- get_set(Xs,[1,2,3]).
Xs = [1,1,1] ;
Xs = [1,1,2] ;
Xs = [1,1,3] ;
Xs = [1,2,1] ;
Xs = [1,2,2] ;
Xs = [1,2,3] ;
Xs = [1,3,1] ;
Xs = [1,3,2] ;
Xs = [1,3,3] ;
Xs = [2,1,1] ;
Xs = [2,1,2] ;
Xs = [2,1,3] ;
Xs = [2,2,1] ;
Xs = [2,2,2] ;
Xs = [2,2,3] ;
Xs = [2,3,1] ;
Xs = [2,3,2] ;
Xs = [2,3,3] ;
Xs = [3,1,1] ;
Xs = [3,1,2] ;
Xs = [3,1,3] ;
Xs = [3,2,1] ;
Xs = [3,2,2] ;
Xs = [3,2,3] ;
Xs = [3,3,1] ;
Xs = [3,3,2] ;
Xs = [3,3,3] ;
false. % terminates universally
Let's try the other way round!
?- get_set([1,2,3],Ys).
Ys = [1,2,3] ;
Ys = [1,3,2] ;
Ys = [2,1,3] ;
Ys = [3,1,2] ;
Ys = [2,3,1] ;
Ys = [3,2,1] ;
false. % terminates universally

Permuted combinations of the elements of a list - Prolog

How can I generate all the possible combinations of the elements of a list?
For example, given the list [1,2,3], I want to design a predicate with the form comb([1,2,3], L). which should return the following answer for L:
[1]
[2]
[3]
[1,2]
[2,1]
[1,3]
[3,1]
[2,3]
[3,2]
[1,2,3]
[1,3,2]
[2,1,3]
[2,3,1]
[3,1,2]
[3,2,1]
What you are asking for involves both combinations (selecting a subset) and permutations (rearranging the order) of a list.
Your example output implies that the empty list is not considered a valid solution, so we will exclude it in the implementation that follows. Reconsider if this was an oversight. Also this implementation produces the solutions in a different order than your example output.
comb(InList,Out) :-
splitSet(InList,_,SubList),
SubList = [_|_], /* disallow empty list */
permute(SubList,Out).
splitSet([ ],[ ],[ ]).
splitSet([H|T],[H|L],R) :-
splitSet(T,L,R).
splitSet([H|T],L,[H|R]) :-
splitSet(T,L,R).
permute([ ],[ ]) :- !.
permute(L,[X|R]) :-
omit(X,L,M),
permute(M,R).
omit(H,[H|T],T).
omit(X,[H|L],[H|R]) :-
omit(X,L,R).
Tested with Amzi! Prolog:
?- comb([1,2,3],L).
L = [3] ;
L = [2] ;
L = [2, 3] ;
L = [3, 2] ;
L = [1] ;
L = [1, 3] ;
L = [3, 1] ;
L = [1, 2] ;
L = [2, 1] ;
L = [1, 2, 3] ;
L = [1, 3, 2] ;
L = [2, 1, 3] ;
L = [2, 3, 1] ;
L = [3, 1, 2] ;
L = [3, 2, 1] ;
no
Stay pure by defining comb/2 based on same_length/2, prefix/2, foldl/4 and
select/3:
comb(As,Bs) :-
same_length(As,Full),
Bs = [_|_],
prefix(Bs,Full),
foldl(select,Bs,As,_).
Here's the sample query given by the OP:
?- comb([1,2,3],Xs).
Xs = [1]
; Xs = [2]
; Xs = [3]
; Xs = [1,2]
; Xs = [1,3]
; Xs = [2,1]
; Xs = [2,3]
; Xs = [3,1]
; Xs = [3,2]
; Xs = [1,2,3]
; Xs = [1,3,2]
; Xs = [2,1,3]
; Xs = [2,3,1]
; Xs = [3,1,2]
; Xs = [3,2,1]
; false.
Ok! But what if the list given as the first argument contains duplicates?
?- comb([1,1,2],Xs).
Xs = [1]
; Xs = [1] % (redundant)
; Xs = [2]
; Xs = [1,1]
; Xs = [1,2]
; Xs = [1,1] % (redundant)
; Xs = [1,2] % (redundant)
; Xs = [2,1]
; Xs = [2,1] % (redundant)
; Xs = [1,1,2]
; Xs = [1,2,1]
; Xs = [1,1,2] % (redundant)
; Xs = [1,2,1] % (redundant)
; Xs = [2,1,1]
; Xs = [2,1,1] % (redundant)
; false.
Not quite! Can we get rid of above redundant answers? Yes, simply use selectd/3!
comb(As,Bs) :-
same_length(As,Full),
Bs = [_|_],
prefix(Bs,Full),
foldl(selectd,Bs,As,_).
So let's re-run above query again with the improved implementation of comb/2!
?- comb([1,1,2],Xs).
Xs = [1]
; Xs = [2]
; Xs = [1,1]
; Xs = [1,2]
; Xs = [2,1]
; Xs = [1,1,2]
; Xs = [1,2,1]
; Xs = [2,1,1]
; false.
there is a predefined predicate called permutation ...
1 ?- permutation([1,2,3],L).
L = [1, 2, 3] ;
L = [2, 1, 3] ;
L = [2, 3, 1] ;
L = [1, 3, 2] ;
L = [3, 1, 2] ;
L = [3, 2, 1] .
2 ?- listing(permutation).
lists:permutation([], [], []).
lists:permutation([C|A], D, [_|B]) :-
permutation(A, E, B),
select(C, D, E).
lists:permutation(A, B) :-
permutation(A, B, B).
true.
hope this helps ..
Hint: This is easy to do if you have written a predicate inselt(X,Y,Z), which holds if any insertion of Y into X gives Z:
inselt([E|X], Y, [E|Z]) :- inselt(X,Y,Z).
inselt(X, Y, [Y|X]).
Then comb/3 can be coded recursively using inselt/3.

Prolog Arguments are not sufficiently instantiated

I'm trying to match a subset of the facts I'm creating, and my testcase was working great!
x([1,2,3,4],'bleah').
x([1,2,4],'bleah2').
x([1,2],'bleah8').
x([1,3,4],'bleah3').
x([5,6,7,8],'bleah5').
x([6,7,8,9],'bleah6').
fuzzy(X,R) :- x(Z, R), subset(X,Z) .
remaining(X,Y,D,M) :- x(Z,D) , select(X,Z,N), select(Y,N,M).
pair(X,Y,R) :- x([X,Y],R) ; x([Y,X],R).
Output:
?- x([1,2|REST],D).
REST = [3, 4],
D = bleah ;
REST = [4],
D = bleah2 ;
REST = [],
D = bleah8 ;
false.
?- pair(2,1,D).
D = bleah8 ;
false.
?- fuzzy([2,1],R).
R = bleah ;
R = bleah2 ;
R = bleah8 ;
false.
?- remaining(2,1,D,M).
D = bleah,
M = [3, 4] ;
D = bleah2,
M = [4] ;
D = bleah8,
M = [] ;
false.
Then I added a fact to represent my next potential case, and now it's quite broken. I'm new to Prolog, I'm not sure why this is or how to fix it.
x([6,X,8,9],'woot') :- (X+0) > 7.
Output:
?- x([1,2|REST],D).
REST = [3, 4],
D = bleah ;
REST = [4],
D = bleah2 ;
REST = [],
D = bleah8 ;
false.
?- pair(2,1,D).
D = bleah8 ;
false.
?- fuzzy([2,1],R).
R = bleah ;
R = bleah2 ;
R = bleah8 ;
ERROR: >/2: Arguments are not sufficiently instantiated
^ Exception: (9) _G260+0>7 ? abort
% Execution Aborted
?- remaining(2,1,D,M).
D = bleah,
M = [3, 4] ;
D = bleah2,
M = [4] ;
D = bleah8,
M = [] ;
ERROR: >/2: Arguments are not sufficiently instantiated
^ Exception: (10) _G270+0>7 ? abort
% Execution Aborted
?- x([_,15,_,_],D).
D = woot.
Suggestions welcome.
Can X only be a natural number? If yes, then you can change your rule
x([6,X,8,9], 'woot') :- (X+0) > 7.
to
x([6, X, 8, 9], 'woot') :- between(8, inf, X).
This works at least in SWI-Prolog:
?- x(A, B).
A = [6, 8, 8, 9],
B = woot ;
A = [6, 9, 8, 9],
B = woot ;
A = [6, 10, 8, 9],
B = woot ;
...
In fuzzy/2 and remaining/4, you are calling x/2 with an uninstantiated Z. This means that the Left Hand Side of + (and therefore >) is uninstantiated.
Ok, changing to a finite datatype helped!
% Basic comparisons
same(X,Y) :- X == Y.
greaterThan(X,Y) :- lessThan(Y,X).
lessThan(X,Y) :- is_lessThan(X,Y).
lessThan(X,Y) :- is_lessThan(X,Z) , lessThan(Z,Y).
% Enumerate a list
is_lessThan( 'a', 'b' ).
is_lessThan( 'b', 'c' ).
is_lessThan( 'c', 'd' ).
is_lessThan( 'd', 'e' ).
is_lessThan( 'e', 'f' ).
is_lessThan( 'f', 'g' ).
is_lessThan( 'g', 'h' ).
is_lessThan( 'h', 'i' ).
% "Static" facts of variable length
x(['a','b','c','d'],'abcd').
x(['a','b','d'],'abd').
x(['a','b'],'ab').
x(['a','c','d'],'acd').
x(['e','f','g','h'],'efgh').
x(['f','g','h','i'],'fghi').
% "Dynamic" facts of variable length and constraint
x(['f',X,'h','i'],'fXhi') :- greaterThan('g',X).
x(['f',X,Y],'fXY') :- greaterThan('g',X), lessThan(Y,'i').
% specify the two list items separately in X & Y
fuzzyMatch(X,Y,R) :- x([X,Y],R) ; x([Y,X],R) .
% specify the list X
fuzzyMatch(X,R) :- x(Z, R), subset(X,Z) .
% specify two list items separately, returning the remaining terms that didn't match
fuzzyMatch(X,Y,D,M) :- x(Z,D) , select(X,Z,N), select(Y,N,M).
Output:
?- fuzzyMatch('b','a',D).
D = ab ;
false.
?- fuzzyMatch(['b','a'],D).
D = abcd ;
D = abd ;
D = ab ;
D = fXY ;
D = fXY ;
false.
?- fuzzyMatch('b','a',R,D).
R = abcd,
D = [c, d] ;
R = abd,
D = [d] ;
R = ab,
D = [] ;
R = fXY,
D = [f] ;
R = fXY,
D = [f] ;
false.

Resources