% -----------------------------------------------------------------------------
%  (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.
% 
% =============================================================================


/*** DEDUCE -- top-level checker command ***/
deduce :-
        (
           command_arg(expression, EXPRN)
        ;
           prompt_user('DEDUCE -- Type formula to deduce.', 'DEDUCE -- Formula? '),
           rread(EXP),
           parse_expression(EXP, EXPRN)
        ),
        (
           EXPRN=c#N,
           conc(N,FORMULA)
        ;
           novars(EXPRN),                                       /* CFR009 */
           checktype(EXPRN, boolean),                           /* CFR009 */
           FORMULA=EXPRN
        ),
        (
           command_arg(hyplist, HYPLIST)
        ;
           prompt_user('Hypotheses to be used? '),
           rread(HYPLIST),
           check_hyplist(HYPLIST)
        ),
        build_formula(FORMULA, HYPLIST, F1),
        (
           try_deduce(F1),
           !,
           write('*** '),
           print(F1),
           nl,
           write('*** '),
           print(FORMULA),
           write(' by logical deduction'),
           nl,
           add_new_hyp(FORMULA,1)
        ;
           !,
           write('*** FAILED'),
           nl,
           fail
        ),
        (
           EXPRN=c#N,
           done(N)
        ;
           true
        ), !.


/*** BUILD_FORMULA(C,HYPS,F) - create a "HYPS -> C" formula, F ***/
build_formula(F,[],F) :-
   !.

build_formula(F,[N],X -> F) :-
   !,
   hyp(N,X), !.

build_formula(F,[N|T],(H and Y) -> F) :-
   build_formula(F,T,Y -> F),
   hyp(N,H), !.


/*** TRY_DEDUCE(F) - deduce formula F by truth-table means if possible ***/
try_deduce(F) :-
   var_in(F,V),
   !,
   subst_vbl(V,false,F,F1),
   try_deduce(F1),
   subst_vbl(V,true,F,F2),
   try_deduce(F2), !.

try_deduce(F) :-
   simplify(F,true), !.


/*** VAR_IN(FORM,ATF) - find an atf ATF in formula FORM if possible ***/
var_in(not F,V) :- var_in(F,V).
var_in(X and Y,V) :- (var_in(X,V) ; var_in(Y,V)).
var_in(X or Y,V) :- (var_in(X,V) ; var_in(Y,V)).
var_in(X -> Y,V) :- (var_in(X,V) ; var_in(Y,V)).
var_in(X <-> Y,V) :- (var_in(X,V) ; var_in(Y,V)).
var_in(V,V) :- logic_free(V), V\=true, V\=false.


/*** LOGIC_FREE(F) - succeeds if no connectives in F, i.e. if F is an atf ***/
logic_free(not _) :- !, fail.
logic_free(_ or _) :- !, fail.
logic_free(_ and _) :- !, fail.
logic_free(_ -> _) :- !, fail.
logic_free(_ <-> _) :- !, fail.
logic_free(_).


/*** SUBST_VBL(V,X,OLD,NEW) - substitute all V in OLD by X to get NEW ***/
subst_vbl(V,X,V,X) :- !.
subst_vbl(_V,_X,Y,Y) :-
    atomic(Y),
    !.
subst_vbl(V,X,F,F1) :-
    F=..[OP|Args],
    subst_vbl_list(V,X,Args,Args1),
    F1=..[OP|Args1],
    !.


/*** SUBST_VBL_LIST(V,X,OL,NL) - substitute all V in OL by X to get NL ***/
subst_vbl_list(V,X,[A],[A1]) :- subst_vbl(V,X,A,A1), !.
subst_vbl_list(V,X,[A|Args],[A1|Args1]) :-
    subst_vbl(V,X,A,A1),
    !,
    subst_vbl_list(V,X,Args,Args1),
    !.
%###############################################################################
%END-OF-FILE
