I am trying to solve a problem where I need to evaluate the value of a binary expression tree.
tree_calc(Tree, Eval)
where Eval should hold the final result and Tree must be in the form:
tree(LeftNode, Operator, RightNode)
If I create the tree function as per the form above, how am I supposed to pass the results of the calculations back up the recursion if there isn't an empty variable to store the results?
My understanding is that an extra variable is always needed to store the result in.
Apologies in advance as I am sure I am misunderstanding something basic.
Thanks for your help.
In this context, tree isn't what you are calling a function, nor is it what Prolog would refer to as a predicate. tree(LeftNode, Operator, RightNode) is just a term that is used as a structure to represent the tree. So, for example, (2 + 3) * 4 would be represented by, tree(tree(2,+,3), *, 4). You would call your predicate with tree_calc(tree(tree(2,+,3),*,4), Eval) and expect that query to yield, Eval = 20. The term, tree/3 doesn't carry results in this case.
To give an example of how to access tree/3 in a predicate, here's a simple predicate that evaluates the simplest tree (so there's no recursion to tree leaves):
tree_calc(tree(L, Op, R), E) :-
% Neither L or R are of the form `tree/3`
compute(Op, L, R, E).
compute(+, L, R, E) :- E is L + R.
compute(*, L, R, E) :- E is L * R.
compute(-, L, R, E) :- E is L - R.
compute(/, L, R, E) :- E is L / R.
You can generalize compute/4:
compute(Op, L, R, E) :-
Exp =.. [Op, L, R],
E is Exp.
And you can call it like so:
| ?- tree_calc(tree(2,+,3), Eval).
Eval = 5
yes
For your more general case, you'll need to check L and R to see if they are a tree/3 structure themselves and recursively call tree_calc recursively if so.
Prolog is good at matching term patters. So if you check unification L = tree(LL, Op, LR) and it succeeds, that means L is a tree with left branch LL, operation Op, and right branch LR. You can play with this behavior at the Prolog prompt to see how it works:
| ?- Tree = tree(2, +, 3), Tree = tree(L, Op, R).
L = 2
Op = (+)
R = 3
Tree = tree(2,+,3)
yes
| ?- Tree = tree(2,+,tree(3,*,4)), Tree = tree(L, Op, R).
L = 2
Op = (+)
R = tree(3,*,4)
Tree = tree(2,+,tree(3,*,4))
yes
| ?- Tree = tree(2,+,tree(3,*,4)), Tree = tree(L, Op, R), R = tree(LR, OpR, RR).
L = 2
LR = 3
Op = (+)
OpR = (*)
R = tree(3,*,4)
RR = 4
Tree = tree(2,+,tree(3,*,4))
yes
| ?-
Related
Let's say I want to implement a predicate that 'returns' a list of all elements shared by a list of lists.
I can implement it as a one clause (looks bit ugly for logic programing):
shared_members(Members, Lists) :-
Lists = [] ->
Members = []
; findall(M, (maplist(member(M), Lists)), Members).
or as a set of clauses:
shared_members([], []). % possibly adding cut here to increase effciency
shared_members(Members, Lists) :-
findall(M, (maplist(member(M), Lists)), Members).
Which implementation is considered to be more efficient?
I know it depends on the Prolog implementation but maybe there is a general stand about efficiency of these cases.
In this case, you don't even need the first clause shared_member([], []). The findall/3 call will result in Members = [] if Lists = [].
The question is still interesting, though, and so we'll ignore this for now. You could run some stats to determine time-efficiency. Memory efficiency difference is negligible. The second approach given, however, is considered to be the canonical approach in Prolog. But they are also not equivalent in their behavior. The "if-else" in Prolog, as represented by p1 -> p2 ; p3 cuts removes the choice point after evaluation of p1. It's equivalent to p1, !, p2 ; p3.
Here's why this matters. I'll use a contrived example (which also does not require both clauses, but illustrates the point). I'll define a len/2 predicate that is true if the first argument is the length of the second:
len(0, []).
len(N, L) :- length(L, N).
Obviously, as in the case of the original problem, the first clause here is redundant, but it is important for this illustration. If I run this query, I get the following results:
| ?- len(N, [a,b,c]).
N = 3
yes
| ?- len(3, L).
L = [_,_,_]
yes
| ?- len(N, L).
L = []
N = 0 ? ;
L = []
N = 0 ? ;
L = [_]
N = 1 ? ;
L = [_,_]
N = 2 ? ;
L = [_,_,_]
N = 3 ?
Note that if both arguments are variable, it enumerates solutions. (Also, due to the redundant first clause, one of the solutions appears twice.)
Let's rewrite this predicate using "if-else":
len(N, L) :-
( L = []
-> N = 0
; length(L, N)
).
And we'll run it:
| ?- len(N, [a,b,c]).
N = 3
yes
So far, so good. But...
| ?- len(3, L).
no
| ?- len(N, L).
L = []
N = 0
yes
| ?-
Yikes! This is quite different. What happened?
In the second approach, ( L = [] -> N = 0 ; length(L, N) ) first attempts to unify L and []. If L is a variable, this succeeds with L = []. Since it succeeded, Prolog then attempts to unify N = 0. But with the query len(3, L), N is already bound to 3. So N = 0 fails and the entire clause fails.
Using the -> ; construct then, in this case, greatly reduces the generality of the implementation and yields incorrect results in some of the call scenarios.
Question
Is it possible to schedule a goal to be executed as soon as the length of a list is known / fixed or, as #false pointed out in the comments, a given argument becomes a [proper] list? Something along this line:
when(fixed_length(L), ... some goal ...).
When-conditions can be constructed using ?=/2, nonvar/1, ground/1, ,/2, and ;/2 only and it seems they are not very useful when looking at the whole list.
As a further detail, I'm looking for a solution that presents logical-purity if that is possible.
Motivation
I think this condition might be useful when one wants to use a predicate p(L) to check a property for a list L, but without using it in a generative way.
E.g. it might be the case that [for efficiency or termination reasons] one prefers to execute the following conjunction p1(L), p2(L) in this order if L has a fixed length (i.e. L is a list), and in reversed order p2(L), p1(L) otherwise (if L is a partial list).
This might be achieved like this:
when(fixed_length(L), p1(L)), p2(L).
Update
I did implement a solution, but it lacks purity.
It would be nice if when/2 would support a condition list/1. In the meantime, consider:
list_ltruth(L, Bool) :-
freeze(L, nvlist_ltruth(L, Bool)).
nvlist_ltruth(Xs0, Bool) :-
( Xs0 == [] -> Bool = true
; Xs0 = [_|Xs1] -> freeze(Xs1, nvist_ltruth(Xs1, Bool))
; Bool = false
).
when_list(L, Goal_0) :-
nvlist_ltruth(L, Bool),
when(nonvar(Bool),( Bool == true, Goal_0 )).
So you can combine this also with other conditions.
Maybe produce a type error, if L is not a list.
when(nonvar(Bool), ( Bool == true -> Goal_0 ; sort([], L) ).
Above trick will only work in an ISO conforming Prolog system like SICStus or GNU that produces a type_error(list,[a|nonlist]) for sort([],[a|nonlist]), otherwise replace it by:
when(nonvar(Bool),
( Bool == true -> Goal_0 ; throw(error(type_error(list,L), _)).
Many systems contain some implementation specific built-in like '$skip_list' to traverse lists rapidly, you might want to use it here.
I've managed to answer my own question, but not with a pure solution.
Some observations
The difficulty encountered in writing a program that schedules some goal for execution when the length of a list is precisely known is the fact that the actual condition might change. Consider this:
when(fixed_length(L), Goal)
The length of the list might change if L is unbound or if the last tail is unbound. Say we have this argument L = [_,_|Tail]. L has a fixed width only if Tail has a fixed width (in other words, L is a list if T is a list). So, a condition that checks Tail might be the only thing to do at first. But if Tail becomes [a|Tail2] a new when-condition that tests if Tail2 is a list is needed.
The solution
1. Getting the when-condition
I've implemented a predicate that relates a partial list with the when-condition that signals when it might become a list (i.e. nonvar(T) where T is the deepest tail).
condition_fixed_length(List, Cond):-
\+ (List = []),
\+ \+ (List = [_|_]),
List = [_|Tail],
condition_fixed_length(Tail, Cond).
condition_fixed_length(List, Cond):-
\+ \+ (List = []),
\+ \+ (List = [_|_]),
Cond = nonvar(List).
2. Recursively when-conditioning
check_on_fixed_length(List, Goal):-
(
condition_fixed_length(List, Condition)
->
when(Condition, check_on_fixed_length(List, Goal))
;
call(Goal)
).
Example queries
Suppose we want to check that all elements of L are a when the size of L is fixed:
?- check_on_fixed_length(L, maplist(=(a), L)).
when(nonvar(L), check_on_fixed_length(L, maplist(=(a), L))).
... and then L = [_,_|Tail]:
?- check_on_fixed_length(L, maplist(=(a), L)), L = [_,_|L1].
L = [_G2887, _G2890|L1],
when(nonvar(L1), check_on_fixed_length([_G2887, _G2890|L1], maplist(=(a), [_G2887, _G2890|L1]))).
?- check_on_fixed_length(L, maplist(=(a), L)), L = [_,_|L1], length(L1, 3).
L = [a, a, a, a, a],
L1 = [a, a, a].
Impurity
conditon_fixed_length/2 is the source of impurity as it can be seen from the following query:
?- L = [X, Y|Tail], condition_fixed_length(L, Cond), L = [a,a].
L = [a, a],
X = Y, Y = a,
Tail = [],
Cond = nonvar([]).
?- L = [X, Y|Tail], L = [a, a], condition_fixed_length(L, Cond).
false.
Hello is there any way to separate a list in Prolog into two other lists, the first includes everything before an element and the second everything after the element. For example
A=[1,2,3,5,7,9,0] and element=5
the two lists should be
A1=[1,2,3] and A2=[7,9,0]
I don't care about finding the element just what to do next
it's easy as
?- Elem = 5, A = [1,2,3,5,7,9,0], append(A1, [Elem|A2], A).
edit to explain a bit...
append/3 it's a relation among 3 lists.
It's general enough to solve any concatenation on proper lists - when not there are circular arguments.
The comparison it's a plain unification, that take place on second argument. That must be a list beginning with Elem. Prolog list constructor syntax is [Head|Tail]. To make unification succeed, Elem must match the Head.
Here's an alternative method, illustrating how to handle it with list recursion:
split([E|T], E, [], T).
split([X|T], E, [X|LL], LR) :-
X \== E,
split(T, E, LL, LR).
Or better, if your Prolog supports dif/2:
split([E|T], E, [], T).
split([X|T], E, [X|LL], LR) :-
dif(X, E),
split(T, E, LL, LR).
Examples:
| ?- split([1,2,3,4,5], 3, L, R).
L = [1,2]
R = [4,5] ? ;
no
| ?- split([1,2,3,4,5], 5, L, R).
L = [1,2,3,4]
R = [] ? ;
(1 ms) no
| ?- split([1,2,3,4,5], 1, L, R).
L = []
R = [2,3,4,5] ? ;
no
| ?-
It is a sort of specialized twist on append/3 as CapelliC showed.
I need to implement nonrecusrsive scalar projection for lists. List is a recursive data structure in Prolog. Is that also possible? I try to implement like:
scalar(T,U,S) :- scalar(T,U,S,0).
scalar([X|T],[Y|U],S,M):- repeat,M1 = M + S, S1=X*Y,fail.
repeat.
repeat:-repeat.
But it wrong because I not pass M1 S1.
It's so difficult to understand after C coding. Prolog iteration clause is recursive but with "Tail" recursion. It's mean we have right answer on the end of recursion. Recursive clause need to bactrack to up to get the answer.
Nonrecursive method
scal(L1,L2,R):- scal(L1,L2,0,R).
scal([A|L1],[B|L2],F,R):- F1 is (F + A*B),scal(L1,L2,F1,R).
scal([],[],F,F).
Recursive method
scal([],[],0).
scal([A|L1],[B|L2],R) :- scal(L1, L2, R1), R is (R1+A*B).
Assuming you mean the scalar projection of vector A onto B given by:
s = (A dot B)/|B|
Then you could do it this way:
scalar(A, B, S) :-
dot_product(A, B, P),
magnitude(B, M),
S is P / M.
dot_product(A, B, P) :-
maplist(mult, A, B, M),
sum_list(M, P). % In SWI prolog, this would be sumlist
magnitude(V, M) :-
maplist(sq, V, S), % Or maplist(mult, V, V, S)
sum_list(S, SumS),
M is sqrt(SumS).
mult(X, Y, M) :- M is X * Y.
sq(X, S) :- S is X * X.
Need to make a predicate, fill(L,X,N), where L is a list formed containing N elements X. If N <= 0 or N != length of L, L should be an empty list.
Here's what I've done, I've never been able to get the if, else.. structure working correctly in Prolog:
fill(L,X,N) :-
((N =< 0) ->
L = [];
length(L,I),
((N =\+= I) ->
L = [];
fill2(L,X,N))).
fill2([H|T],X,N2) :-
NewN = N2 - 1,
H = X,
fill2(T,X,NewN).
I also have a simpler version, that works except when N != length of L
fill(L,_,N) :-
N =< 0,
L = [].
fill([H|T],X,N) :-
NewN = N - 1,
H = X,
fill(T,X,NewN).
So, for example, fill(L,20,4) returns L = [20,20,20,20], but fill([20,20,20],X,2) doesn't return L = [].
You are misunderstanding how Prolog is meant to be used. Predicates are not exactly functions, so they can't return. If you bind an argument to an instantiated variable:
?- fill([a,a,a], a, 4).
fail
the only sensible thing is that Prolog tells you, "this is not correct". Anyway, in this example:
?- fill([b,b], a, 3).
What should happen? Should the list be [a,a,a], or should the second and third argument be b and 2?
A very simple fill:
fill([], _, 0).
fill([X|Xs], X, N) :- succ(N0, N), fill(Xs, X, N0).
It will fail if not used properly, but you should make clear how it needs to be used.
A note: try to avoid explicit unification in the body of the predicate definition.