10.3. Derivations and Reaction Networks

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

10.3.2. Repetition

A sub-strategy can be repeated.

Explore in the playground.

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

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

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

10.3.5. Double Pushout Printing

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

Explore in the playground.

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