What I have...
tree(nil).
tree(b(Left,_,Right)) :-
tree(Left),
tree(Right).
mirror(b(Left,Head,Right), NewTree) :-
mirror(Left,NewLeft),
mirror(Right,NewRight),
NewTree = b(NewRight,Head,NewLeft).
What I'm querying...
mirror(b(nil,a,b(nil,b,nil)), Result).
Expected result
Result = b(b(nil,b,nil),a,nil).
The tree b(Left,Right,Head) is the first argument of mirror, NewTree is the goal. mirror(Left,NewLeft) recurses through the left side and yields the goal NewLeft, same for Right. NewTree is the tree b(NewRight,Head,NewLeft).
I'm not sure why this isn't working could someone please help.
Based on your current code
tree(nil).
tree(b(Left,_,Right)) :-
tree(Left),
tree(Right).
mirror(b(Left,Head,Right), NewTree) :-
mirror(Left,NewLeft),
mirror(Right,NewRight),
NewTree = b(NewRight,Head,NewLeft).
you are very close.
As noted in a comment by Steven
You're missing the base case for mirror/2. What should NewTree be when the input tree is nil?
is very helpful.
Before getting to the full working predicate lets clear up a other things.
The predicate for tree is not needed.
tree(nil).
tree(b(Left,_,Right)) :-
tree(Left),
tree(Right).
I don't know if you are showing this to shows us that you know how a tree works or what but for others reading this predicate it is not needed for the answer.
That leaves only
mirror(b(Left,Head,Right), NewTree) :-
mirror(Left,NewLeft),
mirror(Right,NewRight),
NewTree = b(NewRight,Head,NewLeft).
A standard style with using a variable that works like an input and output with several usages is for the starting one, append a 0, then for each succeeding use increase the appended number and for the result append nothing.
mirror(b(Left0,Head,Right0), NewTree) :-
mirror(Left0,Left),
mirror(Right0,Right),
NewTree = b(Right,Head,Left).
Next =/2 is just doing unification. This can be refactored as such
mirror(b(Left0,Head,Right0), b(Right,Head,Left)) :-
mirror(Left0,Left),
mirror(Right0,Right).
Now back to your problem
Since a tree is a recursive structure, it can be processed with with recursion. Predicates that work on recursive data structures need a base clause and a clause to do the recursion. You already have a clause to do the recursion but just need a base clause.
If you use the SWI-Prolog gui tracer on your code for the query
mirror(b(nil,a,b(nil,b,nil)), Result).
you will see
that when one of the branches is just nil there is no mirror/2 rule to handle this case.
Adding
mirror(nil,nil).
will solve your problem.
?- mirror(b(nil,a,b(nil,b,nil)), Result).
Result = b(b(nil, b, nil), a, nil).
The entire predicate.
mirror(nil,nil).
mirror(b(Left0,Head,Right0), b(Right,Head,Left)) :-
mirror(Left0,Left),
mirror(Right0,Right).
Related
I'm currently writing a prolog A* search function, and ran into an issue with one of my queries. So I decided to manually test the base case, as that's where the trace was failing.
addAChild([Child],[],[Child]):-
write(woo empty).
I manually ran:
addAChild([c(1,1,p(1,2)),[]],[],A).
but it just fails.
Any help would be appreciated.
[Child] (a 1-element list) cannot unify with [c(1,1,p(1,2)),[]] (a 2-elements list).
That's why it is failing.
You can manually test in the interactive interpreter that those two terms fail to unify:
?- addAChild([Child],[],[Child]) = addAChild([c(1,1,p(1,2)),[]],[],A).
false.
and then you can inspect recursively which part is failing.
The term name (addAChild) and the arity (3) is the same, so we can rule off this issue.
Then proceed to unify each argument:
?- [Child] = A.
A = [Child].
?- [] = [].
true.
?- [Child] = [c(1,1,p(1,2)),[]].
false.
I am still trying to understand the Prolog logic and have stumbled upon a problem.
I am trying to save values found within recursive calls, to pass on or gather.
As such:
main([]) :- !.
main([H|Tail]) :- findall(X,something(_,_,X),R),
getValueReturn(R,H,Lin, Lout),
main(Tail).
% X is the Head from main
getValueReturn([H|Tail],X,Lin, Lout) :- subset(X, H) ->
findall(A,something(A,_,H),L1),
append(Lin,L1,Lout),
getValueReturn(Tail,X,Lout,L)
;
getValueReturn(Tail,X,Lin,Lout).
I would like to gather the results from findall in getValueReturn, combine them, and send them back to main, which can then use them.
How do I create and add to a list within getValueReturn?
Similarly, how can I save the list in my main for all recursive calls?
EDIT:
I edited the code above as per a comment reply, however when I run this through trace, the list deletes all elements when the empty list is found.
What am I doing wrong? This is the first time I try to use the concept of building a list through recursion.
You should post complete code that can be run, with example data. I have not tested this.
You need to pass L around on the top-level also. Using the same variable names for different parameters in adjacent procedures does not improve readability.
main([E|Es],L0,L) :-
findall(X,something(_,_,X),Rs),
getValueReturn(Rs,E,L0,L1),
main(Es,L1,L).
main([],L,L).
getValueReturn([R|Rs],E,L0,L) :-
( subset(E,R) ->
findall(A,something(A,_,R),New),
append(L0,New,L1),
getValueReturn(Rs,E,L1,L)
; getValueReturn(Rs,E,L0,L) ).
getValueReturn([],_,L,L).
A variable can only have one value in Prolog. In your code, for example, Lout is the output from append/3, an input to a recursive call of getValueReturn/4, and then also the output on the top-level. This is probably not going to do what you want.
I have found the best way to do what I was trying to was to use asserta/z when a result was found, and then gather these results later on.
Otherwise the code became overly complicated and did not function as intended.
So I am trying to draw the decision of tree of 2 Prolog problems, one that uses the accumulator and other that doesn't. Here are my problems and the solutions I did, respectively:
length([H|T],N) :- length(T,N1), N is N1+1.
length([ ],0).
Goal: ?: length([1,2,3],N)
Second one with accumulator:
length_acc(L,N) :- len_acc(L,0,N).
len_acc([H|T], A, N) :- A1 is A+1, len_acc(T, A1, N).
len_acc([], A, A).
Goal: ?-length_acc([1,2], N).
Are the decision trees correctly drawn? Or have I made a mistake? Whats the correct way to draw these kind of recursive decision tree?
Thanks.
The tree you are referring to is usually called a search-tree aka SLD-tree, not to be confused with a proof-tree.
Both the problems you have outlined are the most simple cases of search-trees:
there is only one solution
the query does not fail
each step in the search can only match a single clause (empty list vs non-empty list)
These three characteristics imply that there will only be a single branch in the SLD tree.
You'll get the following search-trees:
Note that for it to be a correct search-tree, at most one goal is resolved in each step, which makes search-trees very large... therefore it's common that people make simplified trees where multiple goals can be resolved in each step, which arguably are not true search-trees but illustrates the search in a more succint way.
Edges in the tree are labeled with substitutions that are applied to the variables as part of the unification algorithm.
Search-trees correspond closely to traces, and you can usually do a straight translation from a trace of your program to a search tree.
I advise you to study search-trees for queries that have multiple answers and branches that can fail, which gives more interesting trees with multiple branches. An example from The Art of Prolog by Sterling, Shapiro:
Program:
father(abraham, isaac). male(isaac)
father(haran, lot). male(lot).
father(haran, milcah). female(milcah).
father(haran, yiscah). female(yiscah).
son(X,Y):- father(Y,X), male(X).
daughter(X,Y):- father(Y,X), female(X).
Query:
?: son(S, haran)
Search-tree:
A nice way to understand something is to re-implement it yourself.
It's especially nice to implement Prolog when you already have Prolog to implement it with. :)
program( patriarchs, P ) :-
P = [ % [son(S, haran)] , % Resolvent
[father(abraham, isaac)] % Clauses...
, [father(haran, lot)] % [Head, Body...]
, [father(haran, milcah)]
, [father(haran, yiscah)]
, [male(isaac)]
, [male(lot)]
, [female(milcah)]
, [female(yiscah)]
, [son(X,Y), father(Y,X), male(X)]
, [daughter(X,Y), father(Y,X), female(X)]
].
solve( Program ):-
Program = [[] | _]. % empty resolvent -- success
solve( [[Goal | Res] | Clauses] ) :-
member( Rule, Clauses),
copy_term( Rule, [Head | Body]), % rename vars
Goal = Head, % unify head
append( Body, Res, Res2 ), % replace goal
solve( [Res2 | Clauses] ).
query( What, Query ):- % Query is a list of Goals to Solve
program( What, Program),
solve( [ Query | Program ] ).
Testing,
23 ?- query( patriarchs, [son(S, haran)] ).
S = lot ;
false.
Now the above solve/1 can be augmented to record the record of successful instantiations of Goal making the unifications Goal = Head possible.
I'm learning Erlang from the very basic and have a problem with a tail recursive function. I want my function to receive a list and return a new list where element = element + 1. For example, if I send [1,2,3,4,5] as an argument, it must return [2,3,4,5,6]. The problem is that when I send that exact arguments, it returns [[[[[[]|2]|3]|4]|5]|6].
My code is this:
-module(test).
-export([test/0]).
test()->
List = [1,2,3,4,5],
sum_list_2(List).
sum_list_2(List)->
sum_list_2(List,[]).
sum_list_2([Head|Tail], Result)->
sum_list_2(Tail,[Result|Head +1]);
sum_list_2([], Result)->
Result.
However, if I change my function to this:
sum_list_2([Head|Tail], Result)->
sum_list_2(Tail,[Head +1|Result]);
sum_list_2([], Result)->
Result.
It outputs [6,5,4,3,2] which is OK. Why the function doesn't work the other way around([Result|Head+1] outputing [2,3,4,5,6])?
PS: I know this particular problem is solved with list comprehensions, but I want to do it with recursion.
For this kind of manipulation you should use list comprehension:
1> L = [1,2,3,4,5,6].
[1,2,3,4,5,6]
2> [X+1 || X <- L].
[2,3,4,5,6,7]
it is the fastest and most idiomatic way to do it.
A remark on your fist version: [Result|Head +1] builds an improper list. the construction is always [Head|Tail] where Tail is a list. You could use Result ++ [Head+1] but this would perform a copy of the Result list at each recursive call.
You can also look at the code of lists:map/2 which is not tail recursive, but it seems that actual optimization of the compiler work well in this case:
inc([H|T]) -> [H+1|inc(T)];
inc([]) -> [].
[edit]
The internal and hidden representation of a list looks like a chained list. Each element contains a term and a reference to the tail. So adding an element on top of the head does not need to modify the existing list, but adding something at the end needs to mutate the last element (the reference to the empty list is replaced by a reference to the new sublist). As variables are not mutable, it needs to make a modified copy of the last element which in turn needs to mutate the previous element of the list and so on. As far as I know, the optimizations of the compiler do not make the decision to mutate variable (deduction from the the documentation).
The function that produces the result in reverse order is a natural consequence of you adding the newly incremented element to the front of the Result list. This isn't uncommon, and the recommended "fix" is to simply list:reverse/1 the output before returning it.
Whilst in this case you could simply use the ++ operator instead of the [H|T] "cons" operator to join your results the other way around, giving you the desired output in the correct order:
sum_list_2([Head|Tail], Result)->
sum_list_2(Tail, Result ++ [Head + 1]);
doing so isn't recommended because the ++ operator always copies it's (increasingly large) left hand operand, causing the algorithm to operate in O(n^2) time instead of the [Head + 1 | Tail] version's O(n) time.
I have this predicate that I can't seem to get to work.
The predicate should be used the following way: You give the predicate a list of things (KnowledgeList), and an uninstantiated variable (ExtractedList).
The predicate then should proceed filling ExtractedList.
To fill ExtractedList it iterates over the items of KnowledgeList,
builds a new list of extracted things, and appends this list to ExtractedList.
I know I should probably use recursion to solve this, but I feel stumped at the moment.
extractedKnowledge(KnowledgeList, ExtractedList) :-
list(KnowledgeList),
ExtractedList = [],
length(KnowledgeList,ListLength),
for(X,1,ListLength),
nth(X,KnowledgeList,ListElement),
...?
Since you unify ExtractedList which [], it will always be empty. You should indeed use recursion. Here's a skeletal recursive program to get you started:
% base case: we can only extract 0 items from 0 items
extracted_knowledge([],[]).
% recursive case
extracted_knowledge([Item|Knowledge], Extracted) :-
extracted_knowledge(Knowledge, Extracted0),
% build Extracted from Extracted0 by adding Item,
% if it needs to be extracted