How to get the last answer of the recursion directly in Prolog - recursion

Here is the main part of my code in Prolog:
state(N, Sf) :-
get_initial_state('test.csv',S),
state_sequence(N, S, Sf).
state_sequence(N, S, S).
state_sequence(N, S, Sf) :-
transition_state(S, S, [], Sn),
N > 0,
N1 is N - 1,
state_sequence(N1, Sn, Sf).
transition_state is just a set of rules which does not matter here. And it is a recursion which keeps going to get value of next state until N reaches 0.
Then for example I want the 48th result of state. So my query is
state(48,S).
Then I need to keep pressing ; and prolog keeps telling me next state and then until 48th it results in false.
So how can I get the 48th result directly without telling me results of each state??

The fastest way is to generate all solutions using findall/3, then get the solution you want. This is a simple example to show you the idea:
test(1,0).
test(2,0).
test(3,0).
test(4,0).
test(5,0).
test(6,0).
getNthSolution(Sol,N):-
findall(S,test(S,0),L),
nth1(N,L,Sol).
?- getNthSolution(S,3)
S = 3

Related

Recursive search & Accumulators & Counters in Prolog

After a long search on google I couldn't find a clear answer of this:
In Prolog doing recursion by itself its easy. My main problem is understanding where to place accumulators and counters. Here is an example:
nXlist(N,X,[X|T]):-
N \=0,
N1 is N-1,
nXList(N1,X,T).
nXList(0,_,[]).
media([X|L], N, Soma):-
media(L, N1, Soma1),
N is N1 + 1,
Soma is Soma1 + X.
media([], 0, 0).
On the first example i used a counter BEFORE the recursion but in the second example I use it AFTER. The reason I have done that is the called try and see cause i really can't understand why sometimes is before and sometimes is after...
Maybe the central point of your question is in the preamble:
In Prolog doing recursion by itself its easy
It's not easy, it's mandatory. We don't have loops, because we don't have a way to control them. Variables are assign once.
So, I think the practical answer is rather simple: if the 'predicate' (like is/2) needs a variable value, you ground the variable before calling it.
To me, it helps to consider a Prolog program (a set of clauses) as grammar productions, and clause arguments as attributes, either inherited (values computed before the 'instruction pointer') or synthesized (values computed 'here', to be returned).
update: Most importantly, if the recursive call is not last, the predicate is not tail recursive. So, having anything after the recursive call should be avoided if possible. Notice that both definitions in the answer by user false are tail recursive, and that's precisely due to the fact that the arithmetic conditions there are placed before the recursive call, in both of them. That's so basic, that we have to make an effort to notice it explicitly.
Sometimes we count down, sometimes we count up. I discuss this in another answer at length. It talks of accumulators, befores and afters. :)
There's also this thing called "associativity" of an operation (say, +), where
a+(b+(c+....)) == (a+b)+(c+...)
that lets us regroup and (partially) calculate sooner rather than later. As soon as possible, but not sooner.
Short answer: you can place such arithmetical relations both before and thereafter. At least, if you are using constraints in place of (is)/2. The only difference may be in termination and errors.
So let's see how your predicates can be defined with constraints:
:- use_module(library(clpfd)).
nXList(0,_,[]).
nXList(N,X,[X|T]):-
N #> 0,
N1 #= N-1,
nXList(N1,X,T).
media([], 0, 0).
media([X|L], N, Soma):-
N #> 0,
N #= N1 + 1,
Soma #= Soma1 + X,
media(L, N1, Soma1).
You can now use these definitions in a much more general way, say:
?- nXList(3, X, T).
T = [X, X, X]
; false.
?- media(Xs, 3, S).
Xs = [_A, _B, _C], _D+_A#=S, _C+_B#=_D
; false.
... nXList/3 can be more compactly expressed by:
..., length(T, N), maplist(=(X), T), ...

Avoiding infinite recursion but still using unbound parameter passing only

