Courses/CS 332L/Expression evaluation

From CSWiki

Jump to: navigation, search

[edit] Version 1

The following program will evaluate arithmetic expressions in + and *.

?- eval((3+4)*5, R).

R = 35
?- eval(3+4*5, R).

R = 23
?- eval((3+4)*x, R).

R = 7*x
% eval(+Expression, ?Result)

% If the input is of the form E1 + E2
eval(E1 + E2, Result) :-
  !,
  eval(E1, V1),
  eval(E2, V2),
  perform_op(+, V1, V2, Result).
  
% If the input is of the form E1 * E2
eval(E1 * E2, Result) :-
  !,
  eval(E1, V1),
  eval(E2, V2),
  perform_op(*, V1, V2, Result).
  
% Otherwise just return the expression unevaluated.
eval(X, X).
  
% To perform addition on V1 and V2,
% make sure they are both numbers
% and add them.
perform_op(+, V1, V2, Result) :-
  number(V1), 
  number(V2),
  !,
  Result is V1 + V2.
  
% Same for multiplication
perform_op(*, V1, V2, Result) :-
  number(V1), 
  number(V2),
  !,
  Result is V1 * V2.

% If the two arguments are not both numbers
% put them together into an expression.
% Use the univ operator:  =..
perform_op(Op, V1, V2, Expr) :- 
  !,
  Expr =.. [Op, V1, V2].

[edit] Version 2

This version looks up variables in a list of bindings.

?- eval(3+4*x, [x = 5], R).

R = 23
?- eval(z+4*x, [x = 5, z = 10], R).

R = 30
?- eval(z+a*x, [x = 5, z = 10, a = 3], R).

R = 25
?- eval(z+z*x, [x = 5, z = 10, a = 3], R).

R = 60
?- eval(z+w*(x+y), [x = 5, z = 10, y = 3], R).

R = 10+w*8
% eval(+Expression, +Bindings, ?Result)

eval(X, Bindings, V) :-
  member(X = V, Bindings),
  !.

eval(X, _Bindings, X) :-
  atom(X),  
  !.
  
eval(E1 + E2, Bindings, Result) :-
  !,
  eval(E1, Bindings, V1),
  eval(E2, Bindings, V2),
  perform_op(+, V1, V2, Result).
  
eval(E1 * E2, Bindings, Result) :-
  !,
  eval(E1, Bindings, V1),
  eval(E2, Bindings, V2),
  perform_op(*, V1, V2, Result).
  
eval(X, _Bindings, X).
  
perform_op(+, V1, V2, Result) :-
  number(V1), 
  number(V2),
  !,
  Result is V1 + V2.
  
perform_op(*, V1, V2, Result) :-
  number(V1), 
  number(V2),
  !,
  Result is V1 * V2.
  
perform_op(Op, V1, V2, Expr) :- 
  !,
  Expr =.. [Op, V1, V2].

[edit] Version 3

Use univ (=..) in both directions.

% eval(+Expression, ?Result)

eval(X, Bindings, V) :-
  member(X = V, Bindings),
  !.

eval(X, _Bindings, X) :-
  atom(X),  
  !.
  
eval(E1 + E2, Bindings, Result) :-
  !,
  eval(E1, Bindings, V1),
  eval(E2, Bindings, V2),
  perform_op(+, V1, V2, Result).
  
eval(E1 * E2, Bindings, Result) :-
  !,
  eval(E1, Bindings, V1),
  eval(E2, Bindings, V2),
  perform_op(*, V1, V2, Result).
  
eval(X, _Bindings, X).
  

% If the two arguments are  both numbers
% put them together into an expression.
% Use the univ operator:  =.. Then
% evaluate the expression using "is".
perform_op(Op, V1, V2, Result) :-
  number(V1), 
  number(V2),
  !,
  Expr =.. [Op, V1, V2],
  Result is Expr.
    
% If the two arguments are not both numbers
% put them together into an expression.
% Use the univ operator:  =..
perform_op(Op, V1, V2, Expr) :- 
  !,
  Expr =.. [Op, V1, V2].

[edit] Version 4

Use univ for eval also. Get subtraction, division, exponentiation, integer division, modulo and all the other 2-argument arithmetic functions described in section 4.26.3 of the online manual for "free."

?- eval(max(1, z/(w*(x-y)^y)), [w = 1, x = 5, z = 10, y = 3], R).

R = 1.25
% eval(+Expression, +Bindings, ?Result)


eval(X, Bindings, V) :-
  member(X = V, Bindings),
  !.
  
eval(X, _Bindings, X) :-
  atomic(X),  
  !.
  
eval(Expr, Bindings, Result) :-
  % current_arithmetic_function/1 succeeds if Expr 
  % unifies with a defined arithmetic function.
  current_arithmetic_function(Expr),
  Expr =.. [Op, E1, E2],
  !,
  eval(E1, Bindings, V1),
  eval(E2, Bindings, V2),
  perform_op(Op, V1, V2, Result).
  
eval(Expr, _Bindings, _Result) :-
  Expr =.. [Op, _E1, _E2],
  !,
  write('Not a defined binary arithmetic function: '),
  writeln(Op),
  fail.

eval(X, _Bindings, X).
  

perform_op(Op, V1, V2, Result) :-
  number(V1), 
  number(V2),
  !,
  Expr =.. [Op, V1, V2],
  Result is Expr.
    
perform_op(Op, V1, V2, Expr) :- 
  !,
  Expr =.. [Op, V1, V2].
Personal tools