Commit 75003b7b authored by Nicolas Dumazet's avatar Nicolas Dumazet

Use a so-called closure of the simulation tree to reduce the search space:

instead of walking all descendants of root applied rules, we now only
walk the ancestors of related movements and their descendants.

This means that a few branches get pruned, namely the branches stemming
from ancestors of related movements that dont include such related
movements as descendants.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@36584 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 99b1483a
...@@ -377,26 +377,67 @@ class BusinessPath(Path, Predicate): ...@@ -377,26 +377,67 @@ class BusinessPath(Path, Predicate):
full simulation trees per applied rule full simulation trees per applied rule
""" """
portal_catalog = self.getPortalObject().portal_catalog portal_catalog = self.getPortalObject().portal_catalog
root_applied_rule_set = set()
delivery_simulation_movement_list = portal_catalog( delivery_simulation_movement_list = portal_catalog(
delivery_uid=[x.getUid() for x in explanation.getMovementList()]) delivery_uid=[x.getUid() for x in explanation.getMovementList()])
for simulation_movement in delivery_simulation_movement_list: related_list = self.getBusinessPathClosure(delivery_simulation_movement_list)
applied_rule = simulation_movement.getRootAppliedRule()
root_applied_rule_set.add(applied_rule)
simulation_movement_list = []
for applied_rule in root_applied_rule_set:
simulation_movement_list.extend(self._recurseGetValueList(
applied_rule, 'Simulation Movement'))
self_url = self.getRelativeUrl() self_url = self.getRelativeUrl()
return [simulation_movement for simulation_movement return [m for m in related_list if m.getCausality() == self_url]
in simulation_movement_list
# related with explanation def getBusinessPathClosure(self, movement_list):
if simulation_movement.getCausality() == self_url and \ # We color/remember all paths to all items in movement_list
self._isDeliverySimulationMovementRelated( # Also, if A and B are in movement_list with
simulation_movement, delivery_simulation_movement_list)] # A an ancestor of B, the path to B is not colored
colored_tree_dict = dict()
leaf_marker = object()
for simulation_movement in movement_list:
# remove portal_simulation
path_list = simulation_movement.getRelativeUrl().split("/")[1:]
cur = colored_tree_dict
for path in path_list[:-1]:
cur = cur.setdefault(path, {})
if cur == leaf_marker:
# an ancestor of simulation_movement was colored before
break
else:
# note that we remove possibly-colored-before descendants
cur[path_list[-1]] = leaf_marker
# We note closure(ns)=descendants(ns) U ancestors(ns) with ns a nodeset
#
# At this point, L = leafs(colored_tree) is the smallest nodeset ns satisfying
# descendants(ns) == descendants(movement_list)
# Because L < movement_list, we have closure(L) < closure(movement_list)
# Note that
# ancestors(movement_list) < closure(L)
# hence
# closure(L) == closure(movement_list)
related_list = []
def closure(root, tree):
"""
recursive helper filling related_list with closure(leafs(tree))
tree represents a coloration of the complete simulation tree.
tree is rooted at root
- we include all colored non-leaf movements
- we include all movement descendants of a colored leaf
"""
for k, v in tree.iteritems():
cur = root[k]
# XXX maybe using parity Applied Rule / Simulation Movement is enough?
if cur.getPortalType() == 'Simulation Movement':
related_list.append(cur)
if v == leaf_marker:
related_list.extend(self._recurseGetValueList(cur, 'Simulation Movement'))
else:
closure(cur, v)
closure(self.getPortalObject().portal_simulation, colored_tree_dict)
return related_list
def getExpectedQuantity(self, explanation, *args, **kwargs): def getExpectedQuantity(self, explanation, *args, **kwargs):
""" """
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment