Mercurial > code > home > repos > homeauto
diff service/mqtt_to_rdf/inference.py @ 1668:89e53cb8a01c
fix some harder tests. Mostly, _advanceTheStack needed to spin the odometer rings starting from the other side, to get all the right combos
author | drewp@bigasterisk.com |
---|---|
date | Tue, 21 Sep 2021 22:29:19 -0700 |
parents | a2347393b43e |
children | 9d00adef0b22 |
line wrap: on
line diff
--- a/service/mqtt_to_rdf/inference.py Tue Sep 21 22:19:11 2021 -0700 +++ b/service/mqtt_to_rdf/inference.py Tue Sep 21 22:29:19 2021 -0700 @@ -61,7 +61,8 @@ self._shortId = next(_chunkLooperShortId) self._alignedMatches = list(self.lhsChunk.ruleMatchesFrom(self.workingSet)) - self._current = CandidateBinding({}) # only ours- do not store prev, since it could change without us + # only ours- do not store prev, since it could change without us + self._current = CandidateBinding({}) self._pastEnd = False self._seenBindings: List[CandidateBinding] = [] # combined bindings (up to our ring) that we've returned @@ -78,7 +79,9 @@ return self.prev.currentBinding() def advance(self): - """update to a new set of bindings we haven't seen (since last restart), or go into pastEnd mode""" + """update _current to a new set of valid bindings we haven't seen (since + last restart), or go into pastEnd mode. Note that _current is just our + contribution, but returned valid bindings include all prev rings.""" if self._pastEnd: raise NotImplementedError('need restart') ringlog.debug('') @@ -89,7 +92,6 @@ augmentedWorkingSet = list( applyChunky(self.prev.currentBinding(), self._alignedMatches, returnBoundStatementsOnly=False)) - if self._advanceWithPlainMatches(augmentedWorkingSet): ringlog.debug(f'{INDENT*6} <-- {self}.advance finished with plain matches') return @@ -108,19 +110,13 @@ for aligned in augmentedWorkingSet: try: - fullBinding = aligned.totalBindingIfThisStmtWereTrue(self._prevBindings()) - except Inconsistent: - ringlog.debug(f'{INDENT*7} ChunkLooper{self._shortId} - {aligned} would be inconsistent with prev bindings') + newBinding = aligned.newBindingIfMatched(self._prevBindings()) + except Inconsistent as exc: + ringlog.debug( + f'{INDENT*7} ChunkLooper{self._shortId} - {aligned} would be inconsistent with prev bindings ({exc})') continue - newBinding = fullBinding.copy() - newBinding.subtract(self._prevBindings()) - - ringlog.debug(f'{INDENT*7} {newBinding=} {self._seenBindings=}') - if fullBinding not in self._seenBindings: - self._seenBindings.append(fullBinding.copy()) - self._current = newBinding - ringlog.debug(f'{INDENT*7} new binding from {self} -> {fullBinding}') + if self._testAndKeepNewBinding(newBinding): return True return False @@ -142,16 +138,22 @@ pass else: if newBinding is not None: - fullBinding: CandidateBinding = self._prevBindings().copy() - fullBinding.addNewBindings(newBinding) - if fullBinding not in self._seenBindings: - self._seenBindings.append(fullBinding) - self._current = newBinding - ringlog.debug(f'{INDENT*7} new binding from {self} -> {fullBinding}') + if self._testAndKeepNewBinding(newBinding): return True return False + def _testAndKeepNewBinding(self, newBinding): + fullBinding: CandidateBinding = self._prevBindings().copy() + fullBinding.addNewBindings(newBinding) + isNew = fullBinding not in self._seenBindings + ringlog.debug(f'{INDENT*7} {self} considering {newBinding=} to make {fullBinding}. {isNew=}') + if isNew: + self._seenBindings.append(fullBinding.copy()) + self._current = newBinding + return True + return False + def _boundOperands(self, operands) -> List[Node]: pb: CandidateBinding = self._prevBindings() @@ -296,15 +298,15 @@ raise NoOptions() def _advanceTheStack(self, looperRings: List[ChunkLooper]) -> bool: - carry = True # 1st elem always must advance - for i, ring in enumerate(looperRings): + carry = True # last elem always must advance + for i, ring in reversed(list(enumerate(looperRings))): # unlike normal odometer, advancing any earlier ring could invalidate later ones if carry: odolog.debug(f'{INDENT*4} advanceAll [{i}] {ring} carry/advance') ring.advance() carry = False if ring.pastEnd(): - if ring is looperRings[-1]: + if ring is looperRings[0]: allRingsDone = [r.pastEnd() for r in looperRings] odolog.debug(f'{INDENT*4} advanceAll [{i}] {ring} says we done {allRingsDone=}') return True