Prolog Skip some backtracking branches - prolog

I'm trying to generate some Kakuros, generate not solve.
I have all rules to generate it, but the firsts results are senseless, those are like squares.
Now I want to skip some branches, 15000 for example, to see the kakuro generated at that point.
I have tried with an Auxiliary Variable, but when it fails, the Kakuro Generator start again.

You can keep a dynamic counter-like predicate in the knowledge base that gets increased every time the main predicate is executed. The value of the counter is changed with assert and retract, i.e., it is not a variable within your main predicate but a globally stored value.
Within your main predicate, if you add the condition that the counter should be higher than some skip value, then you force backtracking over the actual rules for a specified number of iterations.
As an example, consider the built-in predicate permutation/2 which computes permutations of a list (note: tested using SWI-Prolog, other interpreters have different built-in predicates). Example output:
?- permutation([1,2,3,4,5],L).
L = [1, 2, 3, 4, 5] ;
L = [1, 2, 3, 5, 4] ;
L = [1, 2, 4, 3, 5] ;
L = [1, 2, 4, 5, 3] ;
L = [1, 2, 5, 3, 4] ;
L = [1, 2, 5, 4, 3] ;
If you want to skip the first 5 iterations in your query, you can use the following code:
:- dynamic iteration_nr/1.
iteration_nr(0).
get_permutations(L1,L2,Skip) :-
permutation(L1,L2),
iteration_nr(N),
N2 is N+1,
retract(iteration_nr(N)),
asserta(iteration_nr(N2)),
Skip < N2. % force backtracking here if counter < Skip
Example output:
?- get_permutations([1,2,3,4,5],L2,5).
L2 = [1, 2, 5, 4, 3] ;
L2 = [1, 3, 2, 4, 5] ;
L2 = [1, 3, 2, 5, 4]
Note that asserta is used here (i.e., assert at the start) instead of plain assert, which is deprecated. Note also that the counter will keep the value, so when you run this a second time in the same session the results will be different. To reset the counter you can use a separate initialization predicate, for example:
init_and_get_permutations(L1,L2,Skip) :-
retractall(iteration_nr(_)),
asserta(iteration_nr(0)),
get_permutations(L1,L2,Skip).
Further note: the use of assert and retract is not really considered 'clean' Prolog programming, because it is procedural and changes the knowledge base. However, for some applications it can be useful.

Related

Printing minimum answer as list?

I have a predicate min1([4,2,3,5],L). I want it to return the minimum number for each time the list is sent back as a tail. Example:
List Head|Tail Tail L
[4,2,3,5] [4,2,3,5] [2,3,5] 2
[2,3,5] [2,3,5] [3,5] 2
[3,5] [3,5] [5] 3
[5] [5] [] 5
My code:
min([X],[X]).
min([H|T],Min):-
min(T,TMin),
H=<TMin,
Min is H.
min([H|T],Min):-
min(T,TMin),
H>TMin,
Min is TMin.
min1([],[]).
min1([H|T],L):-
min([H|T],R),
write(R),
min1(T,R).
The problem that I am facing is with L. It does not print anything. When I use write(R), it's showing me the right result but I am unable to print it as a List in L. What should I correct?
?-min1([4,2,3,5],L).
223[5]
L = []
By removing write(R):
?-min1([4,2,3,5],L).
false
One of your problems is trying to understand your program using I/O. This is often not a very useful thing to do in Prolog. If you are interested in the suffixes of the list, even just for debugging, expose those suffixes as an argument of the predicate. This is much clearer than trying to print intermediate results. Because Prolog backtracks, it can be hard to understand what an intermediate result means, at what point it exists, and whether you can actually use it before backtracking makes it disappear.
Your other problem is trying to do too much at once. Take things step by step. Prolog is a language that is well suited for decomposing problems into tiny bits. It also often forces you to decompose a problem into tiny bits.
So, first: Enumerating a list's suffixes (including the list itself as a trivial suffix).
list_suffix(List, List).
list_suffix([_ | Suffix], SuffixOfSuffix) :-
list_suffix(Suffix, SuffixOfSuffix).
?- list_suffix([4, 2, 3, 5], Suffix).
Suffix = [4, 2, 3, 5] ;
Suffix = [2, 3, 5] ;
Suffix = [3, 5] ;
Suffix = [5] ;
Suffix = [].
Then, separately, computing the minimum of a list. Your implementation is almost OK for this, the first clause needed to unwrap [X] (though it could be more efficient by using an accumulator):
list_minimum([X], X).
list_minimum([H | T], Min):-
list_minimum(T, TMin),
H =< TMin,
Min is H.
list_minimum([H | T], Min):-
list_minimum(T, TMin),
H > TMin,
Min is TMin.
?- list_minimum([4, 2, 3, 5], Minimum).
Minimum = 2 ;
false.
Now, and only now, we are in a position to tackle the combined problem:
?- list_suffix([4, 2, 3, 5], Suffix), list_minimum(Suffix, Minimum).
Suffix = [4, 2, 3, 5],
Minimum = 2 ;
Suffix = [2, 3, 5],
Minimum = 2 ;
Suffix = [3, 5],
Minimum = 3 ;
Suffix = [5],
Minimum = 5 ;
false.
You can pack this up in a predicate definition:
list_suffix_suffixminimum(List, Suffix, SuffixMinimum) :-
list_suffix(List, Suffix),
list_minimum(Suffix, SuffixMinimum).
?- list_suffix_suffixminimum([4, 2, 3, 5], Suffix, SuffixMinimum).
Suffix = [4, 2, 3, 5],
SuffixMinimum = 2 ;
Suffix = [2, 3, 5],
SuffixMinimum = 2 ;
Suffix = [3, 5],
SuffixMinimum = 3 ;
Suffix = [5],
SuffixMinimum = 5 ;
false.
Maybe even without exposing the suffix:
list_suffixminimum(List, SuffixMinimum) :-
list_suffix(List, Suffix),
list_minimum(Suffix, SuffixMinimum).
?- list_suffixminimum([4, 2, 3, 5], SuffixMinimum).
SuffixMinimum = 2 ;
SuffixMinimum = 2 ;
SuffixMinimum = 3 ;
SuffixMinimum = 5 ;
false.
Now, and only now that the problem has been solved, you can add I/O if you feel like it. Although at this point, why would you?

