molfoundry.Rule#
- class molfoundry.Rule#
- static fromGMLString(gml, name=None, invert=False, add=True)#
- static fromDFS(dfs, name=None, labelType=LabelType.String, invert=False, add=True)#
Build a
Rulefrom a RuleDFS line-notation string (L >> R).Vertices are related across
>>by their ids: a shared id whose label is unchanged is a context vertex, otherwise a relabeling. PasslabelType=LabelType.Termwhen the_-prefixed /*labels are term variables. Implicit hydrogens are not added on rule sides.
- static fromGMLFile(f, name=None, invert=False, add=True)#
- static identity(graph, name=None, *, constraints=(), condition=None, labelType=LabelType.String, add=True)#
The identity rule
G <- G -> Gongraph.Everything is context, so the rule rewrites nothing. As an observable it counts the matches of
graphin a state that satisfyconstraintsandcondition(the pattern observables of Behr, Krivine, Andersen and Merkle, arXiv:2106.02573). It is thesqpoJumpClosure()of every rule whose input isgraphunder these conditions.Rule vertices take the graph’s external ids – the ids of the GML it was read from (
vertex.externalId) – when every vertex has a distinct one, and the vertex ids otherwise.constraints(any ofAdjacencyConstraint,LabelAnyConstraint,ShortestPathConstraintandNoEdgeConstraint) and the nestedconditionname vertices by these ids, as the rule’s GML would; they are whatmatchConstraintsAdjacencyand friends andmatchConditionread back. ANoEdgeConstraint’simpliedflag is ignored, since the rule creates no edge.namedefaults to the graph’s name with a suffix. Like the other constructors, the rule is added to the global rule list unlessadd=False.path = Graph.fromGMLString( 'graph [ node [ id 0 label "C" ] node [ id 1 label "O" ] node [ id 2 label "C" ] ' 'edge [ source 0 target 1 label "-" ] edge [ source 1 target 2 label "-" ] ]', add=False) # C-O-C whose carbons are not bonded to each other. ether = Rule.identity(path, "ether", constraints=[NoEdgeConstraint(0, 2)], add=False) ether.numMatches([state], ApplyMode.UseAny)
Raises
LogicErrorwhen a constraint or the condition names a vertex the graph does not have.- Parameters:
graph (Graph)
name (str | None)
constraints (Iterable[AdjacencyConstraint | LabelAnyConstraint | ShortestPathConstraint | NoEdgeConstraint])
condition (ConditionTrue | ConditionExists | ConditionNot | ConditionAnd | ConditionOr | AdjacencyConstraint | LabelAnyConstraint | ShortestPathConstraint | NoEdgeConstraint | None)
labelType (LabelType)
- Return type:
- static fromMolFoundry(id, name=None, invert=False, add=True)#
- optimize()#
Return a folded copy of this rule.
Every node and edge that is present and unchanged on both sides (same label, and same stereo for nodes) is moved into the context (K) instead of appearing separately in the left (L) and right (R) sides. This rule itself is left unchanged and the returned rule carries the folded form; both have the same
canonKey, which is computed on the folded form.- Return type:
- compileConditions()#
Return a copy of this rule with its match constraints moved into its condition tree as expanded patterns.
Each
matchConstraints*entry that has an exact pattern form becomes that pattern inmatchCondition(a no-edge constraint becomesnot existsthe edge; an adjacency constraint becomesexists/not existsthe required neighbors; a bounded shortest path becomes path patterns), never an opaque leaf. Opaque leaves the condition tree already carries are expanded the same way, in place. The converted constraints are conjoined with the condition the rule already has: appended to its children when its root is already anand, otherwise placed beside it under a newandroot.Each expansion is simplified: parts the rule’s own pattern already guarantees drop out (an “at least one O neighbor” the left side’s own bond provides, a path the left side already contains), and a constraint the pattern guarantees outright is removed without adding anything. Each remaining constraint stays one operand of the root
and.Kept as constraints, unchanged: those with no finite pattern form (label-any constraints, shortest-path lower bounds, adjacency constraints under term labels), and the no-edge constraints a loaded rule implies for each edge it creates (marked
implied), which loading re-derives anyway. A tree leaf with no pattern form stays where it is in the tree. The result can still be inverted withmakeInverse()whenever this rule can.The returned rule admits exactly the same matches; it is decided by the generic pattern evaluator rather than the constraints’ tuned evaluators, which is slower on large graphs. This rule itself is left unchanged.
- Return type:
- dpoJumpClosure(name=None)#
The DPO jump closure
I <- K -> Iof this ruleL <- K -> R.As an observable it counts this rule’s DPO applications to a state: the matches of its input
I = Lthat satisfy the rule’s application conditions and the dangling condition (Behr, Krivine, Andersen and Merkle, arXiv:2106.02573, Thm. 6(2) and Remark 3). What the rule deletes or relabels is deleted and recreated with its left label. Each deleted vertex is recreated under a fresh id, since one id on both sides is one kept vertex.namedefaults to this rule’s name with a suffix.
- sqpoJumpClosure(name=None)#
The SqPO jump closure
I <- I -> Iof this ruleL <- K -> R.As an observable it counts the matches of the input
I = Lthat satisfy the rule’s application conditions; SqPO has no dangling condition.namedefaults to this rule’s name with a suffix.
- property vertices: List[RuleVertex]#
The vertices of the rule’s span, each a
RuleVertex.Every vertex carries its left/right images and a
Membershipsaying whether the rule keeps, changes, creates, or deletes it.
- property edges: List[RuleEdge]#
The edges of the rule’s span, each a
RuleEdge.Each edge’s endpoints are
RuleVertexobjects, so an edge’s span information reaches its endpoints’ viaedge.source/edge.target.
- getVertex(id)#
The span vertex with the given rule node
id, orNoneif absent.- Parameters:
id (int)
- Return type:
RuleVertex | None
- getEdge(source, target)#
The span edge between
sourceandtarget(either order), orNone.
- property matchConstraintsAdjacency: Tuple[AdjacencyConstraint, ...]#
The rule’s adjacency constraints (GML
constrainAdj), read-only.
- property matchConstraintsLabelAny: Tuple[LabelAnyConstraint, ...]#
The rule’s label constraints (GML
constrainLabelAny), read-only.
- property matchConstraintsShortestPath: Tuple[ShortestPathConstraint, ...]#
The rule’s shortest-path constraints (GML
constrainShortestPath), read-only.
- property matchConstraintsNoEdge: Tuple[NoEdgeConstraint, ...]#
The rule’s no-edge constraints (GML
constrainNoEdge), read-only.Includes the ones loading a rule adds for every edge it creates, marked
implied.
- property matchCondition: ConditionTrue | ConditionExists | ConditionNot | ConditionAnd | ConditionOr | AdjacencyConstraint | LabelAnyConstraint | ShortestPathConstraint | NoEdgeConstraint | None#
The rule’s nested application condition (GML
condition), read-only, orNonewhen it has none. Vertices are named by id, as in GML; seemolfoundry.constraints. A match must satisfy it in addition to thematchConstraints*.
- numMatches(graphs, mode=ApplyMode.UseAll, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism), *, onlyProper=None)#
The number of matches
DG.build().apply(graphs, rule, mode)admits.modeselects which graphs a match may use, as inDG.Builder.apply()(seeApplyMode). For a rule with two isolatedAvertices and chainsA-A-A-A:ApplyMode.UseAll(default) counts the matches that use every listed graph exactly once:numMatches([chain])is 12, the ordered pairs inside the chain, andnumMatches([chain, chain])is 32, only the 2 * 16 pairs between the chains use both;ApplyMode.UseAnycounts every match in exactly the listed graphs:numMatches([chain, chain], ApplyMode.UseAny)is 56, 2 * 12 inside the chains and 2 * 16 between them;ApplyMode.UseAnyMultiplicitylets a match span further copies:numMatches([chain], ApplyMode.UseAnyMultiplicity)is 44, 12 inside one copy and 2 * 16 across two.
Matching, the dangling condition, the rule’s application conditions, and the checks of the rewrite itself (an edge the rule creates must not exist yet) run as in a derivation, but no products are built, canonicalized, or added to a derivation graph. Every match counts: matches related by a symmetry of the graphs and both orientations of a symmetric rule are counted separately, and so are matches that differ only in which copy of a graph plays which role. That makes this the sum of
DG.HyperEdge.numMatches()over the hyperedgesapplyderives, except that underUseAnya match using one of several identical listed graphs counts once per graph it could use, which a hyperedge (one per reaction) does not tell apart.labelSettingsdefaults to that of aDG. MØD’sonlyProperflag is still accepted: true isUseAll, falseUseAny.A rule with an empty left side has one match, the empty one, the only map of the empty graph into a state. It uses no graph, so
UseAnyandUseAnyMultiplicityadmit it in every state andUseAllonly whengraphsis empty; the rule’s conditions are read on the empty host it uses. The identity rule of the empty graph thus counts the constant 1, and a rule creating something from nothing one application per state, asapplyderives it: a hyperedge without sources.
- matches(graphs, mode=ApplyMode.UseAll, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism))#
The matches
numMatches()counts, each as thematchDG.Builder.applyMatch()takes to apply the rule there.A match maps every vertex of the left side, by rule vertex id, to
(graph index, vertex id): the position of its graph ingraphsand the vertex’s id in that graph.modeisApplyMode.UseAll(default) orApplyMode.UseAny, both readinggraphsas the concrete state, each listed graph one copy; identical graphs listed twice are two copies, told apart by their positions.ApplyMode.UseAnyMultiplicityraises aLogicError, as its matches may use copiesgraphsdoes not list. For a rule with two isolatedAvertices and a chainA-A-A-A,matches([chain, chain], ApplyMode.UseAny)lists 56 matches: 12 inside each chain and 32 between them, the latter being allmatches([chain, chain])lists.for match in rule.matches([ethanol], ApplyMode.UseAny): edge, vertexMap = builder.applyMatch([ethanol], rule, match)
The matches pass every check
numMatches()makes, in a fixed order. A rule with an empty left side lists the empty match,{}, wherenumMatches()counts it.labelSettingsdefaults to that of aDG.
- print() None#
- print(printer: GraphPrinter | None = None) None
- Parameters:
printer (GraphPrinter | None)
- Return type:
None
- svg() str#
- svg(printer: GraphPrinter | None = None) str
Render the rule to an SVG string and return it — the same depiction
printshows, without the summary card wrapper.- Parameters:
printer (GraphPrinter | None)
- Return type: