12.3. Derivations and Reaction Networks

12.3.1. Rule Application

Transformation rules (reaction patterns) can be applied to graphs (molecules) to create new graphs (molecules). The transformations (reactions) implicitly form a directed (multi-)hypergraph (chemical reaction network).

Explore in the playground.

 1 include("0050_formoseGrammar.py")
 2 # Reaction networks are expaned using a strategy:
 3 strat = (
 4    # A molecule can be active or passive during evaluation.
 5    addUniverse(formaldehyde) # passive
 6    >> addSubset(glycolaldehyde) # active
 7    # Aach reaction must have a least 1 active educt.
 8    >> inputRules
 9 )
10 # We call a reaction network a 'derivation graph'.
11 dg = DG(graphDatabase=inputGraphs)
12 dg.build().execute(strat)
13 # They can also be visualised.
14 dg.print()

12.3.2. Repetition

A sub-strategy can be repeated.

Explore in the playground.

 1 include("0050_formoseGrammar.py")
 2 strat = (
 3    addUniverse(formaldehyde)
 4    >> addSubset(glycolaldehyde)
 5    # Iterate the rule application 4 times.
 6    >> repeat[4](
 7       inputRules
 8    )
 9 )
10 dg = DG(graphDatabase=inputGraphs)
11 dg.build().execute(strat)
12 dg.print()

12.3.3. Application Constraints

We may want to impose constraints on which reactions are accepted. E.g., in formose the molecules should not have too many carbon atoms.

Explore in the playground.

 1 include("0050_formoseGrammar.py")
 2 strat = (
 3    addUniverse(formaldehyde)
 4    >> addSubset(glycolaldehyde)
 5    # Constrain the reactions:
 6    # No molecules with more than 20 atom can be created.
 7    >> rightPredicate[
 8       lambda derivation: all(g.numVertices <= 20 for g in derivation.right)
 9    ](
10       # Iterate until nothing new is found.
11       repeat(
12          inputRules
13       )
14    )
15 )
16 dg = DG(graphDatabase=inputGraphs)
17 dg.build().execute(strat)
18 dg.print()

12.3.4. Advanced Printing

Reaction networks can become large, and often it is necessary to hide parts of the network, or in general change the appearance.

Explore in the playground.

 1 include("0212_dgPredicate.py")
 2 # Create a printer with default options:
 3 p = DGPrinter()
 4 # Hide "large" molecules: those with > 4 Cs:
 5 p.pushVertexVisible(lambda v: v.graph.vLabelCount("C") <= 4)
 6 # Hide the reactions with the large molceules as well:
 7 def edgePred(e):
 8    if any(v.graph.vLabelCount("C") > 4 for v in e.sources): return False
 9    if any(v.graph.vLabelCount("C") > 4 for v in e.targets): return False
10    return True
11 p.pushEdgeVisible(edgePred)
12 # Add the number of Cs to the molecule labels:
13 p.pushVertexLabel(lambda v: "\\#C=" + str(v.graph.vLabelCount("C")))
14 # Highlight the molecules with 4 Cs:
15 p.pushVertexColour(lambda v: "blue" if v.graph.vLabelCount("C") == 4 else "")
16 # Print the network with the customised printer.
17 dg.print(p)

12.3.5. Double Pushout Printing

Each reaction/derivation can be visualised as a DPO diagram.

Explore in the playground.

1 include("0212_dgPredicate.py")
2 for e in dg.edges:
3    e.print()