I have the following working program: (It can be tested on this site: http://swish.swi-prolog.org, I've removed the direct link to a saved program, because I noticed that anybody can edit it.)
It searches for a path between two points in an undirected graph. The important part is that the result is returned in the scope of the "main" predicate. (In the Track variable)
edge(a, b).
edge(b, c).
edge(d, b).
edge(d, e).
edge(v, w).
connected(Y, X) :-
(
edge(X, Y);
edge(Y, X)
).
path(X, X, _, []) :-
connected(X, _).
path(X, Y, _, [X, Y]) :-
connected(Y, X).
path(X, Z, Visited, [X|Track]) :-
connected(X, Y),
not(member(X, Visited)),
path(Y, Z, [X|Visited], Track).
main(X, Y) :-
path(X, Y, [], Track),
print(Track),
!.
Results:
?- main(a, e).
[a, b, d, e]
true
?- main(c, c).
[]
true
?- main(b, w).
false
My questions:
The list of visited nodes is passed down to the predicates in 2 different ways. In the bound Visited variable and in the unbound Track variable. What are the names of these 2 different forms of parameter passing?
Normally I only wanted to use the unbound parameter passing (Track variable), to have the results in the scope of the main predicate. But I had to add the Visited variable too, because the member checking didn't work on the Track variable (I don't know why). Is it possible to make it work with only passing the Track in an unbound way? (without the Visited variable)
Many thanks!
The short answer: no, you cannot avoid the extra argument without making everything much messier. This is because this particular algorithm for finding a path needs to keep a state; basically, your extra argument is your state.
There might be other ways to keep a state, like using a global, mutable variable, or dynamically changing the Prolog data base, but both are more difficult to get right and will involve more code.
This extra argument is often called an accumulator, because it accumulates something as you go down the proof tree. The simplest example would be traversing a list:
foo([]).
foo([X|Xs]) :-
foo(Xs).
This is fine, unless you need to know what elements you have already seen before getting here:
bar(List) :-
bar_(List, []).
bar_([], _).
bar_([X|Xs], Acc) :-
/* Acc is a list of all elements so far */
bar_(Xs, [X|Acc]).
This is about the same as what you are doing in your code. And if you look at this in particular:
path(X, Z, Visited, /* here */[X|Track]) :-
connected(X, Y),
not(member(X, Visited)),
path(Y, Z, [X|Visited], /* and here */Track).
The last argument of path/4 has one element more at a depth of one less in the proof tree! And, of course, the third argument is one longer (it grows as you go down the proof tree).
For example, you can reverse a list by adding another argument to the silly bar predicate above:
list_reverse(L, R) :-
list_reverse_(L, [], R).
list_reverse_([], R, R).
list_reverse_([X|Xs], R0, R) :-
list_reverse_(Xs, [X|R0], R).
I am not aware of any special name for the last argument, the one that is free at the beginning and holds the solution at the end. In some cases it could be an output argument, because it is meant to capture the output, after transforming the input somehow. There are many cases where it is better to avoid thinking about arguments as strictly input or output arguments. For example, length/2:
?- length([a,b], N).
N = 2.
?- length(L, 3).
L = [_2092, _2098, _2104].
?- length(L, N).
L = [],
N = 0 ;
L = [_2122],
N = 1 ;
L = [_2122, _2128],
N = 2 . % and so on
Note: there are quite a few minor issues with your code that are not critical, and giving that much advice is not a good idea on Stackoverflow. If you want you could submit this as a question on Code Review.
Edit: you should definitely study this question.
I also provided a somewhat simpler solution here. Note the use of term_expansion/2 for making directed edges from undirected edges at compile time. More important: you don't need the main, just call the predicate you want from the top level. When you drop the cut, you will get all possible solutions when one or both of your From and To arguments are free variables.

Recursion in· Prolog

I am trying to understand recursion in Prolog, but it is certainly different than how it is in other languages like PHP, Java and C. I have been reading all the tutorials about it, but I still don't get specific, rather complicated cases.
For instance, in order to get the number of occurrences of an element in a list we have:
occurrence([], _, 0).
occurrence([H | T], H, N) :- !, occurrence(T, H, N1), N is N1 + 1.
occurrence([_ | T], H, N) :- occurrence(T, H, N).
which can be called using:
occurrence([1,4,9,1,2],1,R).
and it should result:
?- R=2
Why is line 3 even happening? What is it doing? I wrote this program without looking at the answer and I was done after the 2nd line. Of course it wasn't working though.
On the other hand, why is the "cut" occurring in there? I have been trying to print out the result after every call and I just get more and more confused.
Line 3 handles the case where the head of the list doesn't match the item you're looking for. Suppose you've passed the first element, you wind up in the recursive call to occurrence/3 which looks like:
occurrence([4,9,1,2], 1, 1).
Which rule matches? Rule 1 doesn't match because we don't have the empty list. Rule 2 doesn't match because 4 \= 1. The third rule is for this case, and it just says, you didn't find a 1 here, so keep looking with the tail of the list ([9,1,2]).
The cut is there because the third rule will match any list. The cut commits you to the choice. What choice? That you have the same value in the head of the list and as the element you're seeking, because that's the pattern that must be matched to enter the body of this rule. If you omit the cut, you're permitting a choice point after unifying the head of the list with the element being sought, which means you'll get more than one solution with unifications for R = 2, then R = 1, then R = 0. This is because each 1 could also just be ignored as in the third rule.
You can get rid of the cut by making the third rule conditional:
occurrence([H1|T], H2, N) :- H1 \= H2, occurrence(T, H2, N).
You could also use a conditional expression and have one rule combine rules 2 and 3:
occurrence([H|T], S, N) :-
(H = S
-> occurrence(T, S, N1), N is N1 + 1
; occurrence(T, S, N)
).
This is likely to be somewhat more efficient; the conditional expression doesn't create choice points the way additional rule bodies do. Prolog isn't psychic, so it can't detect that rules are mutually exclusive. I would prefer the logical formulation with multiple rules for readability though.
Hope this helps.

