123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180moduletypeDFA=sigmoduleStates:Finite.SetmoduleTransitions:Finite.SetmoduleLabel:Map.OrderedTypevallabel:Transitions.element->Label.tvalsource:Transitions.element->States.elementvaltarget:Transitions.element->States.elementvalinitial_state:States.elementmoduleFinal:Finite.Mapwithtypecodomain=States.elementendletindex_transitions(typestate)(typetransition)(states:stateFinite.set)(transitions:transitionFinite.set)(target:transitionFinite.element->stateFinite.element):stateFinite.element->transitionFinite.elementFinite.map=letf=Array.make(Finite.cardinalstates+1)0inFinite.Element.itertransitions(funt->letstate=(targett:>int)inf.(state)<-f.(state)+1);fori=0toFinite.cardinalstates-1dof.(i+1)<-f.(i+1)+f.(i)done;leta=Array.make(Finite.cardinaltransitions)(Finite.Element.of_inttransitions0)inFinite.Element.rev_itertransitions(funt->letstate=(targett:>int)inletindex=f.(state)-1inf.(state)<-index;a.(index)<-t);(funst->letst=(st:stateFinite.element:>int)inletoffset=f.(st)inletn=f.(st+1)-offsetin(modulestructmoduleDomain=Finite.Set(structletn=nend)typecodomain=transitionFinite.elementletelementn=a.(offset+(n:Domain.element:>int))end))letdiscard_unreachable(typestate)(typetransition)(blocks:statePartition.t)(transitions_of:stateFinite.element->transitionFinite.elementFinite.map)(target:transitionFinite.element->stateFinite.element)=Partition.iter_marked_elementsblocks0(funstate->Finite.iter_map(transitions_ofstate)(funtransition->Partition.markblocks(targettransition)););Partition.discard_unmarkedblocksmoduleMinimize(DFA:DFA):sigincludeDFAwithmoduleLabel=DFA.Labelvaltransport_state:DFA.States.tFinite.element->States.tFinite.elementoptionvaltransport_transition:DFA.Transitions.tFinite.element->Transitions.tFinite.elementoptionvalrepresent_state:States.tFinite.element->DFA.States.tFinite.elementvalrepresent_transition:Transitions.tFinite.element->DFA.Transitions.tFinite.elementend=struct(* State partition *)letblocks=Partition.create(moduleDFA.States)(* Remove states unreachable from initial state *)let()=Partition.markblocksDFA.initial_state;lettransitions_source=index_transitions(moduleDFA.States)(moduleDFA.Transitions)DFA.sourceindiscard_unreachableblockstransitions_sourceDFA.target(* Index the set of transitions targeting a state *)lettransitions_targeting=index_transitions(moduleDFA.States)(moduleDFA.Transitions)DFA.target(* Remove states unreachable from final states *)let()=Finite.iter_map(moduleDFA.Final)(Partition.markblocks);discard_unreachableblockstransitions_targetingDFA.source(* Split final states *)let()=Finite.iter_map(moduleDFA.Final)(Partition.markblocks);Partition.splitblocks(* Transition partition *)letcords=Partition.create(moduleDFA.Transitions)~partition:(funt1t2->letl1=DFA.labelt1inletl2=DFA.labelt2inDFA.Label.comparel1l2)let()=Partition.discardcords(funt->Partition.set_ofblocks(DFA.sourcet)=-1||Partition.set_ofblocks(DFA.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(DFA.sourcetransition));Partition.splitblocks;while!block_set<Partition.set_countblocksdoPartition.iter_elementsblocks!block_set(funstate->Finite.iter_map(transitions_targetingstate)(Partition.markcords));Partition.splitcords;incrblock_set;done;incrcord_set;donemoduleStates=Finite.Set(structletn=Partition.set_countblocksend)moduleTransitions=Finite.Set(structletn=Partition.set_countcordsend)moduleLabel=DFA.Labellettransport_state_unsafestate=Finite.Element.of_int(moduleStates)(Partition.set_ofblocksstate)letrepresent_statestate=Partition.chooseblocks(state:States.tFinite.element:>int)letrepresent_transitiontransition=Partition.choosecords(transition:Transitions.tFinite.element:>int)letlabeltransition:Label.t=DFA.label(represent_transitiontransition)letsourcetransition=transport_state_unsafe(DFA.source(represent_transitiontransition))lettargettransition=transport_state_unsafe(DFA.target(represent_transitiontransition))letinitial_state=Finite.Element.of_int(moduleStates)(Partition.set_ofblocksDFA.initial_state)moduleFinal=Finite.Map_of_array(structtypecodomain=States.tFinite.elementlettable=Finite.iter_map(moduleDFA.Final)(Partition.markblocks);letsets=Partition.marked_setsblocksinPartition.clear_marksblocks;Array.map(Finite.Element.of_int(moduleStates))(Array.of_listsets)end)lettransport_statestate=matchPartition.set_ofblocksstatewith|-1->None|n->Some(Finite.Element.of_int(moduleStates)n)lettransport_transitiontransition=matchPartition.set_ofcordstransitionwith|-1->None|n->Some(Finite.Element.of_int(moduleTransitions)n)end