% -----------------------------------------------------------------------------
%  (C) Altran Praxis Limited
% -----------------------------------------------------------------------------
% 
%  The SPARK toolset is free software; you can redistribute it and/or modify it
%  under terms of the GNU General Public License as published by the Free
%  Software Foundation; either version 3, or (at your option) any later
%  version. The SPARK toolset is distributed in the hope that it will be
%  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
%  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
%  Public License for more details. You should have received a copy of the GNU
%  General Public License distributed with the SPARK toolset; see file
%  COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy of
%  the license.
% 
% =============================================================================


%-------------------------------------------------------------------------------
% RULE FAMILIES CONTAINED HEREIN :-
%
% inference       : simple inference rules (useful for subgoaling)
% eq              : equality substitution rule
% equiv           : equivalence substitution rule
% simplify        : simplification of expressions rule
% logic           : truth-table logic rules
% standardisation : standardisation rules
% unification     : top-level unification rules
%-------------------------------------------------------------------------------
% MODEL DECLARATIONS FOR THIS FILE :-
%
% rule_family inference:
%         X       requires [ X:any        ] &
%         X or Y  requires [ X:any, Y:any ] &
%         X and Y requires [ X:any, Y:any ] &
%         X -> Y  requires [ X:any, Y:any ] &
%         X <-> Y requires [ X:any, Y:any ].
%
% rule_family eq:
%         X requires [ X:any ].
%
% rule_family equiv:
%         X requires [ X:any ].
%
% rule_family simplify:
%         X requires [ X:any ].
%
% rule_family logic:
%         X requires [ X:any ].
%
% rule_family standardisation:
%         X requires [ X:any ].
%
% rule_family unification:
%         X requires [ X:any ].
%-------------------------------------------------------------------------------


/*** Standard INFERENCE Rules ***/

inference(1): X       may_be_deduced_from [ X ].
inference(2): X       may_be_deduced_from [ Y -> X, Y ].
inference(3): X or Y  may_be_deduced_from [ X ].
inference(4): X or Y  may_be_deduced_from [ Y ].
inference(5): X and Y may_be_deduced_from [ X, Y ].
inference(6): X -> Y  may_be_deduced_from [ not X ].
inference(7): X -> Y  may_be_deduced_from [ Y ].
inference(8): X <-> Y may_be_deduced_from [ X -> Y, Y -> X ].


/*** SUBSTITUTION rule for equality-substitution ***/

eq(1):    X may_be_replaced_by Y if [ X=Y, goal(X\=Y) ].


/*** SUBSTITUTION rule for equivalence-substitution ***/

EQUIV1:   X may_be_replaced_by Y if
                [ goal(nonvar(EQUIV1)),
                  goal(EQUIV1=equiv(1)),
                  X <-> Y,
                  goal(X\=Y) ].


/*** SIMPLIFY rule for simplification of expressions ***/

SIMPLIFY1:    X may_be_replaced_by Y if
                [ goal(nonvar(SIMPLIFY1)),
                  goal(SIMPLIFY1=simplify(1)),
                  goal(var(Y)),
                  goal(simplify(X, Y)),
                  goal(X \= Y) ].

SIMPLIFY2:    X may_be_replaced_by Y if
                [ goal(nonvar(SIMPLIFY2)),
                  goal(SIMPLIFY2=simplify(2)),
                  goal(novars(Y)),
                  goal(X \= Y),
                  goal(simplify(X, Z)),
                  goal(simplify(Y, Z)) ].


/*** LOGICAL DEDUCTION rule - only allowed by explicit call ***/

LOGIC1:     X may_be_deduced_from
                [ goal(nonvar(LOGIC1)),
                  goal(LOGIC1=logic(1)),
                  goal(try_deduce(X)) ].

LOGIC2:     X may_be_replaced_by Y if
                [ goal(nonvar(LOGIC2)),
                  goal(LOGIC2=logic(2)),
                  goal(novars(Y)),
                  goal(checktype(X,boolean)),
                  goal(try_deduce(X <-> Y)) ].


/*** STANDARDISATION rule - only allowed by explicit call ***/
STAND1:     X may_be_replaced_by Y if
                [ goal(nonvar(STAND1)),
                  goal(STAND1=standardisation(1)),
                  goal(novars(Y)),
                  goal(X\=Y),
                  goal(checktype(X,T)),
                  goal(norm_typed_expr(X,T,Z)),
                  goal(norm_typed_expr(Y,T,Z)) ].

STAND2:     X may_be_replaced_by Y if
                [ goal(nonvar(STAND2)),
                  goal(STAND2=standardisation(2)),
                  goal(var(Y)),
                  goal(checktype(X,T)),
                  goal(norm_typed_expr(X,T,Y)) ].

