Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file Congruence.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197(* This file is free software, part of Zipperposition. See file "license" for more details. *)(** {1 Simple and Lightweight Congruence and order} *)moduletypeS=Congruence_intf.S(** The graph used for the congruence *)moduletypeTERM=sigtypetvalequal:t->t->boolvalhash:t->intvalsubterms:t->tlist(** Subterms of the term (possibly empty list) *)valupdate_subterms:t->tlist->t(** Replace immediate subterms by the given list.
This is used to test for equality *)valpp:tCCFormat.printerendmoduleMake(T:TERM)=structtypeterm=T.tmoduleH=CCPersistentHashtbl.Make(structtypet=termletequal=T.equallethash=T.hashend)(** Maps terms to their list of immediate parents, and current
representative *)typet={parents:termlistH.t;(* parent terms *)mutablenext:termH.t;(* pointer towards representative *)}letcreate?(size=64)()={parents=H.createsize;next=H.createsize;}(* update [node.next] to be [next] *)let[@inline]set_next_cctnext:t={ccwithnext=H.replacecc.nexttnext}(* update [node.parents] to be [parents] *)let[@inline]set_parents_cctparents:t={ccwithparents=H.replacecc.parentstparents}let[@inline]next_cct=H.gettcc.next|>CCOpt.get_or~default:tlet[@inline]parents_cct=H.gettcc.parents|>CCOpt.get_or~default:[](* find representative *)letrecfind_cc(t:term):term=letnext=next_cctinifT.equaltnextthent(* root *)else(letroot=find_ccnextin(* path compression. Can be done in place as it doesn't change
the semantics of the CC *)ifnot(T.equalrootnext)then(cc.next<-H.replacecc.nexttroot;);root)(* are two nodes, with their subterm lists, congruent? To
check this, we compute the representative of subnodes
and we check whether updated subterms are equal *)letare_congruent_cct1t2=letl1'=List.map(find_cc)(T.subtermst1)inletl2'=List.map(find_cc)(T.subtermst2)intrylett1=T.update_subtermst1l1'inlett2=T.update_subtermst2l2'inT.equalt1t2withType.ApplyError_->false(* merge n1 and n2 equivalence classes *)letrecmerge_cc(t1:term)(t2:term):t=(* get representatives *)lett1=find_cct1inlett2=find_cct2inifT.equalt1t2thenccelse(letleft,right=parents_cct1,parents_cct2in(* n1 now points to n2, put every class information in n2 *)letcc=set_next_cct1t2inletcc=set_parents_cct2(List.rev_appendleftright)in(* check congruence of parents of n1 and n2 *)List.fold_left(funccp1->List.fold_left(funccp2->ifnot(T.equalp1p2)&&are_congruent_ccp1p2then(merge_ccp1p2)elsecc)ccright)ccleft)(* add [t] to the CC *)letrecaddcc(t:term):t=ifH.memcc.parentstthen(assert(H.memcc.nextt);cc)else(letsubs=T.subtermstinletcc=set_parents_cct[]inletcc=set_next_ccttin(* add subterms *)letcc=List.fold_leftaddccsubsin(* add [t] to list of subterms *)letcc=List.fold_left(funccsub->letrepr=find_ccsubinset_parents_ccrepr(t::parents_ccrepr))ccsubsinletcc=List.fold_left(funccsub->letparents=find_ccsub|>parents_ccinList.fold_left(funccparent_sub->ifnot(T.equaltparent_sub)&&are_congruent_cctparent_subthen(merge_cctparent_sub)elsecc)ccparents)ccsubsincc)letiterccf=H.itercc.next(funmem_->letrepr=find_ccmeminf~mem~repr)letiter_rootsccf=H.itercc.next(funtnext->ifT.equaltnextthenft)let[@inline]mk_eqcct1t2=letcc=addcct1inletcc=addcct2inmerge_cct1t2let[@inline]is_eqcct1t2=letcc=addcct1inletcc=addcct2inT.equal(find_cct1)(find_cct2)letpp_debugout(cc:t):unit=letmoduleFmt=CCFormatinletpp_parentout(t,l)=Fmt.fprintfout"(@[<hv1>parents@ :of %a@ (@[<v>%a@])@])"T.ppt(Util.pp_list~sep:" "T.pp)landpp_nextout(t,u)=Fmt.fprintfout"(@[<hv>next@ :of %a@ :is %a@])"T.pptT.ppuinFmt.fprintfout"(@[<v>cc@ :parent_tbl (@[<v>%a@])@ :next_tbl (@[<v>%a@])@])"(Util.pp_iterpp_parent)(H.to_itercc.parents)(Util.pp_iterpp_next)(H.to_itercc.next)endmoduleFO=Make(structmoduleT=Termtypet=T.tletequal=T.equallethash=T.hashletpp=T.ppletsubtermst=matchT.Classic.viewtwith|T.Classic.App(_,l)->l|_->[]letupdate_subtermstl=matchT.viewt,lwith|T.App(hd,l),l'whenList.lengthl=List.lengthl'->T.apphdl'|_,[]->t|_->assertfalseend)