]> hydra-www.ietfng.org Git - dyna2/commitdiff
Improvements to chart
authortimv <tim.f.vieira@gmail.com>
Sun, 9 Jun 2013 16:40:00 +0000 (12:40 -0400)
committertimv <tim.f.vieira@gmail.com>
Sun, 9 Jun 2013 16:40:00 +0000 (12:40 -0400)
  * 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``.

src/Dyna/Backend/Python/chart.py

index 632a9bb9ec8299aa4184d8a8542dc798b7ea2337..a5cb9d44dcb7ec3f8792e110ffc56c0d90350d15 100644 (file)
@@ -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