I want to calculate the area of a polygon in Prolog.
The area of a polygon is given by the formula:
| {(x1*y2-y1*x2) + (x2*y3-y2*x3) + .... + (xn*y1 - yn*x1)}/2 |
where (x1,y1),(x2,y2)....(xn,yn) are the points of the polygon.
this is my attempt to implement the formula in Prolog:
area(Points,Area):-areaAcc(Points,0,Area).
areaAcc([(X1,Y1),(X2,Y2)|List], Acc, Area):-
areaAcc2([(X1,Y1),(X2,Y2)|List], Acc, Area, (X1,Y1)).
areaAcc2([(X1,Y1),(X2,Y2)|List],Acc,Area,(FirstX,FirstY)):-
NewAcc is (X1*Y2-Y1*X2) + Acc,
areaAcc2([(X2,Y2)|List], NewAcc, Area, (FirstX,FirstY)).
areaAcc2([(Xm,Ym),(Xn,Yn)|[]],Acc,Area,(FirstX,FirstY)):-
Area is abs((Acc + (Xn*FirstY - Yn*FirstX))/2).
but when I run :
area([(4,10),(9,7),(11,2),(2,2),(4,10)],Area).
I get Area = 51.5 instead of the right answer: Area = 45.5.
can anyone recognize my mistake?
If you simplify the base case (the last clause), and pass a not closed polygon, the result is correct
areaAcc2([(Xn,Yn)],Acc,Area,(FirstX,FirstY)):-
Area is abs((Acc + (Xn*FirstY - Yn*FirstX))/2).
yields
?- area([(4,10),(9,7),(11,2),(2,2)], A).
A = 45.5
Otherwise, implementing with library support it's easier:
area_poly(Points, A) :-
aggregate_all(sum(E),
(append(_, [(X1,Y1),(X2,Y2)|_], Points), E is (X1*Y2-Y1*X2)), A2),
A is abs(A2/2).
Note that is misses the last sum of the formula, yet it yields the correct value, because we pass an already closed polygon...
?- area_poly([(4,10),(9,7),(11,2),(2,2),(4,10)], A).
A = 45.5.
edit aggregate_all/3 is available in SWI-Prolog and YAP (shared source code, I think), and - from Internet search - on SICStus Prolog. I think all these derived from Quintus Prolog. About implementation, I sketched lag, but of course reusing library code is better...
It's been a while since I sweated over this sort of problem. But working from
http://mathworld.wolfram.com/PolygonArea.html
http://www.artofproblemsolving.com/Wiki/index.php/Shoelace_Theorem
http://www.mathopenref.com/coordpolygonarea2.html
This is my take on a solution (assuming that the points are properly ordered):
area_polygon( [] , _ ) :- ! , fail . % not a polygon.
area_polygon( [P1] , _ ) :- ! , fail . % 1 single point is not a polygon.
area_polygon( [P1,P2] , _ ) :- ! , fail . % 2 points is a line segment and not a polygon.
area_polygon( [P1,P2,P3|Ps] , A ) :- % now we're getting somehere: 3 points is a triangle.
append( [P1,P2,P3|Ps] , [P1] , X ) , % append the first point to the list so it ends where it started.
area_polygon( X , 0.0 , A ) % call the worker predicate, seeding its accumulator with 0.0
.
area_polygon( [] , T , A ) :- A is abs( T ) / 2.0 .
area_polygon( [(X1,Y1),(X2,Y2)|Ps] , T , A ) :-
T1 is T + (X1+X2) * (Y2-Y1) ,
area_polygon( [(X2,Y2)|Ps] , T1 , A )
.
You might not need the call to append/3 depending on how you represent the polygon.
Related
I need to write a rule that replaces every negative number from a list with 0. This is my code:
neg_to_0(L,R) :-
(
nth1(X,L,E),
E<0,
replace(E,0,L,L2),
neg_to_0(L2,R2)
) ;
R = L.
replace(_, _, [], []).
replace(O, R, [O|T], [R|T2]) :- replace(O, R, T, T2).
replace(O, R, [H|T], [H|T2]) :- H \= O, replace(O, R, T, T2).
I have a rule "replace" which takes the element that needs to be replaced with 0 and returns the new list, but it stops after the rule replaces the values and return the new list, so i made the function to recall the main function with the new data so it can replace the other negative values :
replace(E,0,L,L2),
neg_to_0(L2,R2)
);
R = L.
On the last iteration, when it could not detect any negative numbers, i made it so that it saves the last correct list, but i only get back a "True" instead of the correct list.
Your code seems... awfully complex.
You seem to be trying to write procedural (imperative) code. Prolog is not an imperative language: one describes "truth" and lets Prolog's "inference engine" figure it out. And, pretty much everything is recursive by nature in Prolog.
So, for your problem, we have just a few simple cases:
The empty list [], in which case, the transformed list is... the empty list.
A non-empty list. [N|Ns] breaks it up into its head (N) and its tail (Ns). If N < 0, we replace it with 0; otherwise we keep it as-is. And then we recurse down on the tail.
To replace negative numbers in a list with zero, you don't need much more than this:
%
% negatives_to_zero/2 replaces negative numbers with 0
%
negatives_to_zero( [] , [] ) . % nothing to do for the empty list
negatives_to_zero( [N|Ns] , [M|Ms] ) :- % for a non-empty list,
M is max(N,0), % get the max of N and 0,
negatives_to_zero(Ns,Ms). % and recurse down on the tail
You can easily generalize this, of course to clamp numbers or lists of numbers, and constrain them to lie within a specified range:
%--------------------------------------------------------------------------------
% clamp( N , Min, Max, R )
%
% Constrain N such that Min <= N <= Max, returning R
%
% Use -inf (negative infinity) to indicate an open lower limit
% Use +inf (infinity) or +inf (positive infinity) to indicate an open upper limit
% -------------------------------------------------------------------------------
clamp( Ns , -inf , +inf , Ns ) .
clamp( N , Min , Max , R ) :- number(N) , clamp_n(N,Min,Max,R).
clamp( Ns , Min , Max , Rs ) :- listish(Ns) , clamp_l(Ns,Min,Max,Rs).
clamp_n( N , _ , _ , R ) :- \+number(N), !, R = N.
clamp_n( N , Min , Max , R ) :- T is max(N,Min), R is min(T,Max).
clamp_l( [] , _ , _ , [] ) .
clamp_l( [X|Xs] , Min , Max , [Y|Ys] ) :- clamp_n(X,Min,Max,Y), clamp(Xs,Min,Max,Ys).
listish( T ) :- var(T), !, fail.
listish( [] ) .
listish( [_|_] ) .
How can I implement a binary predicate ,computes the depth of the first argument as its second argument.
Remark: The depth of variables, numbers, function symbols of arity 0, and predicate symbols of arity 0 is 0.
The depth of a term or an atomic formula is the maximum depth of all subterms or subformulas
plus 1.
?-depth((p(X,a(q(Y)),c), X).
X=3
My effort: i implemented max_list predicate but i could not develop my code more.
This works in one direction I think.
depth(A,0):-
\+compound(A).
depth(A,B):-
compound(A),
A =.. [_H|T],
maplist(depth,T,Depths),
max_list(Depths,Max),
B is Max +1.
Here's a simple straightforward approach. It treats lists as if they are a flat data structure (even through in reality, they are a deeply nested ./2 structure.
depth( T , D ) :- % to compute the depth of an arbitrary term...
depth(T,0,D) % - call the worker predicate with the accumulator seeded to zero.
.
depth( T , CM , MD ) :- var(T) , ! , MD is CM+1 . % an unbound term is atomic : its depth is the current depth + 1 .
depth( T , CM , MD ) :- atomic(T) , ! , MD is CM+1 . % an atomic term is...atomic : its depth is the current depth + 1 .
depth( [X|Xs] , CD , MD ) :- % we're going to treat a list as a flat data structure (it's not really, but conceptually it is)
findall( D , (member(T,[X|Xs),depth(T,0,D)) , Ds ) , % - find the depth of each item in the list
max(Ds,N) , % - find the max depth for a list item.
MD is CD + 1 + N % - the max depth is the current depth + 1 (for the containing list) + the max depth of a list item
. %
depth( T , CD , MD ) :- % for other compound terms...
T \= [_|_] , % - excluding lists,
T =.. [_|Args] , % - decompose it into its functor and a list of arguments
depth(Args,0,N) , % - compute the depth of the argument list
MD is CD + N % - the max depth is the current depth plus the depth of the argument list.
. % Easy!
max( [N|Ns] , M ) :- max( Ns , N , M ) . % to compute the maximum value in a list, just call the worker predicate with the accumulator seeded to zero.
max( [] , M , M ) . % when we hit the end of the list, we know the max depth.
max( [N|Ns] , T , M ) :- % otherwise,
( N > T -> T1 = N ; T1 = T ) , % - update the current high water mark
max(Ns,T1,M) % - recurse down.
. % Easy!
A list is really just a term, with some syntax sugar that eases most common use. So, my depth/2 definition, a 1-liner given compound/1, aggregate/3 and arg/3 availability, answers like:
?- depth(a(a,[1,2,3],c),X).
X = 4.
?- depth(p(X,a(q(Y)),c), X).
X = 3.
edit I will leave you the pleasure to complete it: fill the dots
depth(T, D) :- compound(T) -> aggregate(max(B), P^A^(..., ...), M), D is M+1 ; D = 0.
edit apparently, no pleasure in filling the dots :)
depth(T, D) :-
compound(T)
-> aggregate(max(B+1), P^A^(arg(P, T, A), depth(A, B)), D)
; D = 0.
Alright, so I'm working on a homework assignment, this is supposed to be a four function calculator taking in a list of strings [three, times, two] for example, and output a number. It only considers the numbers from one to twenty in its initial list. The following code is all my own. It runs up to the point where it takes in the last item in the list (that I've been using to test it, but the problem is for any of the inputs) in numberize and then will not unify.
calculator([twenty, times, three, plus, five, divided_by, two],Total).
I know the solution must be an easy one, but I'm not experienced enough yet in Prolog to figure it out.
My question is: how do I fix my code so that it runs the way I want it to?
calculator(X,Total):-
numberize(X,L),
reverse(L,L1),
func(L1,Total).
numberize([X,Y|T],L):-
str2num(X,X1),
numberize(T,[Y,X1|L]).
numberize([X],L):-
str2num(X,X1),
%somehow add on the X1 to the front of L without any errors and it's golden
/*Whatever that line is*/L is [X1|L].
func([X1,X,Z1|T], Total):-
(X == times, times(X1,Z1,Ttl));
(X == plus, plus(X1,Z1,Ttl));
(X == divided_by, divided_by(X1,Z1,Ttl));
(X == minus, minus(X1,Z1,Ttl)),
func([Ttl|T],Total).
str2num(one, X):- X is 1.
str2num(two, X):- X is 2.
str2num(three, X):- X is 3.
str2num(four, X):- X is 4.
str2num(five, X):- X is 5.
str2num(six, X):- X is 6.
str2num(seven, X):- X is 7.
str2num(eight, X):- X is 8.
str2num(nine, X):- X is 9.
str2num(ten, X):- X is 10.
str2num(eleven, X):- X is 11.
str2num(twelve, X):- X is 12.
str2num(thirteen, X):- X is 13.
str2num(fourteen, X):- X is 14.
str2num(fifteen, X):- X is 15.
str2num(sixteen, X):- X is 16.
str2num(seventeen, X):- X is 17.
str2num(eighteen, X):- X is 18.
str2num(nineteen, X):- X is 19.
str2num(twenty, X):- X is 20.
times(X,Y,Prod):-
Prod is X*Y.
plus(X,Y,Sum):-
Sum is X+Y.
divided_by(X,Y,Quo):-
Quo is X/Y.
minus(X,Y,Dif):-
Dif is X-Y.
Small style remark: use facts for str2num/2: just str2num(one, 1). instead of str2num(one, X):- X is 1., etc. Added benefit is that now the predicate can be used both ways, like str2num(Word, 1).
As for the main question, you are almost correct.
The whole numberize predicate can be as simple as this:
numberize([X], [N]) :-
str2num(X, N).
numberize([X, Op | T], [N, Op | NewT]) :-
str2num(X, N),
numberize(T, NewT).
Let's test it:
?- numberize([one, plus, two, minus, three], L).
L = [1, plus, 2, minus, 3]
But you need to remove call to reverse from calculator:
calculator(X,Total):-
numberize(X,L),
func(L,Total).
You have almost correct func predicate. One problem: in Prolog you should have braces around disjunction:
func([X1,X,Z1|T], Total):-
(
X == times, times(X1,Z1,Ttl)
;
X == plus, plus(X1,Z1,Ttl)
;
X == divided_by, divided_by(X1,Z1,Ttl)
;
X == minus, minus(X1,Z1,Ttl)
),
func([Ttl|T],Total).
The second problem: when your list reduced to one number (think how func([1,plus,2], Total) will call func([3], Total) the predicate will fail. All you need to fix this is the rule that Total of a list with just 1 number is the number itself:
func([X], X).
Now the whole thing works:
?- calculator([one, plus, two], Total).
Total = 3
?- calculator([one, plus, two, minus, four], Total).
Total = -1
The way I'd approach this is to start by defining a grammar for arithmetic expressions. The "standard" way of defining grammars is left-recursive. Since prolog does recursive descent parsing, the grammar can't be left-recursive. Every iteration has to remove something from the token stream, lest you go in to the death spiral of infinite recursion. Here's my non-left recursive grammar for a 4-banger calculator like yours:
expression : multiplicative_expression '+' expression
| multiplicative_expression '-' expression
| multiplicative_expression
;
multiplicative_expression : factor '*' multiplicative_expression
| factor '/' multiplicative_expression
| factor '%' multiplicative_expression
| factor
;
factor : '-' value
| '(' expression ')'
| value
;
value : number
Once we have the grammar, the prolog code pretty much writes itself. First, some facts to work with. We need a list of operators and their types (along with the equivalent prolog operator:
operator( plus , additive , '+' ) .
operator( minus , additive , '-' ) .
operator( times , multiplicative , '*' ) .
operator( divided_by , multiplicative , '/' ) .
operator( modulo , multiplicative , 'mod' ) .
And a words-to-numbers-map:
number_word( zero , 0 ).
number_word( one , 1 ).
...
number_word( nineteen , 19 ) .
number_word( twenty , 20 ) .
And we need our interface predicate, calculate/2:
%--------------------------------------------------------------------
% we can calculate a result if Expr is a valid expression
% that consumes all the available tokens in the token stream
%---------------------------------------------------------------------
calculate(Expr,Result) :- expr( Expr , Result , [] ) .
That invokes the "start symbol" of the grammar, expr/3. expr/3 (and the other worker predicates) are pretty much direct restatements of the grammar, with the additional requirement that they need to hand back the unconsumed portion of the input token stream. The parse is successful, if, at the end of the day, the token stream is empty:
expr( Xs , Result , Tail ) :- % per the grammar, an expression is
mult( Xs , LHS , [Sym|X1] ) , % - a multiplicative expression, followed by
operator( Sym , additive , Op ) , % - an infix additive operator, followed by
expr( X1 , RHS , X2 ) , % - another expression
Term =.. [Op,LHS,RHS] , % * in which case, we construct the proper prolog structure
Result is Term , % * in which case, we evaluate the result in the usual way
Tail = X2 % * and unify any remaining tokens with the Tail
. %
expr( Xs , Result , Tail ) :- % alternatively, an expression is simply
mult( Xs , Result , Tail ) % - a single multiplicative expression
. %
The worker predicate for multiplicative terms, mult/3 is pretty much identical — a direct restatement of the grammar:
mult( Xs , Result, Tail ) :- % a multiplicative expression is
factor( Xs , LHS , [Sym|X1] ) , % - a factor, followed by
operator( Sym , multiplicative , Op ) , % - an infix multiplicative operator, followed by
mult( X1 , RHS , X2 ) , % - another factor
evaluate( Op , LHS , RHS , Result ) , % * in which case, we evalute the result in the usual way
Tail = X2 % * and unify any remaining tokens with the tail
. %
mult( Xs , Result , Tail ) :- % alternatively, a multiplicative expression is simply
factor( Xs , Result , Tail ) % - a single factor
. %
Finally, since we're not wrassling with higher-precedence operations like unary minus, exponentiation or parentheses that change operator precedence, a factor is simply a number word that can be converted into an integer value:
factor( [X|Xs] , Value , Xs ) :- % a factor is simply
number_word(X,Value) % - a number value (in our case, a word that we convert to an integer)
.
and a simple helper to evaluate each subexpression as needed:
evaluate( Op , LHS , RHS , Result ) :- % to evaluate an infix term,
Term =.. [Op,LHS,RHS] , % - use univ to convert to the correct prolog structure, and
Result is Term % evaluate it as the result
. %
Hello I have to solve some prolog problems with lists but i can't figure it out how these work.
I have to add "1" after every even element in a list, and to make the difference of 2 lists.
I know this seems easy, in other language like java or c# i would make it very easy, but prolog it's giving me headaches.
Please help me :|
Edited to note the clarified problem statement ("even item" meaning the item's value is even (rather than the item's ordinal position within the list):
insert_one_after_even_items( [] , [] ). % if the source list is exhaused, we're done.
insert_one_after_even_items( [X|Xs] , [X,1|Ys] ) :- % otherwise,
0 is X mod 2 , % - if the number is even, prepend it and a 1 to the result list, and
insert_one_after_even_items( Xs , Ys ) % - recurse down.
. %
insert_one_after_even_items( [X|Xs] , [X|Ys] ) :- % otherwise,
1 is X mod 2 , % - if the number is odd, prepend it to the result list, and
insert_one_after_even_items( Xs , Ys ) % - recurse down.
. % Easy!
For your second problem, producing the difference between two lists, are you talking about set differences? If so, given two sets A and B, are you talking about the relative difference (all elements of A that do not exist in B), or the absolute difference (all elements of either A or B that do not exist in both sets)?
To solve the relative set difference problem (Find all members of A that do not also exist in B), you can use the built-in member/2 predicate:
relative_difference( [] , _ , [] ) . % if the source list is exhausted, we're done
relative_difference( [A|As] , Bs , R ) :- % if the source list is non-empty, and
member(A,Bs) , % - the current A is an element of B,
! , % - we insert a deterministic cut (no backtracking)
relative_difference( As , Bs , R ) % - and recurse down, discarding the current A
. %
relative_difference( [A|As] , Bs , [A|R] ) :- % if the source list is non-empty (and A is not an element of B due to the cut inserted earlier)
relative_difference( As , Bs , R ) % we simply add A to the result list and recurse down.
.
One thing you will note here: we are building the result list in all of these examples is built from a variable. The tail of the list is unbound (and passed as the new result to the next recursive call, where it either become a new list node or, at the very end, the empty list.
This has the effect of
building the list in order (rather than in reverse order).
if the result was bound on the initial call, unification against the expected result occurs item by item as the recursion proceeds, which means
execution is short-circuited when the first unification failure occurs.
If your prolog implementation doesn't have member/2 as a built in, it's easy enough to implement. Something like this ought to do it:
member(X,[X|T]) :- ! . % A hit! cut and succeed.
member(X,[_|T]) :- member(X,T) . % ... and a miss. Just recurse down on the tail.
I made two different Fibonacci functions, the first one worked perfectly. Then I tried to simplify it in an intuitive way. I thought it would work but for some reason it says ERROR: Out of local stack every time I test it.
Working version:
fibonacci(0,0).
fibonacci(1,1).
fibonacci(N,F) :- N1 is N-1, N2 is N-2, fibonacci(N1,F1), fibonacci(N2,F2), F is F1+F2.
Not working version:
fibonacci(0,0).
fibonacci(1,1).
fibonacci(N,F) :- fibonacci(N-1,F1), fibonacci(N-2,F2), F is F1+F2.
Could someone explain me what is the problem with the second one? Thanks.
Your problem is that in your second one you are recursively calling fibonacci/2 with the term N-1 instead of an integer whose value is N-1.
So, for example if you where calling fibonacci(3, F) it would enter in the third clause and call fibonacci(3-1, F1) instead of fibonacci(2, F1). It would then enter again in the third clause and call fibonacci(3-1-1, F1) and so on.
Note that Prolog uses special operator is to perform arithmetic operations.
The first example is right.
Wouldn't this be simpler? Define fibonnaci\3 such that the first two arguments are the two 'seed' elements (normally 1 and 1, though they can be any two positive integers). The third argument is the computed value of that element of the series.
All you have to do is maintain a sliding window as you recurse along the fibonnaci sequence, thus:
%
% the public interface predicate
%
fibonnaci( A , _ , A ) . % 1. return the first element of the series
fibonnaci( _ , B , B ) . % 2. return the second element of the series
fibonnaci( A , B , C ) :- % 3. all subsequent values are the sum of
fib_body( A , B , C ) . % the preceding two elements in the series.
%
% the 'private' worker predicate
%
fib_body( A , B , X ) :- % 1. first, compute the next element of the series
X is A + B . % as the sum of the preceding two elements.
fib_body( A , B , X ) :- % 2. on backtracking, shift our window
C is A + B , % and recurse down to get the next element
fib_body( B , C , X ) . % in the series.