# HG changeset patch # User drewp@bigasterisk.com # Date 1630994674 25200 # Node ID 97b2c3cfdb83f0653137d68b01c8d2869fc6adf5 # Parent 03ed8c9abd5bbf5535615d8c25f9c3c75d800046 refactor: inline an odometer algorithm in place of itertools.product diff -r 03ed8c9abd5b -r 97b2c3cfdb83 service/mqtt_to_rdf/inference.py --- a/service/mqtt_to_rdf/inference.py Mon Sep 06 23:03:51 2021 -0700 +++ b/service/mqtt_to_rdf/inference.py Mon Sep 06 23:04:34 2021 -0700 @@ -87,16 +87,34 @@ def _possibleBindings(self, workingSet, stats) -> Iterator['BoundLhs']: """this yields at least the working bindings, and possibly others""" candidateTermMatches: Dict[BindableTerm, Set[Node]] = self._allCandidateTermMatches(workingSet) + for bindRow in self._product(candidateTermMatches): + try: + yield BoundLhs(self, bindRow) + except EvaluationFailed: + stats['permCountFailingEval'] += 1 + def _product(self, candidateTermMatches: Dict[BindableTerm, Set[Node]]) -> Iterator[CandidateBinding]: orderedVars, orderedValueSets = _organize(candidateTermMatches) self._logCandidates(orderedVars, orderedValueSets) - log.debug(f'{INDENT*3} trying all permutations:') - for valueSet in itertools.product(*orderedValueSets): - try: - yield BoundLhs(self, CandidateBinding(dict(zip(orderedVars, valueSet)))) - except EvaluationFailed: - stats['permCountFailingEval'] += 1 + if not orderedValueSets: + yield CandidateBinding({}) + return + if not orderedValueSets or not all(orderedValueSets): + # some var or bnode has no options at all + return + rings: List[Iterator[Node]] = [itertools.cycle(valSet) for valSet in orderedValueSets] + currentSet: List[Node] = [next(ring) for ring in rings] + starts = [valSet[-1] for valSet in orderedValueSets] + while True: + for col, curr in enumerate(currentSet): + currentSet[col] = next(rings[col]) + log.debug(repr(currentSet)) + yield CandidateBinding(dict(zip(orderedVars, currentSet))) + if curr is not starts[col]: + break + if col == len(orderedValueSets) - 1: + return def _allCandidateTermMatches(self, workingSet: ReadOnlyWorkingSet) -> Dict[BindableTerm, Set[Node]]: """the total set of terms each variable could possibly match"""