Skip to content

Commit 79966f6

Browse files
committed
Select the rate rules to average based on the norm distance
Previously, we were using a distance algorithm that choose the manhattan distance. Now we move to use the Euclidian norm distance instead in hopes of decreasing the usage of very general nodes Speed up norm distance calculation by storing the node's level in the Entry() object when parsing group tree
1 parent 7c2e1b5 commit 79966f6

File tree

2 files changed

+31
-3
lines changed

2 files changed

+31
-3
lines changed

rmgpy/data/base.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ def loadOldDictionary(self, path, pattern):
451451

452452
def __loadTree(self, tree):
453453
"""
454-
Parse an old-style RMG tree located at `tree`. An RMG tree is an n-ary
454+
Parse an group tree located at `tree`. An RMG tree is an n-ary
455455
tree representing the hierarchy of items in the dictionary.
456456
"""
457457

@@ -498,7 +498,10 @@ def __loadTree(self, tree):
498498
else:
499499
entry.parent = None
500500
self.top.append(entry)
501-
501+
502+
# Save the level of the tree into the entry
503+
entry.level = level
504+
502505
# Add node to list of parents for subsequent iteration
503506
parents.append(label)
504507

rmgpy/data/kinetics/rules.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,25 @@ def __getAverageKinetics(self, kineticsList):
565565
E0 = (E0*0.001,"kJ/mol"),
566566
)
567567
return averagedKinetics
568+
569+
def calculateNormDistance(self, template, otherTemplate):
570+
"""
571+
Calculate the norm distance squared between two rate rules with
572+
`template` and `otherTemplate`. The norm distance is
573+
a^2 + b^2 + c^2 .... when a is the distance between the nodes in the
574+
first tree, b is the distance between the nodes in the second tree, etc.
575+
"""
576+
577+
# Do it the stupid way first and calculate distances from the top
578+
# rather than from each other for now... it's dumb but need to see results first
579+
import numpy
580+
depth = numpy.array([node.level for node in template])
581+
otherDepth = numpy.array([otherNode.level for otherNode in otherTemplate])
568582

583+
distance = numpy.array(depth-otherDepth)
584+
norm = numpy.dot(distance,distance)
585+
return norm
586+
569587
def estimateKinetics(self, template, degeneracy=1):
570588
"""
571589
Determine the appropriate kinetics for a reaction with the given
@@ -588,7 +606,14 @@ def getTemplateLabel(template):
588606
kineticsList.append([kinetics, t])
589607

590608
if len(kineticsList) > 0:
591-
609+
610+
if len(kineticsList) > 1:
611+
# Filter the kinetics to use templates with the lowest minimum euclidean distance
612+
# from the specified template
613+
norms = [self.calculateNormDistance(template, t) for kinetics,t in kineticsList]
614+
minNorm = min(norms)
615+
kineticsList = [pair for pair, norm in zip(kineticsList,norms) if norm == min(norms)]
616+
592617
if len(kineticsList) == 1:
593618
kinetics, t = kineticsList[0]
594619
# Check whether the exact rate rule for the original template (most specific

0 commit comments

Comments
 (0)