Eclipse Prolog: How to make a program that solves boolean expressions (replace variables so that the expression is true)

Viewed 128

So, I have this program that (using TKEclipse) allows me to query boolean expressions and answers with "Yes" or "No", depending on if the statement is true:

:-op(450,yfx,and).
:-op(500,yfx,or).
:-op(500,yfx,nor).
:-op(450,yfx,nand).
:-op(500,yfx,xor).

:-op(400,fy,--).
:-op(600,xfx,==>).



--Arg1:-not(Arg1).
 
Arg1 ==> Arg2 :- --Arg1 or Arg2.

Arg1 and Arg2 :- Arg1, Arg2.

Arg1 or _Arg2 :- Arg1.
_Arg1 or Arg2 :-Arg2.

Arg1 xor Arg2 :- Arg1, --Arg2.
Arg1 xor Arg2 :- --Arg1, Arg2.

Arg1 nor Arg2 :- --(Arg1 or Arg2).
Arg1 nand Arg2 :- --(Arg1 and Arg2).


t. 
f:-!,fail.

For example:

Q:t and t 
A:Yes

Q:t and f
A:No

Now I want to make the program accept variables using the predicate "bool_solve(Expr)". For example:

Q:bool_solve(X and t)
A:X = t
Yes
Q:bool_solve(X and Y)
A:X = t
Y = t
Yes
Q:bool_solve(X or Y)
A:X = t
Y = t
Yes
'more'
A:X = t
Y = f
Yes
'more'
A:X = f
Y = t
Yes
'more'
No

I know how to replace the variables with a specific value (like t) using this code:

bool_solve(Expr):-
    term_variables(Expr,Vars),
    findall(X,X=t, Vars).

term_variables is built-in and finds all the variables in an expression. I know how to unify with the result of the findall with the Expr variables, but I cannot evaluate the Expr. I tried calling it, but it does not work (failed instantiation).

TL;DR: I want to replace the "Goal" (X=t) of the findall predicate so that it evaluates the Expr, replacing all the variables with t or f.

Thank you in advance.

1 Answers

Instead of findall(X,X=t, Vars)

you could use: sentences(Vars), where the predicate sentences/1 is defined such:

sentences([]).
sentences([t|T]):- sentences(T).
sentences([f|T]):- sentences(T).

The predicate bool_solve/1 might be defined by

bool_solve(Expr):-
    term_variables(Expr,Vars),
    sentences(Vars),
    call(Expr).

An alternative is:

bool_solve(Expr):-
    term_variables(Expr,Vars),
    sentences(Vars),
    Expr.

In swi-Prolog, this seems to work:

?- bool_solve(X ==> Y), write(X), write(' '), write(Y), nl, fail.
t t
f t
f t
f f
false.

?- bool_solve(X and Y), write(X), write(' '), write(Y), nl, fail.
t t
false.

?- bool_solve(X or Y), write(X), write(' '), write(Y), nl, fail.
t t
t t
t f
f t
false.

I used this kind of question to make the output look similar to a truth table, so it is easier to check whether it is correct.


Edit:

To visualize what the predicate sentences/1 does, you may use this predicate:

show_instantiations(Expr):-
    term_variables(Expr,Vars),
    sentences(Vars),
    write(Expr), nl.

Now you can ask questions like the following:

?- show_instantiations(--X).
--t
X = t ;
--f
X = f.

?- show_instantiations(--X and X).
--t and t
X = t ;
--f and f
X = f.

?- show_instantiations(--X and Y or X).
--t and t or t
X = Y, Y = t ;
--t and f or t
X = t,
Y = f ;
--f and t or f
X = f,
Y = t ;
--f and f or f
X = Y, Y = f.

You'll get a nicer output, of course, by asking questions like:

?- show_instantiations(--X and Y or X), fail.
--t and t or t
--t and f or t
--f and t or f
--f and f or f
false.

?- show_instantiations(X ==> Y), fail.
t==>t
t==>f
f==>t
f==>f
false.
Related