Prolog - Recursive append to list returning false

Title says it all, but here we are again. Trying to append recursively to a list in Prolog, and while I have previously gotten it to work by having "temporary buffers" (via nb_setval/nb_getval) I'd like to learn how to, in a slightly more appropriate way, recursively append to lists.
I've understood Prolog works all around bindings and once something is bound it's difficult to manipulate it, so initially I sat with this, but I've understood why that does not quite work:
recursiveAppend([], _).
recursiveAppend([H|T], Output):-
append(H, [], Output),
recursiveAppend(T, Output).
That made me change the code and go to the following:
recursiveAppend([], _).
recursiveAppend([H|T], Output):-
append(H, Output, NewOutput),
recursiveAppend(T, NewOutput).
Which I had hoped would work, as it made sense to myself and apparently to others while scouring other StackOverflow questions as well. Unfortunately, calling this predicate in SWI-Prolog only returns false.
?- recursiveAppend([1, 2, 3, 4, 5], L1). false
Expected/desired result would, in this case, be:
?- recursiveAppend([1, 2, 3, 4, 5], L1). L1 = [1, 2, 3, 4, 5].
For the sake of clarification, the runtime of the program should look something like this if "fleshed out":
recursiveAppend([H|T], Output):-
% H is 1, Output is []
append(H, Output, NewOutput),
% NewOutput is [1]
recursiveAppend(T, NewOutput).
recursiveAppend([H|T], Output):-
% H is 2, Output is [1]
append(H, Output, NewOutput),
% NewOutput is [1, 2]
recursiveAppend(T, NewOutput).
recursiveAppend([H|T], Output):-
% H is 3, Output is [1, 2]
append(H, Output, NewOutput),
% NewOutput is [1, 2, 3]
recursiveAppend(T, NewOutput).
recursiveAppend([H|T], Output):-
% H is 4, Output is [1, 2, 3]
append(H, Output, NewOutput),
% NewOutput is [1, 2, 3, 4]
recursiveAppend(T, NewOutput).
recursiveAppend([H|T], Output):-
% H is 5, Output is [1, 2, 3, 4]
append(H, Output, NewOutput),
% NewOutput is [1, 2, 3, 4, 5]
recursiveAppend(T, NewOutput).
recursiveAppend([], _). % First argument (list) is empty, and the second argument (list) has been populated (with [1, 2, 3, 4, 5]), program done.
Any and all help is appreciated, even though this question has probably been asked a million times before!
"Recursive append" is not something that often makes sense in Prolog. The question should include information about what problem you are trying to solve. Currently it is not about that; it is about how you are trying to solve your problem. That "how" is "recursive append", but this is almost certainly not how you should really solve that problem. We could offer better help if we knew what the problem was, not how you think you want to solve it.
Taking the example from the question and the solution from https://stackoverflow.com/a/64092447/4391743:
?- recursiveAppend([1, 2, 3], Ys).
Ys = [1, 2, 3].
?- recursiveAppend(Xs, [1, 2, 3]).
Xs = [1, 2, 3] ;
% nontermination after first answer
?- recursiveAppend([1, 2, X], [A, B, 3]).
X = 3,
A = 1,
B = 2.
?- recursiveAppend([1, 2 | Rest], [A, B, 3, 4]).
Rest = [3, 4],
A = 1,
B = 2 ;
% nontermination after first answer
If this is what you want, then what you seem to want is a "list copy" predicate. Here's a shorter, faster, more complete one:
list_copy([], []).
list_copy([X | Xs], [X | Ys]) :-
list_copy(Xs, Ys).
This doesn't have the non-termination issues that the above predicate has:
?- list_copy([1, 2, 3], Ys).
Ys = [1, 2, 3].
?- list_copy(Xs, [1, 2, 3]).
Xs = [1, 2, 3].
?- list_copy([1, 2, X], [A, B, 3]).
X = 3,
A = 1,
B = 2.
?- list_copy([1, 2 | Rest], [A, B, 3, 4]).
Rest = [3, 4],
A = 1,
B = 2.
If one of the arguments is a list and the other is a variable, a new list structure will be built up and bound to this variable.
But... why do you need a new list structure at all? In pure Prolog you can't tell whether two terms are the same (i.e., sharing the same memory location) or "just" structurally equal. Neither do (or should) you usually care. (There are uses for knowledge about sharing, and about explicit copying, in non-pure Prolog, but again we don't know what you're trying to do.)
So if we can't tell whether a "copy" is indeed a copy or just "an equal term", then we don't need to copy at all. We can get the exact same behavior as above with just unification:
?- [1, 2, 3] = Ys.
Ys = [1, 2, 3].
?- Xs = [1, 2, 3].
Xs = [1, 2, 3].
?- [1, 2, X] = [A, B, 3].
X = 3,
A = 1,
B = 2.
?- [1, 2 | Rest] = [A, B, 3, 4].
Rest = [3, 4],
A = 1,
B = 2.
No copying and certainly no "recursive append" is needed to achieve unification, Prolog knows how to do unification for you.
If this is not what you want, please tell us what the actual problem is. "Recursive append" is almost certainly not it.
Prolog is a different programming paradigm. It requires you to "forget" all you know about programming and learn with an open mind. Don't try to learn Prolog while using "ordinary" variables and reaffecting different values, Prolog variables has only one value or none. They may take different values only on backtracking, and trying to find another set of values to all variables in your program that satisfies all the given predicates.
Suggest you to read books like "learn Prolog Now". Numerous tutorials from state universities are available free on the internet.
Based on your latest edit giving an example to Calling recursiveAppend, here's a code conform with the example.
recursiveAppend(X, Y) :- recursiveAppend(X, [], Y).
recursiveAppend([], X, X).
recursiveAppend([H|T], Current, Output):-
append(Current, [H], NewTemp),
recursiveAppend(T, NewTemp, Output).
Your earlier codes returned false because append expects lists as arguments. So appending an integer (item of input list) will Always fail. I created a version recursiveAppend/3 to accumulate current list in the second arg. At the end of the list, the current list becomes the final output. Will you test it further with more examples and tell us if it is working as required.

