From c300bc395fb987f7ded64c17bce5c966c0279442 Mon Sep 17 00:00:00 2001 From: filliatr Date: Thu, 1 Feb 2001 08:35:21 +0000 Subject: - coqc : option -image - coqmktop : manquaient des -I - tauto : rétablissement du vieux tauto en attendant la stabilité du nouveau - correction d'un bug de Simpl avec Fix (découvert dans preuve FTA) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@1304 85f007b7-540e-0410-9357-904b9bb8a0f7 --- tactics/tauto.ml4 | 1950 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1944 insertions(+), 6 deletions(-) (limited to 'tactics') diff --git a/tactics/tauto.ml4 b/tactics/tauto.ml4 index f181957f3..0415bae4d 100644 --- a/tactics/tauto.ml4 +++ b/tactics/tauto.ml4 @@ -100,6 +100,7 @@ let intuition_main () = and t_simplif = tacticIn simplif in <:tactic<$t_simplif;$t_axioms Orelse Auto with *>> +(*i let compute = function | None -> interp <:tactic> | Some id -> @@ -107,24 +108,1961 @@ let compute = function interp <:tactic> let reduction = Tacticals.onAllClauses (fun ido -> compute ido) +i*) + +let unfold_not_iff = function + | None -> interp <:tactic> + | Some id -> + let ast_id = nvar (string_of_id id) in + interp <:tactic> + +let reduction_not_iff = Tacticals.onAllClauses (fun ido -> unfold_not_iff ido) (* As a simple heuristic, first we try to avoid reduction both in *) (* tauto and intuition *) let tauto = (tclTHEN (init_intros ()) - (tclORELSE - (interp (tauto_main ())) - (tclTHEN reduction (interp (tauto_main ())))) - ) + (tclORELSE + (interp (tauto_main ())) + (tclTHEN reduction_not_iff (interp (tauto_main ())))) + ) let intuition = tclTHEN (init_intros ()) (tclORELSE (interp (intuition_main ())) - (tclTHEN reduction (interp (intuition_main ()))) + (tclTHEN reduction_not_iff (interp (intuition_main ()))) ) - +(*FIXME let _ = hide_atomic_tactic "Tauto" tauto let _ = hide_atomic_tactic "Intuition" intuition +*) + + +(****************************************************************************) +(* VIEUX TAUTO RÉTABLI EN ATTENDANT QUE LE NOUVEAU TAUTO SOIT STABLE *) +(* COUPER TOUT CE QUI SUIT QUAND CE SERA LE CAS *) +(****************************************************************************) + +(* Autor: Cesar A. Munnoz H *) + +open Pp +open Util +open Names +(* open Generic *) +open Term +open Sign +open Environ +open Declare +open Tacmach +open Reduction +open Tacticals +open Tactics +open Pattern +open Hipattern +open Auto +(* Chet's code *) +open Proof_trees +open Clenv +open Pattern + +(* Faut-il comparer le corps des définitions de l'environnement ? *) +let hlset_subset hls1 hls2 = + List.for_all + (fun (_,_,e) -> List.exists + (fun (_,_,e') -> eq_constr (body_of_type e) (body_of_type e')) + hls2) + hls1 + +let hlset_eq hls1 hls2 = + hlset_subset hls1 hls2 & hlset_subset hls2 hls1 + +let eq_gls g1 g2 = + eq_constr (pf_concl g1) (pf_concl g2) & hlset_eq (pf_hyps g1) (pf_hyps g2) + +let gls_memb bTS g = List.exists (eq_gls g) bTS + +let gls_add g bTS = + if gls_memb bTS g then error "backtrack in tauto"; + g::bTS + +let classically cltac = function + | (Some _ as cls) -> (tclTHEN (cltac cls) (clear_clause cls)) + | None -> cltac None + +let module_mark = ["Logic"] +(* patterns *) +let mmk = make_module_marker ["Prelude"] +let false_pattern_mark = put_pat mmk "False" +let true_pattern_mark = put_pat mmk "True" +let and_pattern_mark = put_pat mmk "(and ?1 ?2)" +let or_pattern_mark = put_pat mmk "(or ?1 ?2)" +let eq_pattern_mark = put_pat mmk "(eq ?1 ?2 ?3)" +let pi_pattern = put_pat mmk "(x : ?)((?1)@[x])" +let imply_pattern = put_pat mmk "?1 -> ?2" +let atomic_imply_bot_pattern = put_pat mmk "?1 -> ?2" +let iff_pattern_mark = put_pat mmk "(iff ?1 ?2)" +let not_pattern_mark = put_pat mmk "(not ?1)" +(* squeletons *) +(* +let imply_squeleton = put_squel mmk "?1 -> ?2" +let mkIMP a b = soinstance imply_squeleton [a;b] +*) +let mkIMP a b = mkProd (Anonymous, a, b) + +let false_pattern () = get_pat false_pattern_mark +let true_pattern () = get_pat true_pattern_mark +let and_pattern () = get_pat and_pattern_mark +let or_pattern () = get_pat or_pattern_mark +let eq_pattern () = get_pat eq_pattern_mark +let iff_pattern () = get_pat iff_pattern_mark +let not_pattern () = get_pat not_pattern_mark + +let is_atomic m = + (not (is_conjunction m) || + (is_disjunction m) || + (is_matching (get_pat pi_pattern) m) || + (is_matching (not_pattern ()) m)) + +(* Steps of the procedure *) + +(* 1. A,Gamma |- A *) +let dyck_hypothesis id = exact_check (mkVar id) + +(* 2. False,Gamma |- G *) +let dyck_absurdity_elim = contradiction_on_hyp + +(*3. A,B,Gamma |- G + --------------- + A/\B,Gamma |- G + *) +let dyck_and_elim = compose (classically dAnd) in_some + +(*4. Gamma |- A Gamma |- B + ----------------------- + Gamma |- A /\ B + *) +let dyck_and_intro = (dAnd None) + + +(*5. A,Gamma |- G B,Gamma|- G + --------------------------- + A\/B,Gamma |- G + *) + +let dyck_or_elim = compose (classically (dorE false)) in_some + +(*6. Gamma |- A + ---------- + Gamma |- A\/B + *) +let dyck_or_introleft = (dorE false) + + +(*7. Gamma |-B + --------- + Gamma |- A\/B + *) +let dyck_or_introright = (dorE true) + + +(*8. A,Gamma |- B + -------------- + Gamma |- A -> B + *) +let dyck_imply_intro = (dImp None) + + +(*9. + B,A,Gamma |- G + -------------- + A->B,A,Gamma |- G (A Atomique) + *) + +let atomic_imply_step cls gls = + begin try + let mvb = matches (get_pat atomic_imply_bot_pattern) (clause_type cls gls) in + if not (is_atomic (List.assoc 1 mvb)) then + error "atomic_imply_step" + with PatternMatchingFailure -> error "atomic_imply_step" end; + (tclTHENS (dImp cls) ([clear_clause cls;assumption])) gls + +let dyck_atomic_imply_elim = compose (atomic_imply_step) in_some + +(*10. + C ->(D-> B),Gamma |- G + ----------------------- + (C/\D)->B,Gamma |- G + *) + +let and_imply_step cls gls = + try + match matches (get_pat imply_pattern) (clause_type cls gls) with + | [(1,a);(2,b)] -> + let l = match match_with_conjunction a with + | Some (_,l) -> l + | None -> error "and_imply_step" + in + (tclTHENS (cut_intro (List.fold_right mkIMP l b)) + [clear_clause cls ; + (tclTHENS (tclTHEN (tclDO (List.length l) intro) (dImp cls)) + [assumption; + (tclTHEN (dAnd None) assumption)])]) gls + | _ -> anomaly "Inconsistent pattern-matching" + with PatternMatchingFailure -> error "and_imply_step" + +let dyck_and_imply_elim = compose (and_imply_step) in_some + +(*11. + C->B,D->B,Gamma |-G + -------------------- + (C\/D)->B,Gamma |- G +*) + +let or_imply_step cls gls = + try + match matches (get_pat imply_pattern) (clause_type cls gls) with + | [(1,a);(2,b)] -> + let l = match match_with_disjunction a with + | Some (_,l) -> l + | None -> error "or_imply_step" + in + (tclTHENS (cut_in_parallel (List.map (fun x -> (mkIMP x b)) l)) + (clear_clause cls:: + (List.map + (fun i -> (tclTHENS (tclTHEN intro (dImp cls)) + [assumption ; + (tclTHEN (one_constructor i []) assumption)])) + (interval 1 (List.length l))))) gls + | _ -> anomaly "Inconsistent pattern-matching" + with PatternMatchingFailure -> error "or_imply_step" + +let dyck_or_imply_elim = compose (or_imply_step) in_some + +(*12. +B,Gamma|- G D->B,Gamma |- C->D +---------------------------------- +(C->D)->B,Gamma |- G +*) + +let back_thru_2 id = + applist(mkVar id,[mkMeta (new_meta());mkMeta (new_meta())]) + +let back_thru_1 id = + applist(mkVar id,[mkMeta(new_meta())]) + +let exact_last_hyp = onLastHyp (fun h -> exact_no_check (mkVar (out_some h))) + +let imply_imply_bot_pattern = put_pat mmk "(?1 -> ?2) -> ?3" + +let imply_imply_step cls gls = + let h0 = out_some cls in (* (C->D)->B *) + try + match matches (get_pat imply_imply_bot_pattern) (clause_type cls gls) with + | [(1,c);(2,d);(3,b)] -> + tclTHENS (cut_intro b) + [clear_clause cls; (* B |- G *) + tclTHENS (cut_intro (mkIMP (mkIMP d b) (mkIMP c d))) + [onLastHyp + (fun h1opt (*(D->B)->(C->D)*) -> + let h1 = out_some h1opt in + (tclTHENS (refine (back_thru_1 h0)) + [tclTHENS + (tclTHEN intro (* C *) (refine (back_thru_2 h1))) + [tclTHENS + (tclTHEN intro (* D *) (refine (back_thru_1 h0))) + [tclTHEN intro (* C *) assumption]; + exact_last_hyp]])); + (tclTHEN (clear_clause cls) (intro)) + ] + ] gls + | _ -> anomaly "Inconsistent pattern-matching" + with PatternMatchingFailure -> error "imply_imply_bot_step" + +let dyck_imply_imply_elim = compose (imply_imply_step) in_some + +(*14. + B,Gamma |-G + -------------------- + True->B,Gamma |- G +*) + +let true_imply_step cls gls = + try + match matches (get_pat imply_pattern) (clause_type cls gls) with + | [(1,a);(2,b)] -> + let l = match match_with_unit_type a with + (* match_with_unit_type retournait un constr list option avec un seul + element dans la liste; maintenant il renvoie un constr option *) + (* Some (_::l) -> l *) + | Some _ -> [] + | None -> error "true_imply_step" + in + let h0 = out_some cls in + (tclTHENS (cut_intro b) + [(clear_clause cls); + (tclTHEN (apply(mkVar h0)) (one_constructor 1 []))]) gls + | _ -> anomaly "Inconsistent pattern-matching" + with PatternMatchingFailure -> error "true_imply_step" + +let dyck_true_imply_elim = compose (true_imply_step) in_some + +(* Chet's original algorithm +let rec prove g = + tclCOMPLETE + ((tclORELSE + ((tclORELSE + ((tclORELSE + ((tclORELSE + ((tclORELSE + ((tclORELSE + ((tclORELSE + ((tclORELSE + ((tclORELSE + ((tclORELSE + ((tclORELSE + ((tryAllHyps (clauseTacThen ((comp(dyck_hypothesis) (out_some))) prove))) + ((tryAllHyps (clauseTacThen ((comp(dyck_absurdity_elim) (out_some))) prove))))) + ((tryAllHyps (clauseTacThen ((comp(dyck_and_elim) (out_some))) prove))))) + ((tryAllHyps (clauseTacThen ((comp(dyck_or_elim) (out_some))) prove))))) + ((tryAllHyps (clauseTacThen ((comp(dyck_atomic_imply_elim) (out_some))) prove))))) + ((tryAllHyps (clauseTacThen ((comp(dyck_and_imply_elim) (out_some))) prove))))) + ((tryAllHyps (clauseTacThen ((comp(dyck_or_imply_elim) (out_some))) prove))))) + ((tryAllHyps (clauseTacThen ((comp(dyck_imply_imply_elim) (out_some))) prove))))) + (((tclTHEN (dyck_and_intro) (prove)))))) + (((tclTHEN (dyck_or_introleft) (prove)))))) + (((tclTHEN (dyck_or_introright) (prove)))))) + (((tclTHEN (dyck_imply_intro) (prove)))))) g + +*) + +(* Cesar's code *) + +let trans x = ([],Nametab.sp_of_id CCI (id_of_string x)) + +let flat_map f = + let rec flat_map_f = function + | [] -> [] + | x::l -> f x @ flat_map_f l + in + flat_map_f + +type formula = + | FVar of string + | FAnd of formula*formula + | FOr of formula*formula + | FImp of formula*formula + | FEqu of formula*formula + | FNot of formula + | FEq of formula*formula*formula + | FPred of constr (* Predicado proposicional *) + | FFalse + | FTrue + (* La siguiente no puede aparecer en una formula de entrada *) + (* Representa una formula atomica cuando aparece en un principal de una + regla *) + | FLis of formula list (* Lista de formulas *) + | FAto of string (* Formula atomica *) + | FLisfor of string (* Variable para una lista de formulas *) + (* En el antecedente se llama GAMA, + en el sucedente DELTA *) + +(* Terminos en calculo lambda *) +type termino = + | TVar of string + | TApl of formula*formula*termino*termino + | TFun of string*formula*termino + | TPar of formula*formula*termino*termino + | TInl of formula*formula*termino + | TInr of formula*formula*termino + | TFst of formula*formula*termino + | TSnd of formula*formula*termino + | TCase of formula list * termino list + | TZ of formula * termino + | TExi of string + | TRefl of formula * formula (*Reflexividad de la igualdad *) + | TSim of formula * formula * formula * termino + (*Simetria de la igualdad *) + | TTrue + (* Los siguientes terminos se usan solamente en las sustituciones *) + | TSum of termino*termino (* Suma de terminos *) + | TLis of termino list (* Lista de terminos *) + | TLister of string (* Variable para una lista de terminos *) + (* En el antecendete se llama Gama, + en el sucedente Delta *) + | TZero of formula (* Milagro *) + +(* Es una formula asociada con un termino del calculo lambda, o los + multiconjuntos Gama y Delta *) +type formulaT = termino*formula + +(* La primera componente es el antecedente, la segunda es sucedente *) +type sequente = formulaT list * formulaT list + +(* Substitucion de variable por una formula *) +type subsF = (string*formula) list + +(* Substitucion de variable por un lambda termino *) +type subsT = (string*termino) list + +type regla = { + tip: string; (* Tipo de la formula principal *) + heu: bool; (* Si es una regla heuristica o no *) + ant: bool; (* Si principal es antecedente o sucedente *) + pri: formulaT;(* Formula principal de la regla *) + pre: sequente list; (* Premisas de la regla *) + res: sequente;(* Restricciones para la aplicacion de una regla*) + def: subsT; (* Definicion de los terminos del lado derecho *) + sub: subsT; (* Substitucion que se aplica al lado derecho de la + conclusion para obetener el lambda termino *) + ren: string list; (* Variables que se deben renombrar *) + vardelta:bool; (* Si se usa la variable proposicional DELTA *) + ssi:bool; (* Si la regla es reversible o no *) + rendelta: string list } (* Renombramientos de delta *) + (* Note que si Res = A |- B, entonces la conclusion de la regla es + A,Gama,Pri' |- B, Pri'',Delta + Si ant = true Pri'= Pri + Si ant =false Pri''=Pri*) + +(* Substitucion Formula Termino para aplicar una regla *) +type sFT = { + sReg : regla ref; (*Apuntador a la regla *) + sFor : subsF; (*Substitucion de Formulas *) + sGam : formulaT list; (* Lista de formulas de Gamma *) + sDel : formulaT list; (* Lista de formulas de Delta *) + sRen : (string*subsT) list; (* Renombramientos de variables *) + sTer : subsT; (* Susbstitucion de terminos *) + sDef : subsT } (* Definicion de terminos *) + +type subsFT = SNil | SCons of sFT + +type reglaSub = RNil | RCons of (sFT*regla list*formulaT list*sequente) + +(* De un arbol de demostracion *) +type nodo = { + seq: sequente ref; (* Sequente que se resuelve *) + reg: regla ref; (* Regla usada para resolver *) + sd: subsT; (* Substitucion que define los lambda terminos *) + st: subsT } (* Substitucion que calcula el lambda termino *) + +(* Arbol de demostracion *) +type arbol = Nil | Cons of arbol * nodo * arbol + +(* Demostracion *) +(* Si el secuente es valido Arb es un arbol de demostracion y Lisbut + es vacio, sino Lisbut es un contexto en el cual Arb es valido *) +type demostracion = { arb : arbol; lisbut : formulaT list } + +(* Definicion de excepcion para rescribir terminos *) +exception NoAplica +exception TacticFailure + +(* ------------------ Sistema de Gentzen Intuisionista -------------------*) +(* Gama,Delta son metavariables de conjuntos de reglas + A,B son variables de formulas *) + +let gama = (TLister "Gama",FLisfor "GAMA") +let delta = (TLister "Delta",FLisfor "DELTA") +let delta' = (TLister "Delta'",FLisfor "DELTA") +let delta'' = (TLister "Delta''",FLisfor "DELTA") + +let curry(a,b,c,a_0,b_0,p) = TFun(a_0,a,TFun(b_0,b,TApl(FAnd(a,b),c,p, + TPar(a,b,TVar a_0,TVar b_0)))) +let left(a,b,c,a_0,p) = TFun(a_0,a,TApl(FOr(a,b),c,p,TInl(a,b,TVar a_0))) +let right(a,b,c,b_0,p) = TFun(b_0,b,TApl(FOr(a,b),c,p,TInr(a,b,TVar b_0))) +let imp2(a,b,c,a_0,b_0,p) = TFun(a_0,a,TApl(FImp(b,a),c,p,TFun(b_0,b,TVar a_0))) + +(* Regla inicial *) +(* / A,Gama |- A,Delta *) +let inic = { + tip="inic"; + heu=false; + ant=true; + pri= TVar "#x",FAto "#A"; + pre=[]; + res=([],[TVar "#x",FVar "#A"]); + def=["Delta",TZero(FLisfor "DELTA")]; + sub=[]; + ren=["#x"]; + vardelta = true; + ssi = true; + rendelta=[] } + +(* Regla l_false *) +(* / Gama,False |- Delta *) +let l_false = { + tip="false"; + heu=false; + ant=true; + pri= TVar "#x",FFalse; + pre=[]; + res=([],[]); + def=["Delta",TZ(FLisfor "DELTA",TVar "#x")]; + sub=[]; + ren=["#x"]; + vardelta = true; + ssi = true; + rendelta=[]} + +(* Regla r_true *) +(* / Gama |- True,Delta *) +let r_true = { + tip="true"; + heu=false; + ant=false; + pri= TTrue,FTrue; + pre=[]; + res=([],[]); + def=["Delta",TZero(FLisfor "DELTA")]; + sub=[]; + ren=[]; + vardelta = true; + ssi = true; + rendelta=[]} + +(* Regla l_and *) +(* A,B,Gama |- Delta / FAnd(A,B),Gama |- Delta *) +let l_and = { + tip="l_and"; + heu=false; + ant=true; + pri= TVar "#xy",FAnd(FVar "#A",FVar "#B"); + pre=[[TVar "#x",FVar "#A";TVar "#y",FVar "#B";gama],[delta]]; + res=([],[]); + def=[]; + sub=["#x",TFst(FVar "#A",FVar "#B",TVar "#xy"); + "#y",TSnd(FVar "#A",FVar "#B",TVar "#xy")]; + ren=["#x";"#y"]; + vardelta = false; + ssi = true; + rendelta=[]} + +(* Regla r_and *) +(* Gama |- A,Delta' Gama |- B,Delta'' / Gama |- A/\B,Delta *) +let r_and = { + tip="r_and"; + heu=false; + ant=false; + pri= TPar(FVar "#A",FVar "#B",TVar "#x",TVar "#y"), + FAnd(FVar "#A",FVar "#B"); + pre=[[gama],[TVar "#x",FVar "#A";delta'];[gama], + [TVar "#y",FVar "#B";delta'']]; + res=([],[]); + def=["Delta",TSum(TLister "Delta'",TLister "Delta''")]; + sub=[]; + ren=["#x";"#y"]; + vardelta = true; + ssi = true; + rendelta=["Delta'";"Delta''"]} + +(* Regla l_or *) +(* A,Gama |- Delta' B,Gama |- Delta'' / A\/B,Gama |- Delta *) +let l_or = { + tip="l_or"; + heu=false; + ant=true; + pri= TVar "#xy",FOr(FVar "#A",FVar "#B"); + pre=[[TVar "#x",FVar "#A";gama],[delta']; + [TVar "#y",FVar "#B";gama],[delta'']]; + res=([],[]); + sub=[]; + def=["Delta", TCase([FVar "#A";FVar "#B";FLisfor "DELTA"], + [TFun("#x",FVar "#A",TLister "Delta'"); + TFun("#y",FVar "#B",TLister "Delta''"); + TVar "#xy"])]; + ren=["#x";"#y";"#xy"]; + vardelta = true; + ssi = true; + rendelta=["Delta'";"Delta''"]} + +(* Regla r_or *) +(* Gama |- A,B,Delta / Gama |- A\/B,Delta *) +let r_or = { + tip="r_or"; + heu=false; + ant=false; + pri= TSum(TInl(FVar "#A",FVar "#B",TVar "#x"), + TInr(FVar "#A",FVar "#B",TVar "#y")), + FOr(FVar "#A",FVar "#B"); + pre=[[gama], + [TVar "#x",FVar "#A";TVar "#y",FVar "#B";delta]]; + res=([],[]); + sub=[]; + def=[]; + ren=["#x";"#y"]; + vardelta = false; + ssi = true; + rendelta=[]} + +(* Regla l_imp1 *) +(* A,B,Gama |- Delta / A->B,A,Gama |- Delta (A es un atomo) *) +let l_imp1 = { + tip="l_imp1"; + heu=false; + ant=true; + pri= TVar "#p",FImp(FAto "#A",FVar "#B"); + pre=[[TVar "#x",FVar "#B";gama], + [delta]]; + res=([TVar "#a",FVar "#A"],[]); + def=[]; + sub=["#x",TApl(FVar "#A",FVar "#B",TVar "#p",TVar "#a")]; + ren=["#x"]; + vardelta = false; + ssi = true; + rendelta=[]} + +(* Regla l_imp2 *) +(* C->(D->B),Gama |- Delta / C/\D->B,Gama |- Delta *) +let l_imp2 = { + tip="l_imp2"; + heu=false; + ant=true; + pri= TVar "#p",FImp(FAnd(FVar "#C",FVar "#D"),FVar "#B"); + pre=[[TVar "#x",FImp(FVar "#C",FImp(FVar "#D",FVar "#B"));gama], + [delta]]; + res=([],[]); + def=[]; + sub=["#x",curry(FVar "#C",FVar "#D",FVar "#B","#c","#d",TVar "#p")]; + ren=["#x";"#c";"#d"]; + vardelta = false; + ssi = true; + rendelta=[]} + +(* Regla l_imp3 *) +(* C->B,D->B,Gama |- Delta / C\/D->B,Gama |- Delta *) +let l_imp3 = { + tip="l_imp3"; + heu=false; + ant=true; + pri= TVar "#p",FImp(FOr(FVar "#C",FVar "#D"),FVar "#B"); + pre=[[TVar "#x",FImp(FVar "#C",FVar "#B");TVar "#y", + FImp(FVar "#D",FVar "#B");gama], + [delta]]; + res=([],[]); + def=[]; + sub=["#x",left(FVar "#C",FVar "#D",FVar "#B","#c",TVar "#p"); + "#y",right(FVar "#C",FVar "#D",FVar "#B","#d",TVar "#p")]; + ren=["#x";"#y";"#c";"#d"]; + vardelta = false; + ssi = true; + rendelta=[]} + +(* Regla l_imp4 *) +(* D->B,Gama |- C->D,Delta B,Gama |- Delta / (C->D)->B,Gama |- Delta *) +let l_imp4 = { + tip="l_imp4"; + heu=false; + ant=true; + pri= TVar "#p",FImp(FImp(FVar "#C",FVar "#D"),FVar "#B"); + pre=[[TVar "#x",FVar "#B";gama],[delta]; + [TVar "#z",FImp(FVar "#D",FVar "#B");gama],[TVar "#y", + FImp(FVar "#C",FVar "#D")]]; + res=([],[]); + def=[]; + sub=["#x", + TApl(FImp(FVar "#C",FVar "#D"),FVar "#B",TVar "#p", + TApl(FVar "#D",FVar "#B", + TFun("#z",FImp(FVar "#D",FVar "#B"),TVar "#y"), + imp2(FVar "#D",FVar "#C",FVar "#B","#d","#c",TVar "#p")))]; + ren=["#x";"#y";"#z";"#d";"#c"]; + vardelta = false; + ssi = false; + rendelta=[]} + +(* Regla l_imp5 *) +(* (A->False)->B,Gama |- Delta / Not(A)->B,Gama |- Delta *) +let l_imp5 = { + tip="l_imp5"; + heu=false; + ant=true; + pri= TVar "#x",FImp(FNot(FVar "#A"),FVar "#B"); + pre=[[TVar "#x",FImp(FImp(FVar "#A",FFalse),FVar "#B");gama], + [delta]]; + res=([],[]); + def=[]; + sub=[]; + ren=["#x"]; + vardelta = false; + ssi = true; + rendelta=[]} + +(* Regla l_imp6 *) +(* (C->D/\D->C)->B,Gama |- Delta / (C<->D)->B,Gama |- Delta *) +let l_imp6 = { + tip="l_imp6"; + heu=false; + ant=true; + pri= TVar "#x",FImp(FEqu(FVar "#C",FVar "#D"),FVar "#B"); + pre=[[TVar "#x", + FImp(FAnd(FImp(FVar "#C",FVar "#D"), + FImp(FVar "#D",FVar "#C")),FVar "#B");gama],[delta]]; + res=([],[]); + def=[]; + sub=[]; + ren=["#x"]; + vardelta = false; + ssi = true; + rendelta=[]} + +(* Regla l_imp7 *) +(* B,Gama |- Delta / True->B,Gama |- Delta *) +let l_imp7 = { + tip="l_imp7"; + heu=false; + ant=true; + pri= TVar "#t",FImp(FTrue,FVar "#B"); + pre=[[TVar "#x",FVar "#B";gama],[delta]]; + res=([],[]); + def=[]; + sub=["#x",TApl(FTrue,FVar "#B",TVar "#t",TTrue)]; + ren=["#x"]; + vardelta = false; + ssi = true; + rendelta=[]} + +(* Regla r_imp *) +(* A,Gama |- B / Gama |- A->B,Delta *) +let r_imp = { + tip="r_imp"; + heu=false; + ant=false; + pri= TFun("#x",FVar "#A",TVar "#y"),FImp(FVar "#A",FVar "#B"); + pre=[[TVar "#x",FVar "#A";gama],[TVar "#y",FVar "#B"]]; + res=([],[]); + def=["Delta",TZero(FLisfor "DELTA")]; + sub=[]; + ren=["#x";"#y"]; + vardelta = true; + ssi = false; + rendelta=[]} + +(* Regla l_not *) +(* A->False,Gama |- Delta / Not(A),Gama |- Delta *) +let l_not = { + tip="l_not"; + heu=false; + ant=true; + pri= TVar "#x",FNot(FVar "#A"); + pre=[[TVar "#x",FImp(FVar "#A",FFalse);gama],[delta]]; + res=([],[]); + def=[]; + sub=[]; + ren=["#x"]; + vardelta = false; + ssi = true; + rendelta=[]} + +(* Regla r_not *) +(* Gama |- A->False,Delta / Gama |- Not(A),Delta *) +let r_not = { + tip="r_not"; + heu=false; + ant=false; + pri= TVar "#x",FNot(FVar "#A"); + pre=[[gama],[TVar "#x",FImp(FVar "#A",FFalse);delta]]; + res=([],[]); + def=[]; + sub=[]; + ren=["#x"]; + vardelta = false; + ssi = true; + rendelta=[]} + +(* Regla l_equ *) +(* A->B/\B->A,Gama |- Delta / A<->B,Gama |- Delta *) +let l_equ = { + tip="l_equ"; + heu=false; + ant=true; + pri= TVar "#x",FEqu(FVar "#A",FVar "#B"); + pre=[[TVar "#x",FAnd(FImp(FVar "#A",FVar "#B"), + FImp(FVar "#B",FVar "#A"));gama],[delta]]; + res=([],[]); + def=[]; + sub=[]; + ren=["#x"]; + vardelta = false; + ssi = true; + rendelta=[]} + +(* Regla r_equ *) +(* Gama |- A->B/\B->A,Delta / Gama |- A<->B,Delta *) +let r_equ = { + tip="r_equ"; + heu=false; + ant=false; + pri= TVar "#x",FEqu(FVar "#A",FVar "#B"); + pre=[[gama], + [TVar "#x",FAnd(FImp(FVar "#A",FVar "#B"), + FImp(FVar "#B",FVar "#A"));delta]]; + res=([],[]); + def=[]; + sub=[]; + ren=["#x"]; + vardelta = false; + ssi = true; + rendelta=[]} + +(* Definicion de la regla VACIA *) +let vACIA = { + tip="vacia"; + heu=false; + ant=false; + pri=gama; + pre=[]; + res=([],[]); + def=[]; + sub=[]; + ren=[]; + vardelta = false; + ssi = false; + rendelta=[]} + +(*---------------------- Reglas heuristicas ------------------------------*) + +(* Regla simetria de igualdad *) +(* / a=b,Gama |- b=a,Delta *) +let sim = { + tip="sim"; + heu=true; + ant=true; + pri= TVar "#x",FEq(FVar "#A",FVar "#a",FVar "#b"); + pre=[]; + res=([],[TSim(FVar "#A",FVar "#a",FVar"#b",TVar"#x"), + FEq(FVar "#A",FVar "#b",FVar "#a")]); + def=["Delta",TZero(FLisfor "DELTA")]; + sub=[]; + ren=["#x";"#a";"#b"]; + vardelta = true; + ssi = true; + rendelta=[]} + +(* Regla r_refl *) +(* / Gama |- a=a,Delta *) +let r_refl = { + tip="refl"; + heu=true; + ant=false; + pri= TRefl(FVar "#A",FVar "#a"),FEq(FVar "#A",FVar "#a",FVar "#a"); + pre=[]; + res=([],[]); + def=["Delta",TZero(FLisfor "DELTA")]; + sub=[]; + ren=["#a"]; + vardelta = true; + ssi = true; + rendelta=[]} + +let sistema = [inic;l_false;r_true;l_and;r_and;l_imp1;l_imp2;l_imp3; + l_imp5;l_imp6;l_imp7;l_not;r_not;l_equ;r_equ;r_imp; + l_or;r_or;l_imp4] + +(*----------- Proyecciones del tipos de datos Sequente ----------------------*) + +(* Antecedente de un sequente *) +let ante (a,_) = a + +(* Sucedente de un sequente *) +let suce (_,s) = s + +(*----------- Constructores de los tipos de datos ----------------------*) + +(* Simplifica una substitucion es decir elemina las substituciones + inutiles *) +let rec simple = function + | [] -> [] + | ((x,_) as a)::z -> + if String.get x 0 = '#' then simple z else a::simple z + +(* Construye un node de demostracion *) +let consd a l = {arb=a;lisbut=l} + +(* Construye un nodo de un arbol *) +let consa s r sd st = {seq = ref s;reg = ref r;sd = simple sd; + st= simple st} + +(* Construye un nodo de sustitucion *) +let conss r sf sg sd ren sdef ster = + SCons({sReg=ref r;sFor=sf;sGam=sg;sDel=sd; + sRen=ren;sDef=sdef;sTer=ster}) + +(*----------------------- Aplicacion de Reglas ------------------------------*) + +(* Buscar un nombre de variable en una sustitucion, retorna la lista + que contiene la formula que la variable sustituye *) +let rec busque n = function + | [] -> [] + | (x,f)::y -> if x=n then [f] else busque n y + +(* Aplicar una substitucion a una formula, retorna otra formula *) +let rec apl_f s = function + | (FVar y) as x -> (match busque y s with + | [] -> x + | a::_ -> a ) + | (FLisfor y) as x -> (match busque y s with + | [] -> x + | a::_ -> a) + | FAnd (a,b) -> FAnd(apl_f s a, apl_f s b) + | FOr (a,b) -> FOr(apl_f s a, apl_f s b) + | FImp (a,b) -> FImp(apl_f s a, apl_f s b) + | FEqu (a,b) -> FEqu(apl_f s a, apl_f s b) + | FEq (a,b,c) -> FEq(apl_f s a, apl_f s b,apl_f s c) + | FNot a -> FNot(apl_f s a) + | x -> x + +(* Aplicar una sustitucion a una lista de formulas *) +let apl_lf s l = List.map (apl_f s) l + +(* Encuentra un unificador de primer orden de dos formulas proposicionales, + retorna la pareja (e,u), donde e indica exito o fracaso + y u es el unificador principal (si no existe es [] vacia ) *) +let rec unif_f = function + | FAnd(a,b),FAnd(x,y) -> unif_lf([a;b],[x;y]) + | FOr(a,b),FOr(x,y) -> unif_lf([a;b],[x;y]) + | FImp(a,b),FImp(x,y) -> unif_lf([a;b],[x;y]) + | FEqu(a,b),FEqu(x,y) -> unif_lf([a;b],[x;y]) + | FEq(a,b,c),FEq(x,y,z) -> unif_lf([a;b;c],[x;y;z]) + | FVar(a),x -> (true,[a,x]) + | FAto(a),(FPred(_) as x) -> (true,[a,x]) + | FAto(a),(FEq(_) as x) -> (true,[a,x]) + | FPred(a),FPred(x) -> (eq_constr a x,[]) + | FNot(a),FNot(x) -> unif_f(a,x) + | FFalse,FFalse -> (true,[]) + | FTrue,FTrue -> (true,[]) + | _ -> (false,[]) + +and unif_lf = function + | ([],[]) -> (true,[]) + | (x::y,a::b) -> + let (e,u) = unif_f (x,a) in + if e then + let (e1,u1) = unif_lf (apl_lf u y,b) in + if e1 then (true,u@u1) else (false,[]) + else + (false,[]) + | _ -> (false,[]) + +(* Aplicar una substitucion a un lamda termino, retorna otro lambda termino *) +let rec apl_t st sf = function + | (TVar y) as x -> (match busque y st with + | [] -> x + | a::_ -> a ) + | (TLister y) as x -> (match busque y st with + | [] -> x + | a::_ -> a ) + | TApl(f1,f2,t1,t2) -> TApl (apl_f sf f1,apl_f sf f2, + apl_t st sf t1,apl_t st sf t2) + | TFun(x,f,y) -> (match busque x st with + | [] -> TFun(x,apl_f sf f,apl_t st sf y) + | [TVar n] -> TFun(n,apl_f sf f,apl_t st sf y) + | _ -> raise TacticFailure) + | TCase(lf,lt) -> TCase(List.map (apl_f sf) lf,List.map (apl_t st sf) lt) + | TPar(f1,f2,t1,t2) -> TPar(apl_f sf f1,apl_f sf f2, + apl_t st sf t1,apl_t st sf t2) + | TInl(f1,f2,t) -> TInl(apl_f sf f1,apl_f sf f2,apl_t st sf t) + | TInr(f1,f2,t) -> TInr(apl_f sf f1,apl_f sf f2,apl_t st sf t) + | TFst(f1,f2,t) -> TFst(apl_f sf f1,apl_f sf f2,apl_t st sf t) + | TSnd(f1,f2,t) -> TSnd(apl_f sf f1,apl_f sf f2,apl_t st sf t) + | TRefl(f1,f2) -> TRefl(apl_f sf f1,apl_f sf f2) + | TSim(f1,f2,f3,t) -> TSim(apl_f sf f1,apl_f sf f2, + apl_f sf f3,apl_t st sf t) + | TLis lt -> TLis (List.map (apl_t st sf) lt) + | TSum(t1,t2) -> TSum (apl_t st sf t1,apl_t st sf t2) + | TZ(f,t) -> TZ(apl_f sf f,apl_t st sf t) + | (TExi y) as x -> (match busque y st with + | [] -> x + | a::_ -> a ) + | TZero f -> TZero(apl_f sf f) + | t -> t + +(* Aplicar substitucion gama delta y una substitucion de terminos lambda + a una lista de formulasT, retorna una lista de formulasT *) +let rec apl_lft (s,gama_0,delta_0) st rendelta = + (* Aplicar una substitucion gama delta y una substitucion de terminos a una + formulaT, retorna una lista de formulasT *) + let apl_fm = function + | (_,FLisfor "GAMA") -> gama_0 + | (TLister x,FLisfor "DELTA") -> + (match busque x rendelta with + | [] -> delta_0 + | a::_ -> apl_lft ([],[],[]) a [] delta_0) + | (_,FLisfor "DELTA") -> delta_0 + | (t,f) -> [apl_t st [] t,apl_f s f] + in + flat_map apl_fm + +(* Aplicar substitucion gama delta y una substitucion de terminos lambda a un + sequente, retorna un nuevo sequente*) +let apl sf st rendelta = function + (l1,l2) -> (apl_lft sf st rendelta l1,apl_lft sf st rendelta l2) + +(* Aplicar la regla r, dada una substitucion. + Retorna una lista de sequentes *) +let aplr_s subs = List.map (apl (subs.sFor,subs.sGam,subs.sDel) + subs.sDef subs.sRen) !(subs.sReg).pre + +(* Componer dos substituciones de lambda terminos. Aplica la primera + sobre la segunda *) +let rec comp_st st = function + | [] -> st + | (x,y)::z -> (x,apl_t st [] y)::comp_st st z + +(* Renombrar las variables izquierdas de una sustitucion *) +let rec ren_izq ren = function + | [] -> [] + | ((x,y) as a)::z -> match busque x ren with + | [TVar a] -> (a,y)::ren_izq ren z + | _ -> a::ren_izq ren z + +(* Indica si dos formulas son iguales *) +let iguales_f f1 f2 = + let (e,u) = unif_f(f1,f2) in + e & u = [] + +(*------------------- Unificador para lambda terminos --------------------*) + +(* Encuentra un unificador de primer orden de dos lambda terminos, + retorna la pareja (e,u), donde e indica exito o fracaso + y u es el unificador principal (si no existe es [] vacia ). + TPara los terminos que contienen formulas recibe el unificador de + ellas *) +let rec unif_t sf = function + | (TVar x,((TVar y) as y_0)) -> + if (x = y) then (true,[]) else (true,[x,apl_t [] sf y_0]) + | (TVar x, y) -> (true,[x,apl_t [] sf y]) + | TApl(f,ff,t,tt),TApl(f1,ff1,t1,tt1) -> + unif_lft sf [f;ff][f1;ff1][t;tt][t1;tt1] + | TZ(f,t), TZ(f1,t1) -> unif_lft sf [f][f1][t][t1] + | (TExi x,((TExi y) as y_0)) -> + if (x = y) then (true,[]) else (true,[x,apl_t [] sf y_0]) + | TZero f, TZero f1 -> unif_lft sf [f][f1][][] + | TTrue,TTrue -> (true,[]) + | TFun(x,f,t),TFun(a,f1,t1) -> unif_lft sf [f][f1][t][t1] + | TPar(f,ff,t,tt),TPar(f1,ff1,t1,tt1) -> + unif_lft sf [f;ff][f1;ff1] [t;tt][t1;tt1] + | TInl(f,ff,t),TInl(f1,ff1,t1) -> unif_lft sf [f;ff][f1;ff1][t][t1] + | TInr(f,ff,t),TInr(f1,ff1,t1) -> unif_lft sf [f;ff][f1;ff1][t][t1] + | TFst(f,ff,t),TFst(f1,ff1,t1) -> unif_lft sf [f;ff][f1;ff1][t][t1] + | TSnd(f,ff,t),TSnd(f1,ff1,t1) -> unif_lft sf [f;ff][f1;ff1][t][t1] + | TRefl(f,ff),TRefl(f1,ff1) -> unif_lft sf [f;ff][f1;ff1][][] + | TSim(f1,f2,f3,t),TSim(f1',f2',f3',t') -> + unif_lft sf [f1;f2;f3] [f1';f2';f3'][t][t'] + | _ -> (false,[]) + +and iguales_lf sf = function + | ([],[]) -> true + | (x::y,a::b) -> + if iguales_f (apl_f sf x) (apl_f sf a) then + iguales_lf sf (y,b) + else + false + | _ -> false + +and unif_lt sf = function + | ([],[]) -> (true,[]) + | (x::y,a::b) -> + let (e,u) = unif_t sf (x,a) in + if e then + let (e1,u1) = unif_lt sf (y,b) in + if e1 then (true,u@u1) + else (false,[]) + else + (false,[]) + | _ -> (false,[]) + +and unif_lft sf lf lf1 lt lt1 = + if iguales_lf sf (lf,lf1) then + unif_lt sf (lt,lt1) + else + (false,[]) + +(* Indica si dos terminos son iguales *) +let iguales_t t1 t2 = + let (e,u) = unif_t [] (t1,t2) in + e & u = [] + +(* Indica si dos formulas son iguales. Retorna una pareja con el exito + y un unificador de los dos lambda terminos *) +let iguales_unif uf tr ts fr fs = + if iguales_f fr fs then + let (e,ut) = unif_t uf (ts,tr) in + if e then + (true,ut) + else + raise TacticFailure + else + (false,[]) + +(* Crear una nueva variable *) +let hipvar = ref ((id_of_string "#")::[]) + +let genvar () = + let id = next_ident_away + (id_of_string "H") + !hipvar in + (hipvar := id::(!hipvar); string_of_id id) + +(* Lista de terminos de una substitucion *) +let listerm = List.map snd + +(* Lista de variables de una lista de formulasS *) +let rec lisvar = function + | [] -> [] + | (TVar x,_)::y -> x::lisvar y + | (TExi x,_)::y -> x::lisvar y + | _::y -> lisvar y + +(* Lista de formulas de una lista de formulasS *) +let rec lisfor = function + | [] -> [] + | (TVar _,x)::y -> x::lisfor y + | (TExi _,x)::y -> x::lisfor y + | _::y -> lisfor y + +(* Recibe una lista de variables, retorna un renombramiento de ellas *) +let renombra = List.map (function x -> (x,TVar(genvar()))) + +(* Obtiene un renombramiento de todas las metavariables delta *) +let renombradelta s rend= + let l = lisvar (suce s) in + List.map (function x -> (x,renombra l)) rend + +(* Obtiene una substitucion de las metavariables delta, por lista de + terminos *) +let rec subsdelta = function + | [] -> [] + | (x,y)::y_0 -> match listerm y with + | [] -> [] + | [a] -> (x,a)::subsdelta y_0 + | a -> (x,TLis a)::subsdelta y_0 + +(* Indica si una formula pertenece a una lista de formulasT. + Retorna una pareja con el exito y una unificacion de los lambda terminos *) +let rec pertenece uf ant tr fr = function + | [] -> (false,[]) + | (TLister _,_)::y -> pertenece uf ant tr fr y + | (ts,fs)::y -> + let (e,ut) = + if ant then + iguales_unif uf ts tr fr fs + else + iguales_unif uf tr ts fr fs + in + if e then + (true,ut) + else + pertenece uf ant tr fr y + +(* Indica si la primera lista de formulasT contiene la segunda. + Retorna una pareja con el exito y una unificacion de los lambda terminos *) +let rec contiene uf ant l = function + | [] -> (true,[]) + | (TLister _,_)::y -> contiene uf ant l y + | (tr,fr)::y -> + let (e1,s1) = pertenece uf ant tr fr l in + if e1 then + let (e2,s2) = contiene uf ant l y in + if e2 then + (true,s1@s2) + else + (false,[]) + else + (false,[]) + +(* Decide si un secuente cumple con las restricciones de aplicacion de una + regla. Recibe el unificador de la regla con la restriccion. Retorna una + pareja con el exito y las unificaciones de lambda terminos del antecedente + y el sucedente del secuente *) +let cumple uf res = function (seql,seqr) -> + let (resl,resr) = apl (uf,[],[]) [] [] res in + let (e1,s1) = contiene uf true seql resl in + if e1 then + let (e2,s2) = contiene uf false seqr resr in + if e2 then + (true,s1,s2) + else + (false,[],[]) + else + (false,[],[]) + +(* Compone una substitucion de formulas con una substitucion de terminos *) +let rec comp_sfst uf = function + | [] -> [] + | (x,y)::z -> (x,apl_t [] uf y)::comp_sfst uf z + +(* Crea una substitucion para las variables de un lambda termino, basado + en la regla que aplica *) +let cree_sub s uf ter t ul ur r = + let lv = + if r.vardelta then ["DELTA",FLis(lisfor (suce s))] else [] + in + let rendelta = renombradelta s r.rendelta in + let ren = (renombra r.ren) @ (subsdelta rendelta) in + let sd0 = + if r.ant then + ur (* Calcular definicion basica *) + else + match unif_t uf (t,ter) with + | (false,_) -> raise(TacticFailure) + | (_,u) -> ur@u + in + let sd1 = comp_st r.def sd0 in + let sd2 = comp_sfst (uf@lv) sd1 in (*Susbstituir var. proposicionales *) + let sd = comp_st ren sd2 in (* Componer con un renombramiento *) + let st0 = + if r.ant then (* Calcular sustitucion basica *) + match unif_t uf (ter,t) with + | (false,_) -> raise(TacticFailure) + | (_,u) -> ul@u + else + ul + in + let st1 = comp_st st0 r.sub in + let st2 = comp_sfst (uf@lv) st1 in (*Susbstituir var. proposicionales *) + let st3 = ren_izq ren st2 in (* Componer con un renombramiento *) + let st = comp_st ren st3 in + (sd,st,rendelta) + +(* Decide se una regla dada es aplicable sobre un termino (tf) + de un secuente y un lado de reduccion o. Retorna la sustitucion + apropiada para la regla o SNil si no existe *) + +let rec aplicable s lf tf o = function + ({ant=ant;pri=ter,pri;res=res}) as r -> + if o<>ant then + SNil + else + (match tf with + | (TLister _,_) -> SNil + | (t,f) -> + let (ef,uf) = unif_f(pri,f) in + if ef then + let (et,ul,ur) = cumple uf res s in + if et then + let (gam,del) = if ant then (lf,suce s) + else (ante s,lf) in + let (sd,st,rn) = cree_sub s uf ter t ul ur r in + conss r uf gam del rn sd st + else SNil + else SNil) + +(* Dado una regla, retorna una posicion donde la regla sea aplicable. RNil + si no existe *) +let rec escoja_termino r s o rseq lacum = function + | [] -> + if o=0 then + escoja_termino r s 2 [] lacum rseq + else if o=1 then + escoja_termino r s 2 [] [] rseq + else + RNil + | t::y -> + let oo = if o=0 then 1 else o in + (match aplicable s (lacum@y) t (oo=1) r with + | SNil -> escoja_termino r s oo rseq (lacum@[t]) y + | SCons(s) -> + if oo=1 then RCons(s,[],lacum,(y,rseq)) + else RCons(s,[],lacum,([],y))) + +(* Dado un secuente y un sistema de reglas + retorna una sustitucion apropiada para la regla, o RNil si no existe *) +let rec escoja_regla s (lrseq,lac) = function + | [] -> RNil + | (r::y) as lreg -> + (match escoja_termino r s 0 (suce lrseq) lac (ante lrseq) with + | RNil -> escoja_regla s (s,[]) y + | RCons(subs,_,lanew,lrnew) -> RCons(subs,lreg,lanew,lrnew)) + +(* Si una formula proposicional existe en una lista de formulas *) +let rec existeprop f = function + | [] -> false + | x::y -> if iguales_f f x then true else existeprop f y + +(* Buscar una formula proposicional en una lista de formulasT, + retorna el termino o TZero si no la encuentra *) +let rec busqueprop f = function + | [] -> TZero(FFalse) + | (tt,ff)::y -> if iguales_f f ff then tt else busqueprop f y + +(* Crear un termino como aplicaciones sucesivas del subobjetivo sobre las + hipotesis *) +let rec ter_subobjetivo lisprop subobj = function + | [] -> (fst subobj) + | (x,f)::y -> + if existeprop f lisprop then + ter_subobjetivo lisprop subobj y + else + (match snd(subobj) with + | FImp(a,b) -> ter_subobjetivo (f::lisprop) + (TApl(a,b,fst(subobj),x),b) y + | _ -> TZero(FFalse)) + +(* Convierte la lista del succedente en una disyuncion *) +let rec disyuncion = function + | [] -> FFalse + | [a] -> a + | x::y -> FOr(x,disyuncion y) + +(* Convierte la lista del antecedente en una implicacion *) +let rec implicacion dis vp = function + | [] -> dis + | x::y -> + if (existeprop x vp) then + implicacion dis vp y + else + FImp(x,implicacion dis vp y) + +(* Lista de proposiciones de un secuente sin repetidos *) +let rec it_propos lisacum = function + | [] -> lisacum + | (_,f)::y -> + if (existeprop f lisacum) then + it_propos lisacum y + else + it_propos (lisacum@[f]) y + +let proposiciones = it_propos [] + +(* Generar una subobjetivo de la demostracion de tal manera que + la validez del sequente original sea equivalente a la validez del + subobjetivo *) +let subobjetivo s vp = + let dis = disyuncion (proposiciones (suce s)) in + let ter = TExi(genvar()) in + (ter,implicacion dis vp (proposiciones (ante s))),dis + +(* Crea una substitucion que supone un subobjetivo demostrado *) +let rec termino_caso fapp f = function + | FOr(a,b) -> + let id1 = genvar() in + let t1 = TVar(id1) in + let id2 = genvar() in + let t2 = TVar(id2) in + if iguales_f a f then + TCase([a;b;f],[TFun(id1,a,t1);TFun(id2,b,TZero(f));fapp]) + else + TCase([a;b;f],[TFun(id1,a,TZero(f));TFun(id2,b,termino_caso t2 f b); + fapp]) + | _ -> fapp + +let rec it_subs_subobj subs sec fapp tip = function + | [] -> subs + | ((TVar x,f) as a)::y -> + let t = busqueprop f sec in + if t <> TZero(FFalse) then + it_subs_subobj ((x,apl_t subs [] t)::subs) sec fapp tip y + else + it_subs_subobj ((x,termino_caso fapp f tip)::subs) (a::sec) + fapp tip y + | _ -> assert false + +let subs_subobj fapp tip s = it_subs_subobj [] [] fapp tip s + +let rec esta_en_case l = function + | TApl(_,_,t1,t2) -> + (esta_en_case l t1) or (esta_en_case l t2) + | TFun(_,_,t) -> + esta_en_case l t + | TPar(_,_,t1,t2) -> + (esta_en_case l t1) or (esta_en_case l t2) + | TInl(_,_,t) -> + esta_en_case l t + | TInr(_,_,t) -> + esta_en_case l t + | TFst(_,_,t) -> + esta_en_case l t + | TSnd(_,_,t) -> + esta_en_case l t + | TZ(_,t) -> + esta_en_case l t + | TSum(t1,t2) -> + (esta_en_case l t1) or (esta_en_case l t2) + | TCase([f1;f2;f3],[t1;t2;t3]) -> + (match l with + | [ff1;ff2;ff3] -> + if (iguales_f f1 ff1) & (iguales_f f2 ff2) & + (iguales_f f3 ff3) then + true + else + (esta_en_case l t1) or (esta_en_case l t2) + | _ -> assert false) + | _ -> false + +let rec busque_termino t = function + | [] -> (false,"",false) + | (x,v,o)::y -> if iguales_t t x then (true,v,o) else busque_termino t y + +(* Sistema de reglas para simplificar terminos *) +let rec sistreg lcase = function + | TApl(_,_,TFun (x,_,t),t1) -> apl_t [x,t1] [] t + | TFst(_,_,TPar(_,_,t,_)) -> t + | TSnd(_,_,TPar(_,_,_,t)) -> t + (* Simplificacion con TZero *) + | TApl(_,f,TZero _,t) -> TZero f + | TApl(_,f,t,TZero _) -> TZero f + | TFun(x,f1,TZero f2) -> TZero (FImp(f1,f2)) + | TPar(f1,f2,TZero _,t2) -> TZero (FAnd(f1,f2)) + | TPar(f1,f2,t1,TZero _) -> TZero (FAnd(f1,f2)) + | TInl(f1,f2,TZero _) -> TZero (FOr(f1,f2)) + | TInr(f1,f2,TZero _) -> TZero (FOr(f1,f2)) + | TFst(f1,f2,TZero _) -> TZero f1 + | TSnd(f1,f2,TZero _) -> TZero f2 + | TZ(f,TZero _) -> TZero f + | TSum(TZero _,t) -> t + | TSum(t,TZero _) -> t + | TCase([_;_;f],[_;_;TZero _]) -> TZero f + | TSum(TFun(v1,ff1,t1),TFun(v2,ff2,t2)) -> + TFun(v1,ff1,TSum(t1,apl_t [v2,(TVar v1)][] t2)) + (* Simplificacion del case *) + | TApl(f1,f2,TCase([a;b;FImp(c,d)],[TFun(v1,ff1,t1); + TFun(v2,ff2,t2);t3]),t) -> + TCase([a;b;f2],[TFun(v1,ff1,TApl(c,d,t1,t)); + TFun(v2,ff2,TApl(c,d,t2,t));t3]) + | TApl(f1,f2,t,TCase([a;b;c],[TFun(v1,ff1,t1);TFun(v2,ff2,t2);t3])) -> + TCase([a;b;f2],[TFun(v1,ff1,TApl(f1,f2,t,t1)); + TFun(v2,ff2,TApl(f1,f2,t,t2));t3]) + | TPar(f1,f2,TCase([a;b;c],[TFun(v1,ff1,t1);TFun(v2,ff2,t2);t3]),t) -> + TCase([a;b;FAnd(f1,f2)],[TFun(v1,ff1,TPar(f1,f2,t1,t)); + TFun(v2,ff2,TPar(f1,f2,t2,t));t3]) + | TPar(f1,f2,t,TCase([a;b;c],[TFun(v1,ff1,t1);TFun(v2,ff2,t2);t3])) -> + TCase([a;b;FAnd(f1,f2)],[TFun(v1,ff1,TPar(f1,f2,t,t1)); + TFun(v2,ff2,TPar(f1,f2,t,t2));t3]) + | TInl(f1,f2,TCase([a;b;c],[TFun(v1,ff1,t1);TFun(v2,ff2,t2);t3])) -> + TCase([a;b;FOr(f1,f2)],[TFun(v1,ff1,TInl(f1,f2,t1)); + TFun(v2,ff2,TInl(f1,f2,t2));t3]) + | TInr(f1,f2,TCase([a;b;c],[TFun(v1,ff1,t1);TFun(v2,ff2,t2);t3])) -> + TCase([a;b;FOr(f1,f2)],[TFun(v1,ff1,TInr(f1,f2,t1)); + TFun(v2,ff2,TInr(f1,f2,t2));t3]) + | TFst(f1,f2,TCase([a;b;c],[TFun(v1,ff1,t1);TFun(v2,ff2,t2);t3])) -> + TCase([a;b;f1],[TFun(v1,ff1,TFst(f1,f2,t1)); + TFun(v2,ff2,TFst(f1,f2,t2));t3]) + | TSnd(f1,f2,TCase([a;b;c],[TFun(v1,ff1,t1);TFun(v2,ff2,t2);t3])) -> + TCase([a;b;f2],[TFun(v1,ff1,TSnd(f1,f2,t1)); + TFun(v2,ff2,TSnd(f1,f2,t2));t3]) + | TZ(f,TCase([a;b;c],[TFun(v1,ff1,t1);TFun(v2,ff2,t2);t3])) -> + TCase([a;b;f],[TFun(v1,ff1,TZ(f,t1)); + TFun(v2,ff2,TZ(f,t2));t3]) + | TSum((TCase([a;b;c],[TFun(v1,ff1,t1);TFun(v2,ff2,t2);t3]) as tC1), + (TCase([a';b';c'], + [TFun(v1',ff1',t1');TFun(v2',ff2',t2');t3']) as tC2)) -> + if (iguales_f a a') & (iguales_f b b') then + TCase([a;b;c],[TFun(v1,ff1,TSum(t1,apl_t [v1',(TVar v1)] [] t1')); + TFun(v2,ff2,TSum(t2,apl_t [v2',(TVar v2)] [] t2')); + TSum(t3,t3')]) + else if (esta_en_case [a;b;c] t1') or (esta_en_case [a;b;c] t2') then + TCase([a';b';c'],[TFun(v1',ff1',TSum(t1',tC1)); + TFun(v2',ff2',TSum(t2',tC1));t3']) + else + TCase([a;b;c],[TFun(v1,ff1,TSum(t1,tC2));TFun(v2,ff2,TSum(t2,tC2));t3]) + | TCase([_;_;f],[TFun(_,_,TZero _);TFun(_,_,TZero _);_]) -> TZero(f) + | TCase([a;b;f],[TFun(v1,f1,t1) as tt1;TFun(v2,f2,t2) as tt2;t]) -> + if iguales_t t1 t2 then t2 + else + let (exi,var,ori) = busque_termino t lcase in + if exi then + if ori then apl_t [v1,TVar var][] t1 + else apl_t [v1, TVar var] [] t2 + else raise(NoAplica) + | TSum(t1,t2)-> + if (iguales_t t1 t2) then t1 + else raise (NoAplica) + | TPar(_,_,TFst(_,_,t1),TSnd(_,_,t2)) -> + if iguales_t t1 t2 then + t1 + else raise(NoAplica) + | _ -> raise(NoAplica) + +(* Aplicacion de una regla sobre un termino, si no pudo aplicar retorna + NoAplica. Estrategia mas izquierdo, menos profundo *) + +let pr l = List.hd l + +let sn l = List.hd(List.tl l) + +let rec it_apl_listsistr lcase lacum siapl = function + | [] -> (lacum,siapl) + | x::y -> + let (xp,exi) = + try (apl_sistr lcase x,true) with NoAplica -> (x,false) + in + it_apl_listsistr lcase (lacum@[xp]) (exi or siapl) y + +and apl_listsistr lcase l = it_apl_listsistr lcase [] false l + +and apl_sistr_try lcase x = + try (apl_sistr lcase x,true) with NoAplica -> (x,false) + +and apl_sistr lcase a = + try + sistreg lcase a + with NoAplica -> + (match a with + | TApl(f1,f2,t1,t2) -> + let (lt,exi) = apl_listsistr lcase [t1;t2] in + if exi then TApl(f1,f2,pr lt,sn lt) + else raise(NoAplica) + | TFun(x,f,t) -> + let (lt,exi) = apl_listsistr lcase [t] in + if exi then TFun(x,f,pr lt) + else raise(NoAplica) + | TPar(f1,f2,t1,t2) -> + let (lt,exi) = apl_listsistr lcase [t1;t2] in + if exi then TPar(f1,f2,pr lt,sn lt) + else raise(NoAplica) + | TInl(f1,f2,t) -> + let (lt,exi) = apl_listsistr lcase [t] in + if exi then TInl(f1,f2,pr lt) + else raise(NoAplica) + | TInr(f1,f2,t) -> + let (lt,exi) = apl_listsistr lcase [t] in + if exi then TInr(f1,f2,pr lt) + else raise(NoAplica) + | TFst(f1,f2,t) -> + let (lt,exi) = apl_listsistr lcase [t] in + if exi then TFst(f1,f2,pr lt) + else raise(NoAplica) + | TSnd(f1,f2,t) -> + let (lt,exi) = apl_listsistr lcase [t] in + if exi then TSnd(f1,f2,pr lt) + else raise(NoAplica) + | TZ(f,t) -> + let (lt,exi) = apl_listsistr lcase [t] in + if exi then TZ(f,pr lt) + else raise(NoAplica) + | TSum(t1,t2) -> + let (lt,exi) = apl_listsistr lcase [t1;t2] in + if exi then TSum(pr lt,sn lt) + else raise(NoAplica) + | TCase([f1;f2;f3],[TFun(v1,ff1,t1);TFun(v2,ff2,t2);t3]) -> + let (t1',exi1) = apl_sistr_try ((t3,v1,true)::lcase) t1 in + let (t2',exi2) = apl_sistr_try ((t3,v2,false)::lcase) t2 in + let (t3',exi3) = apl_sistr_try lcase t3 in + if (exi1 or exi2 or exi3) then + TCase([f1;f2;f3],[TFun(v1,ff1,t1'); + TFun(v2,ff2,t2');t3']) + else raise(NoAplica) + | _ -> raise(NoAplica)) + +(* Indica si hay un zero en el termino *) +let rec tiene_zero = function + | TApl(_,_,t,t1) -> tiene_zero(t) or tiene_zero(t1) + | TFun(_,_,t) -> tiene_zero(t) + | TPar(_,_,t,t1) -> tiene_zero(t) or tiene_zero(t1) + | TInl(_,_,t) -> tiene_zero(t) + | TInr(_,_,t) -> tiene_zero(t) + | TFst(_,_,t) -> tiene_zero(t) + | TSnd(_,_,t) -> tiene_zero(t) + | TCase(_,[t;t1;t2]) -> tiene_zero (t) or tiene_zero (t1) or + tiene_zero(t2) + | TZ(_,t) -> tiene_zero(t) + | TZero(f) -> true + | a -> false + +(* Elemento de la posicion p de una lista *) +let rec lis_pos p = function + | [] -> raise(TacticFailure) + | x::y -> if (p=0) then x else lis_pos (p-1) y + +(* Genera una copia de una formula con reemplazo de los terminos de tipo + FLis por las formulas que aparecen en la posicion p'esima de las + listas respectivas *) +let rec copia_f p = function + | FAnd(a,b) -> FAnd(copia_f p a,copia_f p b) + | FEqu(a,b) -> FEqu(copia_f p a,copia_f p b) + | FOr(a,b) -> FOr(copia_f p a,copia_f p b) + | FImp(a,b) -> FImp(copia_f p a,copia_f p b) + | FNot(a) -> FNot(copia_f p a) + | FLis lf -> lis_pos p lf + | a -> a + +(* Genera una copia de un termino con reemplazo de los terminos de tipo + Lista por los terminos que aparecen en la posicion p'esima de las listas + respectivas *) +let rec copia_t sinplus p = function + | TApl(f,f1,t,t1) -> TApl(copia_f p f,copia_f p f1, + copia_t sinplus p t,copia_t sinplus p t1) + | TFun(x,f,t) -> TFun(x,copia_f p f,copia_t sinplus p t) + | TPar(f,f1,t,t1) -> TPar(copia_f p f,copia_f p f1, + copia_t sinplus p t,copia_t sinplus p t1) + | TInl(f,f1,t) -> TInl(copia_f p f,copia_f p f1,copia_t sinplus p t) + | TInr(f,f1,t) -> TInr(copia_f p f,copia_f p f1,copia_t sinplus p t) + | TFst(f,f1,t) -> TFst(copia_f p f,copia_f p f1,copia_t sinplus p t) + | TSnd(f,f1,t) -> TSnd(copia_f p f,copia_f p f1,copia_t sinplus p t) + | TLis lt -> lis_pos p lt + | TSum(t,t1) -> let s = copia_t sinplus p t in + let s1 = copia_t sinplus p t1 in + if sinplus then + if tiene_zero s then s1 + else s + else TSum(s,s1) + | TCase(lf,lt) -> + TCase(List.map (copia_f p) lf,List.map (copia_t sinplus p) lt) + | TZ(f,t) -> TZ(copia_f p f,copia_t sinplus p t) + | TZero(f) -> TZero(copia_f p f) + | a -> a + +(* Reescribe un lambda termino con constructores TZero y TSum a un lambda + termino *) +let rec normal t = + try normal(apl_sistr [] t) with NoAplica -> copia_t true 0 t + +(*-------------------- Procedimiento de decision --------------------------*) + +(* Indica que no debe buscar mas en el arbol *) +let no_back rev = function + {arb=a;lisbut=l} -> (a <> Nil) & (l=[] or rev) + +(* Funcion que dice si un sequente es demostrable o no. Retorna + un arbol de demostracion del sequente, o vacio. *) +let rec naive intu vp = function + (l,r) as s -> naive_s s intu (s,[]) vp sistema + +(* Dado un secuente s y un subsecuente (en el cual busca una formula + para aplicarle una regla), encuentra un elemento de demostracion. + Si intu es true genera subojetivos equivalentes al original en caso + de no encontrar la demostracion. Si es false, retorna el arbol Vacio*) + +and naive_s s intu seq_acum vp listareg = + (match escoja_regla s seq_acum listareg with + | RNil -> + if intu then + let obj = subobjetivo s vp in + let fapp = ter_subobjetivo vp (fst obj) (ante s) in + let subs_sub = subs_subobj fapp (snd obj) (suce s) in + consd (Cons(Nil,consa s vACIA subs_sub [],Nil)) + [fst obj] + else consd Nil [] + | RCons(subs,lreg,lanew,lrnew) -> + let reversible = !(subs.sReg).ssi or subs.sDel = [] in + ( match aplr_s subs with + | [] -> + consd(Cons(Nil, + consa s !(subs.sReg) subs.sDef subs.sTer, + Nil)) [] + | [a] -> + let {arb=a1;lisbut=l1} as al = (naive intu vp a) in + if no_back reversible al then + consd (Cons(a1, + consa s !(subs.sReg) subs.sDef subs.sTer, + Nil)) l1 + else if (not (reversible)) then + naive_s s intu (lrnew,lanew) vp lreg + else + consd Nil [] + | a::(b::_) -> + let {arb=a1;lisbut=l1} as al1 = naive intu vp a in + let {arb=a2;lisbut=l2} as al2 = naive intu vp b in + if (no_back reversible al1) & (no_back reversible al2) then + consd (Cons(a1, + consa s !(subs.sReg) subs.sDef subs.sTer, + a2)) (l1@l2) + else if (not (reversible)) then + naive_s s intu (lrnew,lanew) vp lreg + else + consd Nil [])) + +(* Crea nuevas substituciones para cada variable del sucedente *) +let rec nuevas_subs t p = function + | [] -> [] + | x::y -> (x,copia_t false p t) :: nuevas_subs t (p+1) y + +(* Busca todos lo Delta que aparecen en el lado izquierdo de la + sustitucion y lo reemplaza por las variables del sucedente del secuente *) +let rec remplacedelta lisv = function + | [] -> [] + | ("Delta",t)::y -> nuevas_subs t 0 lisv @ remplacedelta lisv y + | x::y -> x :: remplacedelta lisv y + +(* Calcula una lista de susbtituciones sobre las variables que aparecen al + en el sucedente del secuente de un arbol de demostracion. De tal forma + que al componerlas y aplicarlas se obtienen los lambda terminos que expresan + la demostracion*) +let rec subs_t = function + | Nil -> [] + | Cons(a,{seq=seq;sd=sd0;st=st0;reg=r},b) -> + let sd = if (!r.rendelta <> []) or (!r.vardelta) then + remplacedelta (lisvar (suce !seq)) sd0 + else sd0 in + let st = if (!r.rendelta <> []) or (!r.vardelta) then + remplacedelta (lisvar (suce !seq)) st0 + else st0 in + [sd] @ (subs_t a) @ [st] @ (subs_t b) + +(* Funcion que compone recursivamente una substitucion con una lista + de substituciones *) +let rec componga_r s = function + | [] -> s + | x::y -> componga_r (comp_st x s) y + +(* Dado un arbol de demostracion de un secuente, calcula los lambda terminos + que expresan la demostracion *) +let lterm = function + | Nil -> [] + | (Cons(_,{seq=seq},_)) as a -> + List.map (function (x,y) -> (x,normal y)) (componga_r [] (subs_t a)) + +(*--------------------- Interface con Coq ---------------------------------*) +(*-- Convierte una formula cci a una formula notacion Tauto --*) + +let tAUTOFAIL (g:goal sigma) = + (errorlabstrm "TAUTOFAIL" [< 'sTR "Tauto failed.">] : + goal list sigma * validation) + +let is_imp_term t = + match kind_of_term t with + | IsProd (_,_,b) -> (not((dependent (mkRel 1) b))) + | _ -> false + +(* Chet's code depends on the names of the logical constants. *) + +let tauto_of_cci_fmla gls cciterm = + let rec tradrec cciterm = + if pf_is_matching gls (and_pattern ()) cciterm then + match pf_matches gls (and_pattern ()) cciterm with + | [(1,a);(2,b)] -> FAnd(tradrec a,tradrec b) + | _ -> assert false + else if pf_is_matching gls (or_pattern ()) cciterm then + match pf_matches gls (or_pattern ()) cciterm with + | [(1,a);(2,b)] -> FOr(tradrec a,tradrec b) + | _ -> assert false + else if pf_is_matching gls (iff_pattern ()) cciterm then + match pf_matches gls (iff_pattern ()) cciterm with + | [(1,a);(2,b)] -> FEqu(tradrec a,tradrec b) + | _ -> assert false + else if pf_is_matching gls (eq_pattern ()) cciterm then + match pf_matches gls (eq_pattern ()) cciterm with + | [(1,a);(2,b);(3,c)] -> FEq(FPred a,FPred b, FPred c) + | _ -> assert false + else if pf_is_matching gls (not_pattern ()) cciterm then + match pf_matches gls (not_pattern ()) cciterm with + | [(1,a)] -> FNot(tradrec a) + | _ -> assert false + else if pf_is_matching gls (false_pattern ()) cciterm then + FFalse + else if pf_is_matching gls (true_pattern ()) cciterm then + FTrue + else if is_imp_term cciterm then + match kind_of_term cciterm with + | IsProd (_,a,b) -> FImp(tradrec a,tradrec (pop b)) + | _ -> assert false + else FPred cciterm + in + tradrec (whd_betaiota cciterm) + +(*-- Retorna una lista de todas las variables proposicionales que + aparescan en una lista de formulasS --*) +let rec lisvarprop = function + | [] -> [] + | (_,((FPred x) as fx))::y -> fx::lisvarprop y + | _::y -> lisvarprop y + +(*-- Dado el ambiente COQ construye el lado izquierdo de un secuente + (hipotesis) --*) +let rec constr_lseq gls = function + | [] -> [] + | (idx,c,hx)::rest -> + match Retyping.get_sort_of (pf_env gls) (project gls) hx with + | Prop Null -> + (TVar(string_of_id idx),tauto_of_cci_fmla gls hx) + :: constr_lseq gls rest + |_-> constr_lseq gls rest + +(*-- Dado un estado COQ construye el lado derecho de un secuente + (conclusion) --*) +let constr_rseq gls but = [TVar(genvar()), + tauto_of_cci_fmla gls but] + +(*-- Calula la posicion de la lista de un elemento --*) +let rec pos_lis x = function + | [] -> raise TacticFailure + | a::r -> if (x=a) then 1 else 1 + (pos_lis x r) + +(*-- Construye un termino constr dado una formula tauto --*) +let rec cci_of_tauto_fml () = + let cAnd = global_reference CCI (id_of_string "and") + and cOr = global_reference CCI (id_of_string "or") + and cFalse = global_reference CCI (id_of_string "False") + and cTrue = global_reference CCI (id_of_string "True") + and cEq = global_reference CCI (id_of_string "eq") in + function + | FAnd(a,b) -> applistc cAnd + [cci_of_tauto_fml () a;cci_of_tauto_fml () b] + | FOr(a,b) -> applistc cOr + [cci_of_tauto_fml () a; cci_of_tauto_fml () b] + | FEq(a,b,c)-> applistc cEq + [cci_of_tauto_fml () a; cci_of_tauto_fml () b; + cci_of_tauto_fml () c] + | FImp(a,b) -> mkArrow (cci_of_tauto_fml () a) (cci_of_tauto_fml () b) + | FPred a -> a + | FFalse -> cFalse + | FTrue -> cTrue + | FLis lf -> raise TacticFailure + | FVar a -> raise TacticFailure + | FAto a -> raise TacticFailure + | FLisfor a -> raise TacticFailure + | _ -> anomaly "Tauto:cci_of_tauto_fml" + +let search env id = + try + mkRel (fst (lookup_rel_id id (Environ.rel_context env))) + with Not_found -> + if mem_named_context id (Environ.named_context env) then + mkVar id + else + global_reference CCI id + +(*-- Construye un termino constr de un termino tauto --*) +let cci_of_tauto_term env t = + let cFalse_ind = global_reference CCI (id_of_string "False_ind") + and cconj = global_reference CCI (id_of_string "conj") + and cor_ind = global_reference CCI (id_of_string "or_ind") + and cor_introl = global_reference CCI (id_of_string "or_introl") + and cor_intror = global_reference CCI (id_of_string "or_intror") + and cproj1 = global_reference CCI (id_of_string "proj1") + and cproj2 = global_reference CCI (id_of_string "proj2") + and crefl = global_reference CCI (id_of_string "refl_equal") + and csim = global_reference CCI (id_of_string "sym_eq") + and ci = global_reference CCI (id_of_string "I") + in + let rec ter_constr l = function + | TVar x -> (try (try mkRel(pos_lis x l) + with TacticFailure -> + search env (id_of_string x)) + with _ -> raise TacticFailure) + | TZ(f,x) -> applistc cFalse_ind + [cci_of_tauto_fml () f;ter_constr l x] + | TSum(t1,t2) -> ter_constr l t1 + | TExi (x) -> (try search env (id_of_string x) with + _ -> raise TacticFailure) + | TApl(_,_,t1,t2) -> applistc (ter_constr l t1) [ter_constr l t2] + | TPar(f1,f2,t1,t2) -> applistc cconj + [cci_of_tauto_fml () f1;cci_of_tauto_fml () f2; + ter_constr l t1;ter_constr l t2] + | TInl(f1,f2,t) -> applistc cor_introl + [cci_of_tauto_fml () f1;cci_of_tauto_fml () f2; + ter_constr l t] + | TInr(f1,f2,t) -> applistc cor_intror + [cci_of_tauto_fml () f1;cci_of_tauto_fml () f2; + ter_constr l t] + | TFst(f1,f2,t) -> applistc cproj1 + [cci_of_tauto_fml () f1;cci_of_tauto_fml () f2; + ter_constr l t] + | TSnd(f1,f2,t) -> applistc cproj2 + [cci_of_tauto_fml () f1;cci_of_tauto_fml () f2; + ter_constr l t] + | TRefl(f1,f2) -> applistc crefl + [cci_of_tauto_fml () f1;cci_of_tauto_fml () f2] + | TSim(f1,f2,f3,t) -> applistc csim + [cci_of_tauto_fml () f1;cci_of_tauto_fml () f2; + cci_of_tauto_fml () f3;ter_constr l t] + | TCase(lf,lt) -> applistc cor_ind + ((List.map (cci_of_tauto_fml ()) lf)@ + (List.map (ter_constr l) lt)) + | TFun(n,f,t) -> + Environ.lambda_name env + (Name(id_of_string n ), cci_of_tauto_fml () f,ter_constr (n::l) t) + | TTrue -> ci + | TLis _ -> raise TacticFailure + | TLister _ -> raise TacticFailure + | TZero _ -> raise TacticFailure + in + ter_constr [] t + +let cutUsing id t = (tclTHENS (Tactics.cut t) ([intro_using id;tclIDTAC])) + +let cut_in_parallelUsing idlist l = + let rec prec l_0 = function + | [] -> tclIDTAC + | h::t -> + (tclTHENS (cutUsing (id_of_string (List.hd l_0)) h) + ([prec (List.tl l_0) t;tclIDTAC])) + in + prec (List.rev idlist) (List.rev l) + +let exacto tt gls = + let tac = + try + let t = cci_of_tauto_term (pf_env gls) tt in + exact_no_check t + with _ -> tAUTOFAIL (* Efectivamente, es cualquier cosa!! *) + in tac gls (* Esto confirma el comentario anterior *) + +let subbuts l hyp = cut_in_parallelUsing + (lisvar l) + (List.map (cci_of_tauto_fml ()) (lisfor l)) + +let t_exacto = ref (TVar "#") + +let tautoOR ti gls = + let thyp = pf_hyps gls in + hipvar := ids_of_named_context thyp; + let but = pf_concl gls in + let seq = (constr_lseq gls thyp, constr_rseq gls but) in + let vp = lisvarprop (ante seq) in + match naive ti vp seq with + | {arb=Nil} -> + tAUTOFAIL gls + | {arb=arb;lisbut=l} -> + let se = apl ([],[],[]) (lterm arb) [] seq in + let tt = fst(List.hd(suce se)) in + (t_exacto := tt; + subbuts l thyp gls) + +let tautoOR_0 gl = + tclORELSE + (tclTHENSI (tautoOR false) [fun gl -> exacto (!t_exacto) gl]) + tAUTOFAIL gl + +let intuitionOR = + tclTRY (tclTHEN + (tclTHENSI (tautoOR true) [fun gl -> exacto (!t_exacto) gl]) + default_full_auto) + +(*--- Mixed code Chet-Cesar ---*) + +let rec prove tauto_intu g = + (tclORELSE (tryAllHyps (clauseTacThen + (compose dyck_hypothesis out_some) + (prove tauto_intu))) + (tclORELSE (tryAllHyps (clauseTacThen + (compose dyck_absurdity_elim out_some) + (prove tauto_intu))) + (tclORELSE (tryAllHyps (clauseTacThen + (compose dyck_and_elim out_some) (prove tauto_intu))) + (tclORELSE (tryAllHyps (clauseTacThen + (compose dyck_atomic_imply_elim out_some) + (prove tauto_intu))) + (tclORELSE (tryAllHyps (clauseTacThen + (compose dyck_and_imply_elim out_some) + (prove tauto_intu))) + (tclORELSE (tryAllHyps (clauseTacThen + (compose dyck_or_imply_elim out_some) + (prove tauto_intu))) + (tclORELSE (tclTHEN dyck_and_intro (prove tauto_intu)) + (tclORELSE (tclTHEN dyck_imply_intro (prove tauto_intu)) + (tclORELSE (tryAllHyps (clauseTacThen + (compose dyck_or_elim out_some) (prove tauto_intu))) + (tclORELSE (tryAllHyps (clauseTacThen (* 28/5/99, ajout par HH *) + (compose dyck_imply_imply_elim out_some) + (prove tauto_intu))) + tauto_intu)))))))))) g + +let tauto gls = + let strToOccs x = ([],Nametab.constant_sp_of_id (id_of_string x)) in + (tclTHEN (onAllClausesLR + (unfold_option [strToOccs "not";strToOccs "iff"])) + (prove tautoOR_0)) gls + +let intuition gls = + let strToOccs x = ([],Nametab.constant_sp_of_id (id_of_string x)) in + (tclTHEN + ((tclTHEN (onAllClausesLR + (unfold_option [strToOccs "not";strToOccs "iff"])) + (prove intuitionOR))) intros) gls + +let tauto_tac = hide_atomic_tactic "Tauto" tauto + +let intuition_tac = hide_atomic_tactic "Intuition" intuition + -- cgit v1.2.3