Source code for acsets.petris

"""
In this model, we define a schema for petri nets, and then a subclass of acset
with some convenience methods.
"""
from pathlib import Path

from acsets import (
    CATLAB_SCHEMAS_DIRECTORY,
    HERE,
    JSON_SCHEMAS_DIRECTORY,
    ACSet,
    Attr,
    AttrType,
    Hom,
    Ob,
    Schema,
)

Species = Ob(name="S", title="Species")
Transition = Ob(name="T", title="Transition")
Input = Ob(name="I", title="Input")
Output = Ob(name="O", title="Output")

hom_it = Hom(name="it", dom=Input, codom=Transition, title="Input transition morphism")
hom_is = Hom(name="is", dom=Input, codom=Species, title="Input species morphism")
hom_ot = Hom(name="ot", dom=Output, codom=Transition, title="Output transition morphism")
hom_os = Hom(name="os", dom=Output, codom=Species, title="Output species morphism")

petri_obs = [Species, Transition, Input, Output]
petri_homs = [hom_it, hom_is, hom_ot, hom_os]

Name = AttrType(name="Name", ty=str, title="Name")
Concentration = AttrType(name="Concentration", ty=float, title="Concentration")
Rate = AttrType(name="Rate", ty=float, title="Rate")
Prop = AttrType(name="Prop", ty=dict, title="Property")

attr_sname = Attr(
    name="sname",
    dom=Species,
    codom=Name,
    title="Species name",
    description="An attribute representing the name of a species.",
)
attr_concentration = Attr(
    name="concentration",
    dom=Species,
    codom=Concentration,
    title="Species concentration",
    description="An attribute representing the concentration of a species.",
)
attr_sprop = Attr(
    name="sprop",
    dom=Species,
    codom=Prop,
    title="Species properties",
    description="An attribute representing the properties of a species.",
)
attr_tname = Attr(
    name="tname",
    dom=Transition,
    codom=Name,
    title="Transition name",
    description="An attribute representing the name of a transition.",
)
attr_rate = Attr(
    name="rate",
    dom=Transition,
    codom=Rate,
    title="Transition rate",
    description="An attribute representing the rate of a transition.",
)
attr_tprop = Attr(
    name="tprop",
    dom=Transition,
    codom=Prop,
    title="Transition properties",
    description="An attribute representing the properties of a transition.",
)

labelled_ats = [Name]
labelled_attrs = [attr_sname, attr_tname]

rxn_ats = [Concentration, Rate]
rxn_attrs = [attr_concentration, attr_rate]

prop_ats = [Prop]
prop_attrs = [attr_sprop, attr_tprop]

SchPetriNet = Schema(
    "PetriNet",
    petri_obs,
    petri_homs,
    [],
    [],
)
SchLabelledPetriNet = Schema(
    "LabelledPetriNet", petri_obs, petri_homs, labelled_ats, labelled_attrs
)
SchReactionNet = Schema("ReactionNet", petri_obs, petri_homs, rxn_ats, rxn_attrs)
SchLabelledReactionNet = Schema(
    "LabelledReactionNet", petri_obs, petri_homs, labelled_ats + rxn_ats, labelled_attrs + rxn_attrs
)
SchPropertyPetriNet = Schema("PropertyPetriNet", petri_obs, petri_homs, prop_ats, prop_attrs)
SchPropertyLabelledPetriNet = Schema(
    "PropertyLabelledPetriNet",
    petri_obs,
    petri_homs,
    labelled_ats + prop_ats,
    labelled_attrs + prop_attrs,
)
SchPropertyReactionNet = Schema(
    "PropertyReactionNet", petri_obs, petri_homs, rxn_ats + prop_ats, rxn_attrs + prop_attrs
)
SchPropertyLabelledReactionNet = Schema(
    "PropertyLabelledReactionNet",
    petri_obs,
    petri_homs,
    labelled_ats + rxn_ats + prop_ats,
    labelled_attrs + rxn_attrs + prop_attrs,
)


[docs] class Petri(ACSet): """ A subclass of ACSet customized for petri nets. .. code-block:: sir = Petri() s,i,r = sir.add_species(3) sir.set_subpart(s,attr_sname,"susceptible") sir.set_subpart(s,attr_sprop, { "uuid": "dae22e85-d941-4156-b559-d153a44356f3" }) inf = sir.add_transitions([([s,i],[i,i])]) sir.set_subpart(inf,attr_tname,"infection") sir.set_subpart(inf,attr_tprop, { "uuid": "bba26d0e-3ce5-41e5-ac0e-6be35535d534" }) """ def __init__(self, name="Petri", schema=SchPropertyLabelledReactionNet): """Initialize a new petri net.""" super(Petri, self).__init__(schema.name, schema)
[docs] def add_species(self, n: int) -> range: """Add `n` number of species to the petri net Args: n: The number of species to add to the petri net. Returns: A range of the indexes of the species that were inserted into the petri net. """ return self.add_parts(Species, n)
[docs] def add_transitions(self, transitions: list[tuple[list[int], list[int]]]) -> range: """Add transitions to the petri net Args: transitions: A list of tuples where each tuple has two items: the first is a list of the input species and the second is a list of the output species. Returns: A range of the of the indexes of the transitions that were inserted into the petri net. """ ts = self.add_parts(Transition, len(transitions)) for t, (ins, outs) in zip(ts, transitions): for s in ins: arc = self.add_part(Input) self.set_subpart(arc, hom_it, t) self.set_subpart(arc, hom_is, s) for s in outs: arc = self.add_part(Output) self.set_subpart(arc, hom_ot, t) self.set_subpart(arc, hom_os, s) return ts
if __name__ == "__main__": for schema in [ SchPetriNet, SchLabelledPetriNet, SchReactionNet, SchLabelledReactionNet, SchPropertyPetriNet, SchPropertyLabelledPetriNet, SchPropertyReactionNet, SchPropertyLabelledReactionNet, ]: schema_filename = "{}.json".format(schema.name) CATLAB_SCHEMAS_DIRECTORY.joinpath(schema_filename).write_text( schema.schema.json(indent=2, ensure_ascii=False, sort_keys=True) ) jsonschema_path = JSON_SCHEMAS_DIRECTORY.joinpath(schema_filename) schema.write_schema( JSON_SCHEMAS_DIRECTORY.joinpath(jsonschema_path), uri="https://raw.githubusercontent.com/AlgebraicJulia/py-acsets/main/src/acsets/{}".format( Path(jsonschema_path).relative_to(HERE) ), )