STAND3:     X may_be_deduced_from
                [ goal(nonvar(STAND3)),
                  goal(STAND3=standardisation(3)),
                  goal(norm_typed_expr(X,boolean,true)) ].


/*** UNIFICATION rules - only allowed by explicit call ***/
/* This rule family allows f(x1,...,xn)=f(y1,...,yn) to be deduced from
   x1=y1, ..., xn=yn (for n in 1..9).  unification(n) is for the case when
   f takes n arguments.  For any n, you can survive without these rules if
   you wish: simply prove f(x1,...,xn)=f(y1,...,yn) by contradiction, then
   establish contradiction by replacing each yi by xi (or vice versa), thereby
   gaining the hypothesis f(x1,...,xn)<>f(x1,...,xn), which gives false. */

UNIF1:     X = Y may_be_deduced_from
		[ goal(nonvar(UNIF1)),
		  goal(UNIF1=unification(1)),
		  goal(X =.. [F,X1]),
		  goal(Y =.. [F,Y1]),
		  X1 = Y1 ].

UNIF2:     X = Y may_be_deduced_from
		[ goal(nonvar(UNIF2)),
		  goal(UNIF2=unification(2)),
		  goal(X =.. [F,X1,X2]),
		  goal(Y =.. [F,Y1,Y2]),
		  X1 = Y1, X2 = Y2 ].

UNIF3:     X = Y may_be_deduced_from
		[ goal(nonvar(UNIF3)),
		  goal(UNIF3=unification(3)),
		  goal(X =.. [F,X1,X2,X3]),
		  goal(Y =.. [F,Y1,Y2,Y3]),
		  X1 = Y1, X2 = Y2, X3 = Y3 ].

UNIF4:     X = Y may_be_deduced_from
		[ goal(nonvar(UNIF4)),
		  goal(UNIF4=unification(4)),
		  goal(X =.. [F,X1,X2,X3,X4]),
		  goal(Y =.. [F,Y1,Y2,Y3,Y4]),
		  X1 = Y1, X2 = Y2, X3 = Y3, X4 = Y4 ].

UNIF5:     X = Y may_be_deduced_from
		[ goal(nonvar(UNIF5)),
		  goal(UNIF5=unification(5)),
		  goal(X =.. [F,X1,X2,X3,X4,X5]),
		  goal(Y =.. [F,Y1,Y2,Y3,Y4,Y5]),
		  X1 = Y1, X2 = Y2, X3 = Y3, X4 = Y4, X5 = Y5 ].

UNIF6:     X = Y may_be_deduced_from
		[ goal(nonvar(UNIF6)),
		  goal(UNIF6=unification(6)),
		  goal(X =.. [F,X1,X2,X3,X4,X5,X6]),
		  goal(Y =.. [F,Y1,Y2,Y3,Y4,Y5,Y6]),
		  X1 = Y1, X2 = Y2, X3 = Y3, X4 = Y4, X5 = Y5, X6 = Y6 ].

UNIF7:     X = Y may_be_deduced_from
		[ goal(nonvar(UNIF7)),
		  goal(UNIF7=unification(7)),
		  goal(X =.. [F,X1,X2,X3,X4,X5,X6,X7]),
		  goal(Y =.. [F,Y1,Y2,Y3,Y4,Y5,Y6,Y7]),
		  X1=Y1, X2=Y2, X3=Y3, X4=Y4, X5=Y5, X6=Y6, X7=Y7 ].

UNIF8:     X = Y may_be_deduced_from
		[ goal(nonvar(UNIF8)),
		  goal(UNIF8=unification(8)),
		  goal(X =.. [F,X1,X2,X3,X4,X5,X6,X7,X8]),
		  goal(Y =.. [F,Y1,Y2,Y3,Y4,Y5,Y6,Y7,Y8]),
		  X1=Y1, X2=Y2, X3=Y3, X4=Y4, X5=Y5, X6=Y6, X7=Y7, X8=Y8 ].

UNIF9:     X = Y may_be_deduced_from
		[ goal(nonvar(UNIF9)),
		  goal(UNIF9=unification(9)),
		  goal(X =.. [F,X1,X2,X3,X4,X5,X6,X7,X8,X9]),
		  goal(Y =.. [F,Y1,Y2,Y3,Y4,Y5,Y6,Y7,Y8,Y9]),
		  X1=Y1,X2=Y2,X3=Y3,X4=Y4,X5=Y5,X6=Y6,X7=Y7,X8=Y8,X9=Y9 ].
