123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377(**********************************************************************)(* *)(* LASCAr *)(* *)(* Copyright (c) 2017-present, Jocelyn SEROT. All rights reserved. *)(* *)(* This source code is licensed under the license found in the *)(* LICENSE file in the root directory of this source tree. *)(* *)(**********************************************************************)openUtilsmoduletypeSTATE=OrderedTypeExt.TmoduletypeLABEL=OrderedTypeExt.TmoduletypeATTR=Ltsa.ATTRmoduletypeT=sigtypestate(** The type of state identifiers *)typelabel(** The type of transition labels *)moduleRepr:Ltsa.Twithtypestate=stateandtypelabel=labelandtypeattr=unit(** The underlying representation : a LTS for which state attributes have type [unit]. *)typet=Repr.tvalrepr_of:t->Repr.tvalof_repr:Repr.t->ttypetransition=state*label*state(** The type for transition. A transition is a triplet [(s1,l,s2)], where [s1] is the
source state, [s2] the destination state and [l] the transition label *)typeitransition=label*state(** The type for initial transition. An initial transition is a pair [(l,s)], where
[s] is the destination state and [l] the transition label *)moduleState:STATEwithtypet=statemoduleLabel:LABELwithtypet=labelmoduleStates:Set.Swithtypeelt=statevalstates:t->States.t(** Returns the set of states *)valstates':t->statelist(** Returns the list of states *)valistates:t->States.t(** Returns the set of initial states *)valistates':t->statelist(** Returns the list of initial states *)valtransitions:t->transitionlist(** Returns the list of transitions *)valitransitions:t->itransitionlist(** Returns the list of initial transitions *)valstring_of_state:state->string(** A synonym of {!State.to_string} *)valstring_of_label:label->string(** A synonym of {!Label.to_string} *)valstring_of_transition:transition->string(** {6 Inspectors} *)valis_state:t->state->bool(** [is_state s q] returns true iff [q] is a state in [s] *)valis_init_state:t->state->bool(** [is_init s q] returns true iff [q] is an initial state in [s] *)valis_reachable:t->state->bool(** [is_reachable s q] returns true iff [q] is a reachable state in [s], {i i.e.} if it
can be reached from an initial state using the transitio relation. *)valis_transition:t->transition->bool(** [is_transition t q] returns true iff [t] is a transition in [s] *)valsuccs:t->state->States.t(** [succs s q] returns the set of immediate successors in [s], {i i.e.} the set of state [q'] such that
there exists a transition [(q,l,q')] in [R].
Raise Invalid_argument if [q] is not in [s]. *)valsuccs':t->state->(state*label)list(** [succs' s q] returns the list of immediate successors, with the associated transition label, of state [q] in [s].
Raise Invalid_argument if [q] is not in [s]. *)valpreds:t->state->States.t(** [preds s q] returns the set of immediate predecessors of state [q] in [s], {i i.e.} the set of state [q'] such that
there exists a transition [(q',l,q)] in [R].
Raise Invalid_argument if [q] is not in [s]. *)valpreds':t->state->(state*label)list(** [preds' s q] returns the list of immediate predecessors, with the associated transition label, of state [q] in [s].
Raise Invalid_argument if [q] is not in [s]. *)valsuccs_hat:t->state->States.t(** Transitive closure of [succs].
[succs_hat s q] returns all the successors (immediate or not) of [q] in [s] *)valpreds_hat:t->state->States.t(** Transitive closure of [preds].
[preds_hat s q] returns all the predecessors (immediate or not) of [q] in [s] *)(** {6 Building functions} *)valempty:t(** The empty LTS (no state, no transition) *)valcreate:states:statelist->itrans:(label*state)list->trans:(state*label*state)list->t(** [create qs q0s ts] builds a LTS from
- a list of states identifiers
- a list of initial transitions, where each transition is given as [(label,dst_state)]
- a list of transitions [ts], where each transition is given as [(src_state,label,dst_state)] *)valadd_state:state->t->t(** [add_state q s] returns the LTS obtained by adding state [q] to [s].
Returns [s] is [q] is already a state in [s] *)exceptionInvalid_stateofstatevaladd_transition:state*label*state->t->t(** [add_transition (q1,l,q2) s] returns the LTS obtained by adding transition from state [q1]
to state [q2], with label [l] to LTS [s].
Raises [Invalid_state] if [q1] or [q2] are not states of [s] *)valadd_itransition:label*state->t->t(** [add_itransition (l,q) s] returns the LTS obtained by adding initial transition to state [q],
with label [l] to LTS [s].
Raises [Invalid_state] if [q] are is not a state of [s] *)valremove_state:state->t->t(** [remove_state q s] returns the LTS obtained by removing state [q], and all attached transitions, from [s].
Raises [Invalid_state] is [q] is not a state in [s] *)(** {6 Global iterators} *)valiter_states:(state->unit)->t->unit(** [iter_states f s] applies function [f] to all states (with associated attribute) of [s] *)valfold_states:(state->'a->'a)->t->'a->'a(** [fold_states f s z] computes [f xN ... (f x2 (f x1 z))...], where [x1], ..., [xN] are all the states of [s] *)valiter_transitions:(transition->unit)->t->unit(** [iter_transitions f s] applies function [f] to all transitions of [s] *)valfold_transitions:(transition->'a->'a)->t->'a->'a(** [fold_transitions f s z] computes [f xN ... (f x2 (f x1 z))...], where [x1], ..., [xN] are all the transitions of [s] *)valiter_itransitions:(itransition->unit)->t->unit(** [iter_itransitions f s] applies function [f] to all initial transitions of [s] *)valfold_itransitions:(itransition->'a->'a)->t->'a->'a(** [fold_itransitions f s z] computes [f xN ... (f x2 (f x1 z))...], where [x1], ..., [xN] are all the initial transitions of [s] *)(** {6 State iterators} *)valfold_succs:t->state->(state->label->'a->'a)->'a->'a(** [fold_succs s x f z] computes [f xN lN ... (f x2 (f x1 l1 z) l2)...], where [x1], ..., [xN] are all the
successors of state [x] in LTS [s], and [l1], ..., [lN] the associated transitions labels *)valiter_succs:t->state->(state->label->unit)->unit(** [iter_succs s x f z] computes [f x1 l1; ... ;f xN lN], where [x1], ..., [xN] are all the
successors of state [x] in LTS [s], and [l1], ..., [lN] the associated transitions labels *)valfold_preds:t->state->(state->label->'a->'a)->'a->'a(** [fold_preds s x f z] computes [f xN lN ... (f x2 (f x1 l1 z) l2)...], where [x1], ..., [xN] are all the
predecessors of state [x] in LTS [s], and [l1], ..., [lN] the associated transitions labels *)valiter_preds:t->state->(state->label->unit)->unit(** [iter_preds s x f z] computes [f x1 l1; ... ;f xN lN], where [x1], ..., [xN] are all the
predecessors of state [x] in LTS [s], and [l1], ..., [lN] the associated transitions labels *)(** {6 Global transformations} *)valmap_label:(label->label)->t->tvalclean:t->t(** {6 Output functions} *)valdot_output:string->?fname:string->?options:Dot.graph_stylelist->?marked_states:(state*Dot.node_style)list->?extra_nodes:(string*Dot.node_style)list->?implicit_transitions:transitionlist->t->unitvaldot_output_oc:string->out_channel->?options:Dot.graph_stylelist->?marked_states:(state*Dot.node_style)list->?extra_nodes:(string*Dot.node_style)list->?implicit_transitions:transitionlist->t->unitvaldot_output_execs:string->?fname:string->?options:Dot.graph_stylelist->int->t->unitvaltex_output:string->?fname:string->?listed_transitions:labellistoption->t->unitendmoduleMake(S:Ltsa.STATE)(L:Ltsa.LABEL)=structmoduleAttr=structtypet=unitletcompare=compareletto_string_=""endmoduleRepr=Ltsa.Make(S)(L)(Attr)typestate=Repr.state(* = S.t *)typelabel=Repr.label(* = E.t *)typeattr=Attr.tmoduleState=Repr.StatemoduleLabel=Repr.LabelmoduleStates=Repr.StatesmoduleAttrs=Map.Make(structtypet=stateletcompare=compareend)(* Not used *)typetransition=Repr.transitiontypeitransition=Repr.itransitiontypet=Repr.t(* We keep the same internal repr. It's just that attr=unit here *)letrepr_ofs=sletof_reprs=sletempty=Repr.emptyletadd_stateqs=Repr.add_state(q,())sexceptionInvalid_stateofstateletremove_stateqs=tryRepr.remove_stateqswithRepr.Invalid_states->raise(Invalid_states)letadd_transition((q,l,q')ast)s=tryRepr.add_transitiontswithRepr.Invalid_states->raise(Invalid_states)letadd_itransitionts=tryRepr.add_itransitiontswithRepr.Invalid_states->raise(Invalid_states)letattr_ofsq=()letcreate~states:qs~itrans:ts0~trans:ts=empty|>(functions->List.fold_left(Fun.flipadd_state)sqs)|>(functions->List.fold_left(Fun.flipadd_transition)sts)|>(functions->List.fold_left(Fun.flipadd_itransition)sts0)letstatess=Repr.statessletistatess=Repr.istatessletstates's=List.mapfst(Repr.states's)(* let attrs s = Attrs.empty *)letistates's=Repr.istates'slettransitionss=Repr.transitionssletitransitionss=Repr.itransitionssletstring_of_state=Repr.string_of_stateletstring_of_label=Repr.string_of_labelletstring_of_attr_=""letstring_of_transition(q,l,q')="("^string_of_stateq^","^string_of_labell^","^string_of_stateq'^")"letis_state=Repr.is_stateletis_init_state=Repr.is_init_stateletis_transition=Repr.is_transitionletiter_statesfs=Repr.iter_states(funq_->fq)sletfold_statesfsz=Repr.fold_states(funq_acc->fqacc)szletiter_transitionsfs=Repr.iter_transitionsfsletfold_transitionsfsz=Repr.fold_transitionsfszletiter_itransitionsfs=Repr.iter_itransitionsfsletfold_itransitionsfsz=Repr.fold_itransitionsfszletfold_succssqfz=Repr.fold_succssqfzletfold_predssqfz=Repr.fold_predssqfzletiter_succssqf=Repr.iter_succssqfletiter_predssqf=Repr.iter_predssqfletsuccssq=Repr.succssqletpredssq=Repr.predssqletsuccs'sq=Repr.succs'sqletpreds'sq=Repr.preds'sqletsuccs_hatsq=Repr.succs_hatsqletpreds_hatsq=Repr.preds_hatsqletmap_label=Repr.map_labelletclean=Repr.cleanletis_reachable=Repr.is_reachableletdot_output=Repr.dot_outputletdot_output_oc=Repr.dot_output_ocletdot_output_execs=Repr.dot_output_execslettex_output=Repr.tex_outputendmoduleTrans(S1:T)(S2:T)=structmoduleF=Ltsa.Trans(S1.Repr)(S2.Repr)letmapfsfls1=S2.of_repr(F.mapfsfl(fun_->())(S1.repr_ofs1))endmoduleProduct(S1:T)(S2:T)=structmoduleS=OrderedTypeExt.Pair(S1.State)(S2.State)moduleL=OrderedTypeExt.Either(S1.Label)(S2.Label)moduleR=Make(S)(L)includeRmoduleP=Ltsa.Product(S1.Repr)(S2.Repr)letsynch_productsyncs1s2=letp=P.synch_productsync(S1.repr_ofs1)(S2.repr_ofs2)inletadd_statess=P.fold_states(funq_acc->R.add_stateqacc)psinletadd_transitionss=P.fold_transitions(funtacc->R.add_transitiontacc)psinletadd_itransitionss=P.fold_itransitions(funtacc->R.add_itransitiontacc)psinR.empty|>add_states|>add_transitions|>add_itransitionsletsynchronized_productsync_set=synch_product(functionl->List.memlsync_set)letfree_product=synch_product(function_->true)letasynchronous_product=synch_product(function(Some_,None)|(None,Some_)->true|_->false)letsynchronous_product=synch_product(function(Some_,Some_)->true|_->false)endmoduleProduct3(S1:T)(S2:T)(S3:T)=structmoduleS=OrderedTypeExt.Triplet(S1.State)(S2.State)(S3.State)moduleL=OrderedTypeExt.Either3(S1.Label)(S2.Label)(S3.Label)moduleR=Make(S)(L)includeRmoduleP=Ltsa.Product3(S1.Repr)(S2.Repr)(S3.Repr)letsynch_productsyncs1s2s3=letp=P.synch_productsync(S1.repr_ofs1)(S2.repr_ofs2)(S3.repr_ofs3)inletadd_statess=P.fold_states(funq_acc->R.add_stateqacc)psinletadd_transitionss=P.fold_transitions(funtacc->R.add_transitiontacc)psinletadd_itransitionss=P.fold_itransitions(funtacc->R.add_itransitiontacc)psinR.empty|>add_states|>add_transitions|>add_itransitionsletsynchronized_productsync_set=synch_product(functionl->List.memlsync_set)letfree_product=synch_product(function_->true)letasynchronous_product=synch_product(function(Some_,None,None)|(None,Some_,None)|(None,None,Some_)->true|_->false)letsynchronous_product=synch_product(function(Some_,Some_,Some_)->true|_->false)endmoduletypeMerge=sigtypestatetypelabelvalmerge_state:state*state->statevalmerge_label:labeloption*labeloption->labelendmoduleIProduct(S:T)(M:Mergewithtypestate=S.stateandtypelabel=S.label)=structincludeSmoduleP=Product(S)(S)moduleU=Trans(P)(S)lettr=U.mapM.merge_stateM.merge_labelletfree_products1s2=tr(P.free_products1s2)letsynch_productsyncs1s2=tr(P.synch_productsyncs1s2)letsynchronized_productsyncs1s2=tr(P.synchronized_productsyncs1s2)letasynchronous_products1s2=tr(P.asynchronous_products1s2)letsynchronous_products1s2=tr(P.synchronous_products1s2)endmoduletypeMerge3=sigtypestatetypelabelvalmerge_state:state*state*state->statevalmerge_label:labeloption*labeloption*labeloption->labelendmoduleIProduct3(S:T)(M:Merge3withtypestate=S.stateandtypelabel=S.label)=structincludeSmoduleP=Product3(S)(S)(S)moduleU=Trans(P)(S)lettr=U.mapM.merge_stateM.merge_labelletfree_products1s2s3=tr(P.free_products1s2s3)letsynch_productsyncs1s2s3=tr(P.synch_productsyncs1s2s3)letsynchronized_productsyncs1s2s3=tr(P.synchronized_productsyncs1s2s3)letasynchronous_products1s2s3=tr(P.asynchronous_products1s2s3)letsynchronous_products1s2s3=tr(P.synchronous_products1s2s3)end