Issue with output in Prolog - prolog

I recently wanted to experiment with Prolog to understand how the process of unification works so I wrote the following code to return the nth element from a list.
getfromarray([X|_],1,X).
getfromarray(A,N,E):-
N > 1,
A = [_|Y],
N1 is N-1,
getfromarray(Y,N1,E).
However, upon entering the input to the program as
getfromarray(A,3,E), it returns :-
A = [_G5129, _G5132, E|_G5136]
I understand that since i wrote the rule A = [_|Y] , A is being unified to satisfy the conditions of the rules in the program hence A is being displayed in this format. However, I don't understand why E is not being unified with the value in the array. I did read through the basics of unification in Prolog and I understand that while the answer is not wrong, it does not do what it is intended to do. Can someone suggest a topic in unification I might have missed upon which might help me solve this minor issue?
EDIT:
When I passed a list as a parameter to the program, it gave the associated value of E in the list.However, when I unified a variable A with a list and passed A as a parameter to the program, It is displaying the same output as i mentioned above.
5 ?- getfromarray([1,2,5,4,5],3,E).
E = 5 .
6 ?- A = [1,2,3,4,5].
A = [1, 2, 3, 4, 5].
7 ?- getfromarray(A,3,E).
A = [_G576, _G579, E|_G583] .
8 ?-

Prolog doesn't store your list A, therefore A is uninstantiate.
A = [1, 2, 3, 4, 5].
getfromarray(A,3,E).
This is like just calling :
getfromarray(A,3,E).
Try this in stead :
A = [1, 2, 3, 4, 5], getfromarray(A,3,E).

Related

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 stucks after giving the result

So I have this knowledge base and I am trying to achieve the goals in the code given as comments.
%format of foo: foo(Tag,NumList)
foo(a, [2, 4]).
foo(b,[2, 8, 8, 6,2]).
foo(c,[4, 8, 8, 8, 7]).
foo(d,[7, 8, 8, 2]).
foo(e,[5, 8, 9, 6]).
foo(f,[2, 5]).
foo(g,[2, 6]).
foo(h, [2, 8, 2]).
foo(i, [2, 8, 8, 2]).
foo(j, [2, 3]).
However there is a problem with the goo part. When I only give Total_num to goo and get the unified results for Foo_list, it gives the results but after that it just gets stuck. Nothing works and I have to close the interpreter all the time.
I tried putting cuts to goo helpers but nothing works. Also when I change the order of predicates in goo(putting goo_ordered in front), it doesn't give the list and just gets stuck. How can I fix this problem? What causes it?
Thank you
%returns the sum of the numbers the NumList
foo_sum(Tag,SUM):- foo(Tag,List),foo_sum_helper(List,SUM).
foo_sum_helper([],0).
foo_sum_helper([H|T],Result):- foo_sum_helper(T,Prev_result), Result is H + Prev_result.
%foo diff find the last number in the list.
%It should remain the if it is less than or equal to four, otherwise substract 8 from it
foo_diff(Tag,Diff):- foo(Tag,List),foo_diff_helper(List,Diff).
foo_diff_helper([Last],Result):- Last =< 4, Result is Last,!.
foo_diff_helper([Last],Result):- Last > 4, Result is Last - 4,!.
foo_diff_helper([_,X|T],Result):- foo_diff_helper([X|T], Result).
%goo takes a list of foo's and a number that represents the total number of each foo_sum of foo's.
%Total of foo_diff must be 0
%Also the list of foo's must be in the ascending order.(foo_sum of the first foo in the list is the least one.)
goo(Foo_list,Total_num):- goo_sum(Foo_List,Total_num),goo_diff(Foo_list,0),goo_ordered(Foo_list).
goo_ordered([]).
goo_ordered([_]).
goo_ordered([X,Y|Z]):- foo_sum(X,NUMX),foo_sum(Y,NUMY),NUMX =< NUMY, goo_ordered([Y|Z]).
goo_sum([X],RESULT):- foo_sum(X,RESULT).
goo_sum([H|T],RESULT):- goo_sum(T,PREV_RESULT),foo_sum(H,NUMH), RESULT is NUMH + PREV_RESULT.
goo_diff([X],RESULT):- foo_diff(X,RESULT).
goo_diff([H|T],RESULT):- goo_diff(T,PREV_RESULT),foo_diff(H,HDIFF), RESULT is HDIFF + PREV_RESULT.
What causes it?
Assuming you mean the looping of goo_sum(X, 20):
For the query I get quite a lot of answers. Actually, too much for me. So I will instead consider
?- goo_sum(X, 20), false.
which loops. The A reason is the following very compact failure-slice
goo_sum([X],RESULT):- false, foo_sum(X,RESULT).
goo_sum([H|T],RESULT):-
goo_sum(T,PREV_RESULT), false,
foo_sum(H,NUMH), RESULT is NUMH + PREV_RESULT.
You need to fix the remaining part somehow or the loop will remain.
BTW, using names as foo and goo is not a very good idea. I still do not understand your program and so do you, I presume.
I'd rather stick to smaller programs first. Also consider to use clpfd in place of the moded arithmetic via (is)/2. Here is such a suggested improvement—for a question of your colleague presumably.
And: You got some warnings by the system about a singleton variable, you need to fix that anyway. That is s/Foo_List/Foo_list/

Prolog Skip some backtracking branches

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.

List manipulation with prolog

I am trying to create a query that gives back the following:
sky([1,2,3,4,5,6],X).
X = [1,3,5,2,6,4]
That is, it takes out every other element of a list, and does the same on the remaining list and puts everything together.
This is my code so far.
sky([X|Y], Skied):-
split([X|Y],Z1),
split(X,Z2),
sky(Z2,Z3),
append(Z1,Z3,Skied).
sky([],[]).
split([X,_|T], [X|R]):-
split(T,R).
split([X|[]], [X]).
split([],[]).
Can someone explaint o me why it wont work and the process behind it, like a visual guide. Thanks!
Your code is almost right, instead of split(X,Z2) you need to write split(Y,Z2). That's because X is a single element and split(X,Z2) will return [X], which if I understood correctly isn't what you want. You need to write split(Y,Z2) to take the even elements (or in your description every other element) and call sky(Y,Z3) to do the same recursively. So the new version is:
sky([X|Y], Skied):-
split([X|Y],Z1),
split(Y,Z2),
sky(Z2,Z3),
append(Z1,Z3,Skied).
sky([],[]).
split([X,_|T], [X|R]):-
split(T,R).
split([X|[]], [X]).
split([],[]).
Some examples and output:
?- sky([1,2,3,4,5,6],X).
X = [1, 3, 5, 2, 6, 4] ;
false.
?- sky([1,2,3,4,5,6,7,8,9],X).
X = [1, 3, 5, 7, 9, 2, 6, 4, 8] ;
false.

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.

Resources