From: timv Date: Sun, 9 Jun 2013 16:40:00 +0000 (-0400) Subject: Improvements to chart X-Git-Url: https://hydra-www.ietfng.org/gitweb/?a=commitdiff_plain;h=c27cdccfb18ddffdba042a43f1eecf4756fb3bdb;p=dyna2 Improvements to chart * queries (= Chart.__getitem__) perform fewer set intersections (removed a very slow call to set.copy -- it's faster to intersect two sets and get a copy because the intersection is guaranteed to be smaller!) I'm also using a most constrained variable first heuristic for picking the first index to intersect. * fewer hash look ups with we call ``insert``. --- diff --git a/src/Dyna/Backend/Python/chart.py b/src/Dyna/Backend/Python/chart.py index 632a9bb..a5cb9d4 100644 --- a/src/Dyna/Backend/Python/chart.py +++ b/src/Dyna/Backend/Python/chart.py @@ -75,22 +75,21 @@ class Chart(object): assert val is not None # filter set of candidates by each bound argument - candidates = None - for (ix, x) in zip(self.ix, args): - if isinstance(x, slice): - continue - if candidates is None: - # initial candidates determined by first non-bound column - candidates = ix[x].copy() - else: - candidates &= ix[x] - if not len(candidates): - # no candidates left - break - - if candidates is None: - # This happens when all arguments are free. - candidates = self.intern.values() + b = [(ix[x]) for (ix, x) in zip(self.ix, args) if not isinstance(x, slice)] + + if len(b) == 0: + # all arguments are free. + candidates = self.intern.itervalues() + + elif len(b) == 1: + candidates = iter(b[0]) + + else: + b.sort(key=len) # start with smaller ones + candidates = b[0] & b[1] + for ix in b[2:]: + candidates &= ix + candidates = iter(candidates) # handle the value column separately because we don't index it yet. if isinstance(val, slice): @@ -102,27 +101,13 @@ class Chart(object): if term.value == val: yield term, term.args + (term.value,) # TODO: change codegen to avoid addition.. - def lookup(self, args): - "find index for these args" - assert len(args) == self.arity - + def insert(self, args): # TODO: rename try: return self.intern[args] except KeyError: - return None - - def insert(self, args, val): - - # debugging check: row is not already in chart. - assert self.lookup(args) is None, \ - '%r already in chart with value %r' % (args, val) - - self.intern[args] = term = Term(self.name, args) - term.value = val - term.aggregator = self.new_aggregator() - - # index new term - for i, x in enumerate(args): - self.ix[i][x].add(term) - - return term + self.intern[args] = term = Term(self.name, args) + term.aggregator = self.new_aggregator() + # index new term + for i, x in enumerate(args): + self.ix[i][x].add(term) + return term