123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234moduleFin=Strong.FinitemoduletypeDFA=sigtypestatesvalstates:statesFin.settypetransitionsvaltransitions:transitionsFin.settypelabelvallabel:transitionsFin.elt->labelvalsource:transitionsFin.elt->statesFin.eltvaltarget:transitionsFin.elt->statesFin.eltendmoduletypeINPUT=sigincludeDFAvalinitials:(statesFin.elt->unit)->unitvalfinals:(statesFin.elt->unit)->unitvalrefinements:refine:(iter:((statesFin.elt->unit)->unit)->unit)->unitendletindex_transitions(typestate)(typetransition)(states:stateFin.set)(transitions:transitionFin.set)(target:transitionFin.elt->stateFin.elt):stateFin.elt->(transitionFin.elt->unit)->unit=letf=Array.make(Fin.Set.cardinalstates+1)0inFin.Set.itertransitions(funt->letstate=(targett:>int)inf.(state)<-f.(state)+1);fori=0toFin.Set.cardinalstates-1dof.(i+1)<-f.(i+1)+f.(i)done;leta=Array.make(Fin.Set.cardinaltransitions)(Fin.Elt.of_inttransitions0)inFin.Set.rev_itertransitions(funt->letstate=(targett:>int)inletindex=f.(state)-1inf.(state)<-index;a.(index)<-t);(funstfn->letst=(st:stateFin.elt:>int)infori=f.(st)tof.(st+1)-1dofna.(i)done)letdiscard_unreachable(typestate)(typetransition)(blocks:statePartition.t)(transitions_of:stateFin.elt->(transitionFin.elt->unit)->unit)(target:transitionFin.elt->stateFin.elt)=Partition.iter_marked_elementsblocks0(funstate->transitions_ofstate(funtransition->Partition.markblocks(targettransition)));Partition.discard_unmarkedblocksmoduleMinimize(Label:Map.OrderedType)(In:INPUTwithtypelabel:=Label.t):sigincludeDFAwithtypelabel=Label.tvalinitials:statesFin.eltarrayvalfinals:statesFin.eltarrayvaltransport_state:In.statesFin.elt->statesFin.eltoptionvaltransport_transition:In.transitionsFin.elt->transitionsFin.eltoptionvalrepresent_state:statesFin.elt->In.statesFin.eltvalrepresent_transition:transitionsFin.elt->In.transitionsFin.eltend=struct(* State partition *)letblocks=Partition.createIn.states(* Remove states unreachable from initial state *)let()=In.initials(Partition.markblocks);lettransitions_source=index_transitionsIn.statesIn.transitionsIn.sourceindiscard_unreachableblockstransitions_sourceIn.target(* Index the set of transitions targeting a state *)lettransitions_targeting=index_transitionsIn.statesIn.transitionsIn.target(* Remove states which cannot reach any final state *)let()=In.finals(Partition.markblocks);discard_unreachableblockstransitions_targetingIn.source(* Split final states *)let()=In.finals(Partition.markblocks);Partition.splitblocks(* Split explicitely refined states *)let()=letrefine~iter=iter(Partition.markblocks);Partition.splitblocksinIn.refinements~refine(* Transition partition *)letcords=letpartitiont1t2=Label.compare(In.labelt1)(In.labelt2)inPartition.createIn.transitions~partitionlet()=Partition.discardcords(funt->Partition.set_ofblocks(In.sourcet)=-1||Partition.set_ofblocks(In.targett)=-1)(* Main loop, split the sets *)let()=letblock_set=ref1inletcord_set=ref0inwhile!cord_set<Partition.set_countcordsdoPartition.iter_elementscords!cord_set(funtransition->Partition.markblocks(In.sourcetransition));Partition.splitblocks;while!block_set<Partition.set_countblocksdoPartition.iter_elementsblocks!block_set(funstate->transitions_targetingstate(Partition.markcords));Partition.splitcords;incrblock_set;done;incrcord_set;donemoduleStates=Strong.Natural.Nth(structletn=Partition.set_countblocksend)typestates=States.nletstates=States.nmoduleTransitions=Fin.Array.Of_array(structtypea=In.transitionsFin.eltlettable=letcount=ref0inFin.Set.iterIn.transitions(funtr->ifPartition.is_firstblocks(In.sourcetr)&&Partition.set_ofblocks(In.targettr)>-1thenincrcount);match!countwith|0->[||]|n->Array.maken(Fin.Elt.of_intIn.transitions0)let()=letcount=ref0inFin.Set.iterIn.transitions(funtr->ifPartition.is_firstblocks(In.sourcetr)&&Partition.set_ofblocks(In.targettr)>-1then(letindex=!countinincrcount;table.(index)<-tr));end)typetransitions=Transitions.nlettransitions=Transitions.ntypelabel=Label.tlettransport_state_unsafe=lettable=Fin.Array.initIn.states(Partition.set_ofblocks)inFin.Array.gettableletrepresent_state=lettable=Fin.Array.initstates(funst->Partition.chooseblocks(st:statesFin.elt:>int))inFin.Array.gettableletrepresent_transitiontransition=Fin.(Transitions.table.(transition))letlabeltransition:Label.t=In.label(represent_transitiontransition)letsourcetransition=Fin.Elt.of_intstates(transport_state_unsafe(In.source(represent_transitiontransition)))lettargettransition=Fin.Elt.of_intstates(transport_state_unsafe(In.target(represent_transitiontransition)))letinitials=In.initials(Partition.markblocks);letsets=Partition.marked_setsblocksinPartition.clear_marksblocks;Array.map(Fin.Elt.of_intstates)(Array.of_listsets)letfinals=In.finals(Partition.markblocks);letsets=Partition.marked_setsblocksinPartition.clear_marksblocks;Array.map(Fin.Elt.of_intstates)(Array.of_listsets)lettransport_statestate=matchtransport_state_unsafestatewith|-1->None|n->Some(Fin.Elt.of_intstatesn)lettransport_transition=lettable=Fin.Array.makeIn.transitionsNoneinFin.Array.iteri(funtrtrin->assert(Fin.Array.gettabletrin=None);Fin.Array.settabletrin(Sometr);)Transitions.table;Fin.Array.gettableend