%mathpiper,def="CanProve"

/* Small theorem prover for propositional logic, based on the
 * resolution principle.
 * Written by Ayal Pinkus, based on the simple theorem prover from "Prolog, Ivan Bratko, chapter 20"
 * Version 0.1 initial implementation.
 *
 *
 * Examples:
CanProve(( (a=>b) And (b=>c)=>(a=>c) ))  <-- True
CanProve(a  Or   Not a)                  <-- True
CanProve(True  Or  a)                    <-- True
CanProve(False  Or  a)                   <-- a
CanProve(a  And   Not a)                 <-- False
CanProve(a  Or b Or (a And b))           <-- a Or b
 */

 // <==> LogicSimplify(expr, 3)

/* CanProve tries to prove that the negation of the negation of
   the proposition is true. Negating twice is just a trick to
   allow all the simplification rules a la De Morgan to operate
 */
/*CanProve(_proposition)    <-- CanProveAux( Not CanProveAux( Not proposition));*/

CanProveAux(_proposition)    <-- LogicSimplify(proposition, 3);

CanProve(_proposition)      <-- CanProveAux( proposition );

%/mathpiper



%mathpiper_docs,name="CanProve",categories="User Functions;Propositional Logic"
*CMD CanProve --- try to prove statement
*STD
*CALL
	CanProve(proposition)

*PARMS

{proposition} -- an expression with logical operations

*DESC

MathPiper has a small built-in propositional logic theorem prover.
It can be invoked with a call to {CanProve}.

An example of a proposition is: "if a implies b and b implies c then
a implies c". MathPiper supports the following logical operations:

{Not} :     negation, read as "not"

{And}  :   conjunction, read as "and"

{Or}  :   disjunction, read as "or"

{=>}  : implication, read as "implies"

The abovementioned proposition would be represented by the following expression,

	( (a=>b) And (b=>c) ) => (a=>c)

MathPiper can prove that is correct by applying {CanProve}
to it:

In> CanProve(( (a=>b) And (b=>c) ) => (a=>c))
Result: True;

It does this in the following way: in order to prove a proposition $p$, it
suffices to prove that  $Not p$ is false. It continues to simplify  $Not p$
using the rules:

	Not  ( Not x)      --> x
(eliminate double negation),
	x=>y  -->  Not x  Or  y
(eliminate implication),
	Not (x And y)  -->  Not x  Or  Not y
(De Morgan's law),
	Not (x Or y) -->  Not x  And  Not y
(De Morgan's law),
	(x And y) Or z --> (x Or z) And (y Or z)
(distribution),
	x Or (y And z) --> (x Or y) And (x Or z)
(distribution),
and the obvious other rules, such as,
	True Or x --> True
etc.
The above rules will translate a proposition into a form

	(p1  Or  p2  Or  ...)  And  (q1  Or  q2
	   Or  ...)  And ...
If any of the clauses is false, the entire expression will be false.
In the next step, clauses are scanned for situations of the form:

	(p Or Y)  And  ( Not p Or Z) --> (Y Or Z)
If this combination {(Y Or Z)} is empty, it is false, and
thus the entire proposition is false.

As a last step, the algorithm negates the result again. This has the
added advantage of simplifying the expression further.

*E.G.

In> CanProve(a  Or   Not a)
Result: True;
In> CanProve(True  Or  a)
Result: True;
In> CanProve(False  Or  a)
Result: a;
In> CanProve(a  And   Not a)
Result: False;
In> CanProve(a  Or b Or (a And b))
Result: a Or b;
	

*SEE True, False, And, Or, Not
%/mathpiper_docs