prolog list keeps expanding when semi colon is pressed

Hi I am creating a predicate list from, which if used gives you the numbers between a certain range. So say for instance
list_from(1,5,X).
would give you
X=[1,2,3,4,5].
However I got my predicate to work, but the list just keeps expanding, so it keeps increasing my one and I do not want it to. This is what is happening.
?- list_from(1,7,X).
X = [1, 2, 3, 4, 5, 6, 7] ;
X = [1, 2, 3, 4, 5, 6, 7, 8] ;
X = [1, 2, 3, 4, 5, 6, 7, 8, 9] ;
X = [1, 2, 3, 4, 5, 6, 7, 8, 9|...] ;
X = [1, 2, 3, 4, 5, 6, 7, 8, 9|...]
How do I get this to stop?
Here is my code
list_from(M,N,[]):- M > N.
list_from(M,N,[M|T]):- Mplusone is M + 1, list_from(Mplusone,N,T).
if I remove Mplusone and just M instead I get an error "Out of global stack"
Your two clauses are not mutually exclusive. You have a "guard" in the first clause saying that M > N, but you don't have the opposite condition, M =< N, in the second clause. If you trace the execution you should get an idea of what happens with your current definition.
You might also try to look at the definition of numlist/3 in SWI-Prolog's library(lists). It takes a different approach: first, make sure that the arguments make sense; then, under the condition that the initial Low is indeed lower than High (and both are integers), generate a list.
Semicolon means that you want Prolog to show you more options (that you are not satisfied with the answer). A full stop '.' will stop Prolog from providing you with alternatives.
You could also invoke list_from/3 using once/1. (Credit to #mat)

Eliminate a X element on a list

I have the following knowledge base
eliminate(X,[X|T],T).
eliminate(X,[H|T],[H|T2]) :- eliminate(X,T,T2).
And I have to make the running process of an example by myself, without the interpreter (like a tree).
For example, if I post the query: eliminate(3,[1,2,3,4,5],Y).
First using the first fact, we unificate X=3, and with the second element, which is a list([1,2,3,4,5]) we try to unify 1 with X, but we can't because X now is 3, so it fails and we try with the second rule.
eliminate(3,[1,2,3,4,5],Y).
x = 3, H = 1, T = [2,3,4,5], H = Y , T2 = []
This it the part that I am not sure is right. I don't know why T2 has to be unified with [].
Now with the body clause of the second rule: eliminate(X,T,T2), I have:
eliminate(3,[2,3,4,5],[])
x = 3, (here it fails again, so i have to use the second rule)
eliminate(3,[2,3,4,5],[])
x = 3, H = 2, T = [3,4,5], H = Y, T2 =[] ??? is T2 null again???
T2 doesn't unify with [] the first time the second rule is applied. The resolution knows it is a list (because its on the right side of the [X|Y] construct), but doesn't know its value yet. To find its value, it will first compute the rule, which will find a value for T2 recursively, then unify this value with the Y you ran in your query.
In your example, running the query eliminate(3, [1, 2, 3, 4, 5], Y). will do the following:
Call eliminate(3, [1, 2, 3, 4, 5], Y)
2nd rule: X=3, H=1, T=[2,3,4,5], T2=?, Y=[H|?]
Call eliminate(3, [2, 3, 4, 5], ?)
2nd rule: X=3, H=2, T=[3,4,5], T2=??, Y=[H|??]
Call eliminate(3, [3, 4, 5], ??)
1st rule: ??=[4, 5]
Go back one step, using Y=[H|??], H=2 ??=[4,5]: Y = [2|[4,5]] = [2, 4, 5] = ?
Go back another step, using Y=[H|?], H=1, ?=[2, 4, 5]: Y = [1|[2, 4, 5]] = [1, 2, 4, 5]
I suggest spending some time reading the recusion chapter of your Prolog learning source. Additionally, to find out how you can see this execution in practice to see what's happening, you can use the trace. "command" or other debug equivalent, see this link for swi-pl specifics on debugging a program.

members predicate in Prolog

I'd like to define a members predicate.
members(A, B) means that all members of the list A are members of list B.
top(N) defines how long A can be.
This is my try:
top(5).
members([X], L):-
member(X, L).
members([X| Xs], L):-
member(X, L),
members(Xs, L),
length(Xs, M),
top(N),
M < N.
I'd like to use it as follow:
members(L, [1,2,3]).
The problem with my implementation is that if I ; to get new answers, I'll finish with an ERROR: Out of local stack
?- members(I, [1,2,3]).
I = [1] ;
I = [2] ;
I = [3] ;
I = [1, 1] ;
I = [1, 2] ;
I = [1, 3] ;
I = [1, 1, 1] ;
I = [1, 1, 2] ;
I = [1, 1, 3] ;
I = [1, 1, 1, 1] ;
I = [1, 1, 1, 2] ;
I = [1, 1, 1, 3] ;
I = [1, 1, 1, 1, 1] ;
I = [1, 1, 1, 1, 2] ;
I = [1, 1, 1, 1, 3] ;
;ERROR: Out of local stack
How can I change my code to prevent this out of memory?
As already mentioned, your problem is that you do the length check after the recursive call, meaning that the recursion is unbounded. Unfortunately, just moving the length check above the recursive call like this...
members([X], L):-
member(X, L).
members([X|Xs], L):-
length(Xs, M),
top(N), M < N,
member(X, L),
members(Xs, L).
...is not so good as we get this:
L = [3, 1, 2, 3, 3] ;
L = [3, 2, 2, 3, 3] ;
L = [3, 3, 2, 3, 3] ;
L = [3, 1, 3, 3, 3] ;
L = [3, 2, 3, 3, 3] ;
L = [3, 3, 3, 3, 3] ;
ERROR: Out of global stack
While this gets us the answer, it's not that useful as it can't be put inside a larger predicate since it breaks. It breaks because we have only pushed the problem further along. Here's why:
The problem is that you are constructing the list in a top-down manner. In other words, we define the list like this: List = [Head|Tail] where we stipulate some constraints on Head and state that Tail is made up of a list of elements defined by the same constraints and bounded by a base case. This means that while we are in the middle of the recursive call, we actually only have access to Head - we cannot access the contents of Tail as it is only constructed once the interpreter has gone all the way down and reached the base case (i.e. members([X], L) :-) and then has successively added each Tail to its Head until the final List is constructed.
It may look like we have access to the length, since the length/2 call is sitting there in the middle of the recursive predicate, however since the variable being passed into length/2 for the list is at this stage not bound to anything, Prolog waits until it has finished the recursive calls beneath this point before calculating the length. The problem of course is that the length check is what is bounding the recursion, so it will just continue until it runs out of memory.
While top-down recursion tends to be the default way of constructing Prolog predicates, as this example shows, sometimes we need access to the data structure we are creating. The solution is to use bottom-up recursion. This is implemented in Prolog by means of an accumulator predicate, which starts with an empty list and proceeds to build the list up one by one, by passing the accumulator list (which is a fully ground list) through the recursive predicate. Here's how I would write an accumulator predicate for this problem:
members(I,L) :-
members_accumulator([],I,L).
members_accumulator(Tail,I,L) :-
length(Tail, M),
top(N),
M < N,
member(X, L),
members_accumulator([X|Tail],I,L).
members_accumulator(I,I,_).
We need two predicates, as the first is a wrapper around the accumulator which passes the empty list to the accumulator predicate. The base case no longer has anything to do with the empty list - all it has to do is state that the final accumulator list is actually the final list that we're after (which has been threaded through the accumulator predicate just for this purpose). Also, in this case, the accumulator predicates need to be in this order otherwise there will be one choice point that evaluates as false right at the end.
Getting ones head around recursion in Prolog and when you need to use bottom-up recursion rather than top-down is a non-trivial feat. I didn't really have a solid grasp on it at all until I had a good read through The Art of Prolog. There should also be plenty of info about accumulators online.
Here is an alternate implementation which does'nt require calculating the length of the list. Here N is the length of list A. This solution gives all the answers without going out of stack.
members([X],L,1) :- member(X,L).
members([H|T],L,N) :- N>1 , member(H,L) , N1 is N-1, members(T,L,N1).
Example execution:
?- members(L,[1,2,3],5).
L = [1, 1, 1, 1, 1] ;
L = [1, 1, 1, 1, 2] ;
L = [1, 1, 1, 1, 3] ;
L = [1, 1, 1, 2, 1] ;
...
L = [3, 3, 3, 1, 2] ;
L = [3, 3, 3, 3, 1] ;
L = [3, 3, 3, 3, 2] ;
L = [3, 3, 3, 3, 3] ;
No
You do the check for the depth after the recursion. So the depth of the recursion is not limited, only the resulting lists are discarded as too long.
Use meta-predicate maplist/2,
lambdas, and membership predicate memberd/2 and simply write:
:- use_module(library(lambda)).
members(As,Bs,N) :-
length(Xs,N),
append(As,_,Xs),
maplist(Bs+\A^memberd(A,Bs), As).
Sample query with abbreviated answer sequence:
?- members(As,[1,2,3],5).
As = [ ] ;
As = [ 1] ; As = [ 2] ; As = [ 3] ;
As = [ 1,1] ; As = [ 1,2] ; /* ... */ As = [ 3,3] ;
As = [ 1,1,1] ; As = [ 1,1,2] ; /* ... */ As = [ 3,3,3] ;
As = [ 1,1,1,1] ; As = [ 1,1,1,2] ; /* ... */ As = [ 3,3,3,3] ;
As = [1,1,1,1,1] ; As = [1,1,1,1,2] ; /* ... */ As = [3,3,3,3,3] ;
false.
Above query universally terminates.
Let's look at the size of the solution set:
?- setof(As,members(As,[1,2,3],5),Ass), length(Ass,N_Solutions).
Ass = [[],[1],[1,1],[1,1,1],[1,1,1|...],[1,1|...],[1|...],[...|...]|...],
N_Solutions = 364.
?- 364 =:= 1 + 3 + 3^2 + 3^3 + 3^4 + 3^5.
true.

Resources