Possible helper rules:
This problem does not require a lot of code, but it does require some careful
thinking about
noVars( t ).
noVars( f ).
noVars( [_, L, R] ) :- noVars( L ), noVars( R ).
Note that you'll need another rule in order to handle not, as well.
getVar( N, N ) :- number( N ).
getVar( [_, L, R], N ) :- getVar( L, N ); (noVars(L), getVar( R, N )).
Note that you'll need another rule here to handle the
unary logical expressions that begin with
not.
?- getVar([ifthen, 1, 2], X).
X = 1 ;
No
Although this may seem like a problem, once you substitute a truth
value for 1, the next call to getVar will
happily return the 2. And, did we mention it's much faster?
subst( 1, t, [and, [not, 1], 1], NewExpr ).
NewExpr = [and, [not, t], t]
subst( 1, t, [and, [not, 1], 2], NewExpr ).
NewExpr = [and, [not, t], 2]
eval( Expr, TorF ) would be used only when Expr has no variables -- in fact, you could avoid the explicit noVars check, if this predicate were only called appropriately by taut and/or unsat. Note that any no-variable expression must be either true t or false f.
Then, eval( Expr, t ) would indicate that the no-variable expression Expr evaluates to true. Similarly, eval( Expr, f ) would indicate that Expr evaluates to false. Recursion is important here -- in fact, mutual recursion between the t and f cases. However, be sure that each recursive or mutually-recursive call gets closer to one of the base cases -- otherwise, it could run forever!
If you'd like to use this, here is an example rule that
may help get you started:
eval( [not, SubExpr], t ) :- eval( SubExpr, f ).
In addition, keep in mind that you can use number(N), a predicate built-in to Prolog that makes sure N is bound to a number.