Prolog iteration/recursion to drill down to lowest value

I'm trying to create a predicate in prolog which will hold true if it reaches the lowest numerical value out of a set of values.
For example:
I have something like this at the moment
Base Step
lowest(Object, Value) :- \+ lessThan(Object, Value, NewValue).
Recursive Step
lowest(Object, Value) :- lessThan(Object, Value, NewValue), lowest(Object, NewValue).
Where Object is some abstract object which can have multiple numerical values attached to it.
lessThan returns Values (NewValue) for the Object which are less than the input Value.
And since NewValue will be lower than the input of Value I can assume that with each recursive step Value will be decreasing.
I have abstracted this problem from another which I am trying to solve, but basically what is happening is that I expect only 2 outputs from the whole recursive function, but instead I am getting as many outputs as lessThan(Object, Initial, X) + 2.
I'm not sure if this question is clear, please let me know so I can clarify.
I believe that my base step is correct, since I am making the assumption that if Value is the lowest coupled with Object, then there are no other values less than Value.
I am unsure where to terminate the recursion also, which is adding to my confusion. My guess is that it will terminate once it reaches a state where there are no lower Values for Object.
This sample should work, renaming value/2 as appropriate for your domain.
value(a, 10).
value(a, 3).
value(a, 100).
lowest(Object, L) :-
value(Object, First), !, lowest(Object, First, L).
lowest(Object, LowestSoFar, Lowest) :-
value(Object, Try), Try < LowestSoFar, !,
lowest(Object, Try, Lowest).
lowest(_, Lowest, Lowest).
it yields
?- lowest(a,X).
X = 3.
Note that it repeats the value 'peek' each time, then is not efficient.
A possible alternative is storing the lower value and run a failure driven loop.
Otherwise, SWI-Prolog (and YAP) has library(aggregate):
?- aggregate(min(V), value(a,V), M).
M = 3.

advice needed with prolog cut?

in this task i have a Prolog database filled with e.g.
edge(1,0)
edge(2,0)
edge(1,3)
an edge signifies that two points are joined.
I am asked to write a function called reach(i,j,k) where i is the start point j is the end point and k is the number of steps you may use.
K is needed to stop the recursion looping e.g.
Suppose the only edge I’ve got goes from 1 to3,and I’m trying to get to 6. Then I can’t get from 1to6 in one go. so I’ll look for somewhere I can get to, and see if I can get from there to 6. The first place I can get to in one go is 3, so I’ll try to get from there to 6.
i have done this as so:
%% Can you get there in one step (need two rules because all links are
%% from smaller to greater, but we may need to get from greater to smaller.
reach1(I, J,_K) :-
edge(I, J).
reach1(I, J,_K) :-
edge(J, I).
%% Chhose somewhere you can get to in one step: can you get from there
%% to your target?
reach1(I,J,K) :-
K>1,
edge(I, B),
K1 is K-1,
reach1(B,J,K1).
reach1(I,J,K) :-
K>1,
edge(B, I),
K1 is K-1,
reach1(B,J,K1).
this works, however i am stuck with the second part in which we are asked not to use k but to use a "cut" to do this.
does anyone know how to do this or can give me some pointers?
The cut ensures that once a goal has been resolved in one way, it doesn't look for another way.
example:
reach(I, J,_K) :-
edge(I, J).
no cut - if for some reason Prolog backtracks, it will try to reach from I to J another way.
You might feel there's no point reaching this node another way if the simple edge works, and in that case you can do:
reach(I, J,_K) :-
edge(I, J),
!.
which "cuts" any alternative to this goal, but the one Prolog has found.

Resources