(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* <O___,, * (see version control and CREDITS file for authors & dates) *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (* * (see LICENSE file for the text of the license) *) (************************************************************************)
(* This file implements the basic congruence-closure algorithm by *) (* Downey, Sethi and Tarjan. *) (* Plus some e-matching and constructor handling by P. Corbineau *)
open CErrors open Pp open Names open Sorts open Constr open Context open Vars open Util open Lazy
let init_size=5
let debug_congruence = CDebug.create ~name:"congruence" ()
(* Signature table *)
module ST=struct
(* l: sign -> term r: term -> sign *)
module IntTable = Hashtbl.Make(Int)
module IntPair = struct type t = int * int let equal (i1, j1) (i2, j2) = Int.equal i1 i2 && Int.equal j1 j2 let hash (i, j) = Hashset.Combine.combine (Int.hash i) (Int.hash j) end
module IntPairTable = Hashtbl.Make(IntPair)
type t = {toterm: int IntPairTable.t;
tosign: (int * int) IntTable.t}
let empty () =
{toterm=IntPairTable.create init_size;
tosign=IntTable.create init_size}
let enter t sign st= if IntPairTable.mem st.toterm sign then
anomaly ~label:"enter" (Pp.str "signature already entered.") else
IntPairTable.replace st.toterm sign t;
IntTable.replace st.tosign t sign
let query sign st=IntPairTable.find st.toterm sign
let delete st t= trylet sign=IntTable.find st.tosign t in
IntPairTable.remove st.toterm sign;
IntTable.remove st.tosign t with
Not_found -> ()
let delete_set st s = Int.Set.iter (delete st) s
end
type pa_constructor=
{ cnode : int;
arity : int;
args : int list}
type pa_fun=
{fsym:int;
fnargs:int}
type pa_mark=
Fmark of pa_fun
| Cmark of pa_constructor
module PacOrd = struct type t = pa_constructor let compare { cnode = cnode0; arity = arity0; args = args0 }
{ cnode = cnode1; arity = arity1; args = args1 } = let cmp = Int.compare cnode0 cnode1 in if cmp = 0 then let cmp' = Int.compare arity0 arity1 in if cmp' = 0 then List.compare Int.compare args0 args1 else
cmp' else
cmp end
module PafOrd = struct type t = pa_fun let compare { fsym = fsym0; fnargs = fnargs0 } { fsym = fsym1; fnargs = fnargs1 } = let cmp = Int.compare fsym0 fsym1 in if cmp = 0 then
Int.compare fnargs0 fnargs1 else
cmp end
let family_eq f1 f2 = match f1, f2 with
| Set, Set
| Prop, Prop
| Type _, Type _ -> true
| _ -> false
type'a term =
Symb of constr * (* Hash: *) int
| Product of Sorts.t * Sorts.t
| Eps of Id.t
| Appli of'a * 'a
| Constructor of cinfo (* constructor arity + nhyps *)
(* terms with eagerly cached constr and hash *)
module ATerm : sig type t val proj : t -> t term val mkSymb : constr -> t val mkProduct : (Sorts.t * Sorts.t) -> t val mkEps : Id.t -> t val mkAppli : (t * t) -> t val mkConstructor : Environ.env -> cinfo -> t
val equal : t -> t -> bool val constr : t -> constr val hash : t -> int val nth_arg : t -> int -> t end = struct type t = {
term : t term;
constr : constr lazy_t;
hash : int }
let rec constr_of_term = function
Symb (s,_) -> s
| Product(s1,s2) -> cc_product s1 s2
| Eps id -> mkVar id
| Constructor cinfo -> mkConstructU cinfo.ci_constr
| Appli (s1',s2') -> make_app [force s2'.constr] s1' and make_app l t' = match t'.term with
Appli (s1',s2')->make_app ((force s2'.constr)::l) s1'
| _ -> Term.applist (force t'.constr, l)
let constr t = force t.constr
let make t = {
term = t;
constr = lazy (constr_of_term t);
hash = hash_term t }
let rec drop_univ c = match kind c with
| Const (c,_u) -> mkConstU (c,UVars.Instance.empty)
| Ind (c,_u) -> mkIndU (c,UVars.Instance.empty)
| Construct (c,_u) -> mkConstructU (c,UVars.Instance.empty)
| Sort (Type _u) -> mkSort (type1)
| _ -> Constr.map drop_univ c
let mkSymb s = make (Symb (s, Constr.hash (drop_univ s)))
let mkProduct (s1, s2) = make (Product (s1, s2))
let mkEps id = make (Eps id)
let mkAppli (t1', t2') = make (Appli (t1', t2'))
let mkConstructor env info = let canon i = Environ.QConstruct.canonize env i in let info = { info with ci_constr = on_fst canon info.ci_constr } in
make (Constructor info)
let rec nth_arg t n = match t.term with
Appli (t1',t2')-> if n>0 then nth_arg t1' (n-1) else t2'
| _ -> anomaly ~label:"nth_arg" (Pp.str "not enough args.") end
type ccpattern =
PApp of ATerm.t * ccpattern list(* arguments are reversed *)
| PVar of int * ccpattern list(* arguments are reversed *)
type axiom = constr
let constr_of_axiom c = c
type rule=
Congruence
| Axiom of axiom * bool
| Injection of int * pa_constructor * int * pa_constructor * int
type from=
Goal
| Hyp of constr
| HeqG of Id.t
| HeqnH of Id.t * Id.t
type'a eq = {lhs:int;rhs:int;rule:'a}
type equality = rule eq
type disequality = from eq
type patt_kind =
Normal
| Trivial of types
| Creates_variables
let rec find_aux uf visited i= let j = uf.map.(i).cpath in if j<0 thenlet () = List.iter (compress_path uf i) visited in i else
find_aux uf (i::visited) j
letfind uf i= find_aux uf [] i
let get_representative uf i= match uf.map.(i).clas with
Rep r -> r
| _ -> anomaly ~label:"get_representative" (Pp.str "not a representative.")
let get_constructors uf i= uf.map.(i).constructors
let rec find_oldest_pac uf i pac= try PacMap.find pac (get_constructors uf i) with
Not_found -> match uf.map.(i).clas with
Eqto (j,_) -> find_oldest_pac uf j pac
| Rep _ -> raise Not_found
let get_constructor_info uf i= match ATerm.proj uf.map.(i).aterm with
Constructor cinfo->cinfo
| _ -> anomaly ~label:"get_constructor" (Pp.str "not a constructor.")
letsize uf i=
(get_representative uf i).weight
let axioms uf c = Constrhash.find uf.axioms c
let epsilons uf = uf.epsilons
let add_lfather uf i t= let r=get_representative uf i in
r.weight<-r.weight+1;
r.lfathers<-Int.Set.add t r.lfathers;
r.fathers <-Int.Set.add t r.fathers
let add_rfather uf i t= let r=get_representative uf i in
r.weight<-r.weight+1;
r.fathers <-Int.Set.add t r.fathers
exception Discriminable of int * pa_constructor * int * pa_constructor
let append_pac t p =
{p with arity=pred p.arity;args=t::p.args}
let tail_pac p=
{p with arity=succ p.arity;args=List.tl p.args}
let fsucc paf =
{paf with fnargs=succ paf.fnargs}
let add_pac node pac t = ifnot (PacMap.mem pac node.constructors) then
node.constructors<-PacMap.add pac t node.constructors
let add_paf rep paf t = let already = try PafMap.find paf rep.functions with Not_found -> Int.Set.empty in
rep.functions<- PafMap.add paf (Int.Set.add t already) rep.functions
let aterm uf i=uf.map.(i).aterm
let subterms uf i= match uf.map.(i).vertex with
Node(j,k) -> (j,k)
| _ -> anomaly ~label:"subterms" (Pp.str "not a node.")
letsignature uf i= let j,k=subterms uf i in (find uf j,find uf k)
let next uf= letsize=uf.sizein let nsize= succ sizein if Int.equal nsize uf.max_size then let newmax=uf.max_size * 3 / 2 + 1 in let newmap=Array.make newmax dummy_node in begin
uf.max_size<-newmax;
Array.blit uf.map 0 newmap 0 size;
uf.map<-newmap end else ();
uf.size<-nsize; size
let new_representative typ =
{weight=0;
lfathers=Int.Set.empty;
fathers=Int.Set.empty;
inductive_status=Unknown;
class_type=typ;
functions=PafMap.empty}
let rec canonize_name c = let c = EConstr.Unsafe.to_constr c in let func c = canonize_name (EConstr.of_constr c) in match Constr.kind c with
| Const (kn,u) -> let canon_const = Constant.make1 (Constant.canonical kn) in
(mkConstU (canon_const,u))
| Ind ((kn,i),u) -> let canon_mind = MutInd.make1 (MutInd.canonical kn) in
(mkIndU ((canon_mind,i),u))
| Construct (((kn,i),j),u) -> let canon_mind = MutInd.make1 (MutInd.canonical kn) in
mkConstructU (((canon_mind,i),j),u)
| Prod (na,t,ct) ->
mkProd (na,func t, func ct)
| Lambda (na,t,ct) ->
mkLambda (na, func t,func ct)
| LetIn (na,b,t,ct) ->
mkLetIn (na, func b,func t,func ct)
| App (ct,l) ->
mkApp (func ct,Array.Smart.map func l)
| Proj(p,r,c) -> let p' = Projection.map (fun kn ->
MutInd.make1 (MutInd.canonical kn)) p in
(mkProj (p', r, func c))
| _ -> c
(* rebuild a term from a pattern and a substitution *)
let build_subst uf subst =
Array.map
(fun i -> try aterm uf i with e when CErrors.noncritical e ->
anomaly (Pp.str "incomplete matching."))
subst
let rec inst_pattern subst = function
PVar (i, args) -> List.fold_right
(fun spat f -> ATerm.mkAppli (f,inst_pattern subst spat))
args subst.(pred i)
| PApp (t', args) -> List.fold_right
(fun spat f -> ATerm.mkAppli (f,inst_pattern subst spat))
args t'
let pr_idx_term env sigma uf i = str "[" ++ int i ++ str ":=" ++
Printer.pr_econstr_env env sigma (EConstr.of_constr (ATerm.constr (aterm uf i))) ++ str "]"
let rec add_aterm state t' = let uf=state.uf in try Termhash.find uf.syms t' with
Not_found -> let b=next uf in let trm = ATerm.constr t' in let typ = Retyping.get_type_of state.env state.sigma (EConstr.of_constr trm) in let typ = canonize_name typ in let new_node= match ATerm.proj t' with
Symb _ | Product (_,_) -> let paf =
{fsym=b;
fnargs=0} in
Queue.add (b,Fmark paf) state.marks;
{clas= Rep (new_representative typ);
cpath= -1;
constructors=PacMap.empty;
vertex= Leaf;
aterm= t'}
| Eps id ->
{clas= Rep (new_representative typ);
cpath= -1;
constructors=PacMap.empty;
vertex= Leaf;
aterm= t'}
| Appli (t1',t2') -> let i1=add_aterm state t1' and i2=add_aterm state t2'in
add_lfather uf (find uf i1) b;
add_rfather uf (find uf i2) b;
state.terms<-Int.Set.add b state.terms;
{clas= Rep (new_representative typ);
cpath= -1;
constructors=PacMap.empty;
vertex= Node(i1,i2);
aterm= t'}
| Constructor cinfo -> let paf =
{fsym=b;
fnargs=0} in
Queue.add (b,Fmark paf) state.marks; let pac =
{cnode= b;
arity= cinfo.ci_arity;
args=[]} in
Queue.add (b,Cmark pac) state.marks;
{clas=Rep (new_representative typ);
cpath= -1;
constructors=PacMap.empty;
vertex=Leaf;
aterm=t'} in
uf.map.(b)<-new_node;
Termhash.add uf.syms t' b;
Typehash.replace state.by_type typ
(Int.Set.add b
(try Typehash.find state.by_type typ with
Not_found -> Int.Set.empty));
b
let add_equality0 state c s' t' = let i = add_aterm state s' in let j = add_aterm state t' in
Queue.add {lhs=i;rhs=j;rule=Axiom(c,false)} state.combine;
Constrhash.add state.uf.axioms c (s',t')
let add_equality state id s t =
add_equality0 state (mkVar id) s t
let add_disequality state from s' t' = let i = add_aterm state s' in let j = add_aterm state t' in
state.diseq<-{lhs=i;rhs=j;rule=from}::state.diseq
let add_quant state id pol (nvars,valid1,patt1,valid2,patt2) =
state.quant<-
{qe_hyp_id= id;
qe_pol= pol;
qe_nvars=nvars;
qe_lhs= patt1;
qe_lhs_valid=valid1;
qe_rhs= patt2;
qe_rhs_valid=valid2}::state.quant
let is_redundant state id args = try let norm_args = Array.map (find state.uf) args in let prev_args = Identhash.find_all state.q_history id in List.exists
(fun old_args ->
Util.Array.for_all2 (fun i j -> Int.equal i (find state.uf j))
norm_args old_args)
prev_args with Not_found -> false
let add_inst state (inst,int_subst) =
Control.check_for_interrupt (); if state.rew_depth > 0 then if is_redundant state inst.qe_hyp_id int_subst then
debug_congruence (fun () -> str "discarding redundant (dis)equality") else begin
Identhash.add state.q_history inst.qe_hyp_id int_subst; let subst = build_subst (forest state) int_subst in let prfhead= mkVar inst.qe_hyp_id in let args = Array.map ATerm.constr subst in let _ = Array.rev args in(* highest deBruijn index first *) let prf= mkApp(prfhead,args) in let s = inst_pattern subst inst.qe_lhs and t = inst_pattern subst inst.qe_rhs in
state.changed<-true;
state.rew_depth<-pred state.rew_depth; if inst.qe_pol then begin
debug_congruence (fun () ->
(str "Adding new equality, depth="++ int state.rew_depth) ++ fnl () ++
(str " [" ++ Printer.pr_econstr_env state.env state.sigma (EConstr.of_constr prf) ++ str " : " ++
pr_term state.env state.sigma s ++ str " == " ++ pr_term state.env state.sigma t ++ str "]"));
add_equality0 state prf s t end else begin
debug_congruence (fun () ->
(str "Adding new disequality, depth="++ int state.rew_depth) ++ fnl () ++
(str " [" ++ Printer.pr_econstr_env state.env state.sigma (EConstr.of_constr prf) ++ str " : " ++
pr_term state.env state.sigma s ++ str " <> " ++ pr_term state.env state.sigma t ++ str "]"));
add_disequality state (Hyp prf) s t end end
let link uf i j eq = (* links i -> j *) let node=uf.map.(i) in
node.clas<-Eqto (j,eq);
node.cpath<-j
let rec down_path uf i l= match uf.map.(i).clas with
Eqto (j,eq) ->down_path uf j (((i,j),eq)::l)
| Rep _ ->l
let rec min_path=function
([],l2)->([],l2)
| (l1,[])->(l1,[])
| (((c1,t1)::q1),((c2,t2)::q2)) when eq_pair c1 c2 -> min_path (q1,q2)
| cpl -> cpl
let join_path uf i j=
assert (Int.equal (find uf i) (find uf j));
min_path (down_path uf i [],down_path uf j [])
let union state i1 i2 eq=
debug_congruence (fun () -> str "Linking " ++ pr_idx_term state.env state.sigma state.uf i1 ++
str " and " ++ pr_idx_term state.env state.sigma state.uf i2 ++ str "."); let r1= get_representative state.uf i1 and r2= get_representative state.uf i2 in
link state.uf i1 i2 eq;
Constrhash.replace state.by_type r1.class_type
(Int.Set.remove i1
(try Constrhash.find state.by_type r1.class_type with
Not_found -> Int.Set.empty)); let f= Int.Set.union r1.fathers r2.fathers in
r2.weight<-Int.Set.cardinal f;
r2.fathers<-f;
r2.lfathers<-Int.Set.union r1.lfathers r2.lfathers;
ST.delete_set state.sigtable r1.fathers;
state.terms<-Int.Set.union state.terms r1.fathers;
PacMap.iter
(fun pac b -> Queue.add (b,Cmark pac) state.marks)
state.uf.map.(i1).constructors;
PafMap.iter
(fun paf -> Int.Set.iter
(fun b -> Queue.add (b,Fmark paf) state.marks))
r1.functions; match r1.inductive_status,r2.inductive_status with
Unknown,_ -> ()
| Partial pac,Unknown ->
r2.inductive_status<-Partial pac;
state.pa_classes<-Int.Set.remove i1 state.pa_classes;
state.pa_classes<-Int.Set.add i2 state.pa_classes
| Partial _ ,(Partial _ |Partial_applied) ->
state.pa_classes<-Int.Set.remove i1 state.pa_classes
| Partial_applied,Unknown ->
r2.inductive_status<-Partial_applied
| Partial_applied,Partial _ ->
state.pa_classes<-Int.Set.remove i2 state.pa_classes;
r2.inductive_status<-Partial_applied
| Total cpl,Unknown -> r2.inductive_status<-Total cpl;
| Total (i,pac),Total _ -> Queue.add (i,Cmark pac) state.marks
| _,_ -> ()
let merge eq state = (* merge and no-merge *)
debug_congruence
(fun () -> str "Merging " ++ pr_idx_term state.env state.sigma state.uf eq.lhs ++
str " and " ++ pr_idx_term state.env state.sigma state.uf eq.rhs ++ str "."); let uf=state.uf in let i=find uf eq.lhs and j=find uf eq.rhs in ifnot (Int.equal i j) then if (size uf i)<(size uf j) then
union state i j eq else
union state j i (swap eq)
let update t state = (* update 1 and 2 *)
debug_congruence
(fun () -> str "Updating term " ++ pr_idx_term state.env state.sigma state.uf t ++ str "."); let (i,j) as sign = signature state.uf t in let (u,v) = subterms state.uf t in let rep = get_representative state.uf i in begin match rep.inductive_status with
Partial _ ->
rep.inductive_status <- Partial_applied;
state.pa_classes <- Int.Set.remove i state.pa_classes
| _ -> () end;
PacMap.iter
(fun pac _ -> Queue.add (t,Cmark (append_pac v pac)) state.marks)
(get_constructors state.uf i);
PafMap.iter
(fun paf _ -> Queue.add (t,Fmark (fsucc paf)) state.marks)
rep.functions; try let s = ST.query sign state.sigtable in
Queue.add {lhs=t;rhs=s;rule=Congruence} state.combine with
Not_found -> ST.enter t sign state.sigtable
let process_function_mark t rep paf state =
add_paf rep paf t;
state.terms<-Int.Set.union rep.lfathers state.terms
let process_constructor_mark t i rep pac state =
add_pac state.uf.map.(i) pac t; match rep.inductive_status with
Total (s,opac) -> ifnot (Int.equal pac.cnode opac.cnode) then(* Conflict *) raise (Discriminable (s,opac,t,pac)) else(* Match *) let cinfo = get_constructor_info state.uf pac.cnode in let rec f n oargs args= if n > 0 then match (oargs,args) with
s1::q1,s2::q2->
Queue.add
{lhs=s1;rhs=s2;rule=Injection(s,opac,t,pac,n)}
state.combine;
f (n-1) q1 q2
| _-> anomaly ~label:"add_pacs"
(Pp.str "weird error in injection subterms merge.") in f cinfo.ci_nhyps opac.args pac.args
| Partial_applied | Partial _ -> (* add_pac state.uf.map.(i) pac t; *)
state.terms<-Int.Set.union rep.lfathers state.terms
| Unknown -> if Int.equal pac.arity 0 then
rep.inductive_status <- Total (t,pac) else begin (* add_pac state.uf.map.(i) pac t; *)
state.terms<-Int.Set.union rep.lfathers state.terms;
rep.inductive_status <- Partial pac;
state.pa_classes<- Int.Set.add i state.pa_classes end
let process_mark t m state =
debug_congruence
(fun () -> str "Processing mark for term " ++ pr_idx_term state.env state.sigma state.uf t ++ str "."); let i=find state.uf t in let rep=get_representative state.uf i in match m with
Fmark paf -> process_function_mark t rep paf state
| Cmark pac -> process_constructor_mark t i rep pac state
type explanation =
Discrimination of (int*pa_constructor*int*pa_constructor)
| Contradiction of disequality
| Incomplete of (EConstr.t * int) list
let check_disequalities state = let uf=state.uf in let rec check_aux = function
| dis::q -> let (info, ans) = if Int.equal (find uf dis.lhs) (find uf dis.rhs) then (str "Yes", Some dis) else (str "No", check_aux q) in let _ = debug_congruence
(fun () -> str "Checking if " ++ pr_idx_term state.env state.sigma state.uf dis.lhs ++ str " = " ++
pr_idx_term state.env state.sigma state.uf dis.rhs ++ str " ... " ++ info) in
ans
| [] -> None in
check_aux state.diseq
let one_step state = try let eq = Queue.take state.combine in
merge eq state; true with Queue.Empty -> try let (t,m) = Queue.take state.marks in
process_mark t m state; true with Queue.Empty -> try let t = Int.Set.choose state.terms in
state.terms<-Int.Set.remove t state.terms;
update t state; true with Not_found -> false
let __eps__ = Id.of_string "_eps_"
let new_state_var typ state = let ids = Environ.ids_of_named_context_val (Environ.named_context_val state.env) in let id = Namegen.next_ident_away __eps__ ids in let r = EConstr.ERelevance.relevant in(* TODO relevance *)
state.env<- EConstr.push_named (Context.Named.Declaration.LocalAssum (make_annot id r,typ)) state.env;
id
let complete_one_class state i= match (get_representative state.uf i).inductive_status with
| Partial pac -> let rec app t' typ n = if n<=0 then t' else let _,etyp,rest= destProd typ in let id = new_state_var (EConstr.of_constr etyp) state in app (ATerm.mkAppli (t',ATerm.mkEps id)) (substl [mkVar id] rest) (n-1) in let c = Retyping.get_type_of state.env state.sigma
(EConstr.of_constr (ATerm.constr (aterm state.uf pac.cnode))) in let c = EConstr.Unsafe.to_constr c in let args = List.map (fun i -> ATerm.constr (aterm state.uf i))
pac.args in let typ = Term.prod_applist c (List.rev args) in let ct = app (aterm state.uf i) typ pac.arity in
state.uf.epsilons <- pac :: state.uf.epsilons;
ignore (add_aterm state ct)
| _ -> anomaly (Pp.str "wrong incomplete class.")
let complete state =
Int.Set.iter (complete_one_class state) state.pa_classes
type matching_problem =
{mp_subst : int array;
mp_inst : quant_eq;
mp_stack : (ccpattern*int) list }
let make_fun_table state = let uf= state.uf in let funtab=ref PafMap.empty in
Array.iteri
(fun i inode -> if i < uf.sizethen match inode.clas with
Rep rep ->
PafMap.iter
(fun paf _ -> let elem = try PafMap.find paf !funtab with Not_found -> Int.Set.empty in
funtab:= PafMap.add paf (Int.Set.add i elem) !funtab)
rep.functions
| _ -> ()) state.uf.map;
!funtab
let do_match state res pb_stack = let mp=Stack.pop pb_stack in match mp.mp_stack with
[] ->
res:= (mp.mp_inst,mp.mp_subst) :: !res
| (patt,cl)::remains -> let uf=state.uf in match patt with
PVar (i, []) -> if mp.mp_subst.(pred i)<0 then begin
mp.mp_subst.(pred i)<- cl; (* no aliasing problem here *)
Stack.push {mp with mp_stack=remains} pb_stack end else if Int.equal mp.mp_subst.(pred i) cl then
Stack.push {mp with mp_stack=remains} pb_stack else(* mismatch for non-linear variable in pattern *) ()
| PVar _ -> () (* do not consider application with variable head *)
| PApp (f,[]) -> begin trylet j=Termhash.find uf.syms f in if Int.equal (find uf j) cl then
Stack.push {mp with mp_stack=remains} pb_stack with Not_found -> () end
| PApp(f, ((last_arg::rem_args) as args)) -> try let j=Termhash.find uf.syms f in let paf={fsym=j;fnargs=List.length args} in let rep=get_representative uf cl in let good_terms = PafMap.find paf rep.functions in let aux i = let (s,t) = signature state.uf i in
Stack.push
{mp with
mp_subst=Array.copy mp.mp_subst;
mp_stack=
(PApp(f,rem_args),s) ::
(last_arg,t) :: remains} pb_stack in
Int.Set.iter aux good_terms with Not_found -> ()
let paf_of_patt syms = function
PVar _ -> invalid_arg "paf_of_patt: pattern with variable head"
| PApp (f,args) ->
{fsym=Termhash.find syms f;
fnargs=List.length args}
let init_pb_stack state = let syms= state.uf.syms in let pb_stack = Stack.create () in let funtab = make_fun_table state in let aux inst = begin let good_classes = match inst.qe_lhs_valid with
Creates_variables -> Int.Set.empty
| Normal -> begin try let paf= paf_of_patt syms inst.qe_lhs in
PafMap.find paf funtab with Not_found -> Int.Set.empty end
| Trivial typ -> begin try
Typehash.find state.by_type typ with Not_found -> Int.Set.empty endin
Int.Set.iter (fun i ->
Stack.push
{mp_subst = Array.make inst.qe_nvars (-1);
mp_inst=inst;
mp_stack=[inst.qe_lhs,i]} pb_stack) good_classes end; begin let good_classes = match inst.qe_rhs_valid with
Creates_variables -> Int.Set.empty
| Normal -> begin try let paf= paf_of_patt syms inst.qe_rhs in
PafMap.find paf funtab with Not_found -> Int.Set.empty end
| Trivial typ -> begin try
Typehash.find state.by_type typ with Not_found -> Int.Set.empty endin
Int.Set.iter (fun i ->
Stack.push
{mp_subst = Array.make inst.qe_nvars (-1);
mp_inst=inst;
mp_stack=[inst.qe_rhs,i]} pb_stack) good_classes endin List.iter aux state.quant;
pb_stack
let find_instances state = let pb_stack= init_pb_stack state in let res =ref [] in let _ =
debug_congruence (fun () -> str "Running E-matching algorithm ... "); try whiletruedo
Control.check_for_interrupt ();
do_match state res pb_stack
done;
anomaly (Pp.str "get out of here!") with Stack.Empty -> () in
!res
let build_term_to_complete uf pac = letopen EConstr in let cinfo = get_constructor_info uf pac.cnode in let real_args = List.rev_map (fun i -> EConstr.of_constr (ATerm.constr (aterm uf i))) pac.args in let (kn, u) = cinfo.ci_constr in
(applist (mkConstructU (kn, EInstance.make u), real_args), pac.arity)
let terms_to_complete state = let uf = forest state in List.map (build_term_to_complete uf) (epsilons uf)
let rec execute first_run state =
debug_congruence (fun () -> str "Executing ... "); try while
Control.check_for_interrupt ();
one_step state do ()
done; match check_disequalities state with
None -> ifnot(Int.Set.is_empty state.pa_classes) then begin
debug_congruence (fun () -> str "First run was incomplete, completing ... ");
complete state;
execute false state end else if state.rew_depth>0 then let l=find_instances state in List.iter (add_inst state) l; if state.changed then begin
state.changed <- false;
execute true state end else begin
debug_congruence (fun () -> str "Out of instances ... ");
None end else begin
debug_congruence (fun () -> str "Out of depth ... ");
None end
| Some dis -> Some begin if first_run then Contradiction dis else Incomplete (terms_to_complete state) end with Discriminable(s,spac,t,tpac) -> Some begin if first_run then Discrimination (s,spac,t,tpac) else Incomplete (terms_to_complete state) end
¤ Dauer der Verarbeitung: 0.35 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.