comparison service/mqtt_to_rdf/inference.py @ 1614:97b2c3cfdb83

refactor: inline an odometer algorithm in place of itertools.product
author drewp@bigasterisk.com
date Mon, 06 Sep 2021 23:04:34 -0700
parents 03ed8c9abd5b
children bcfa368e5498
comparison
equal deleted inserted replaced
1613:03ed8c9abd5b 1614:97b2c3cfdb83
85 return True 85 return True
86 86
87 def _possibleBindings(self, workingSet, stats) -> Iterator['BoundLhs']: 87 def _possibleBindings(self, workingSet, stats) -> Iterator['BoundLhs']:
88 """this yields at least the working bindings, and possibly others""" 88 """this yields at least the working bindings, and possibly others"""
89 candidateTermMatches: Dict[BindableTerm, Set[Node]] = self._allCandidateTermMatches(workingSet) 89 candidateTermMatches: Dict[BindableTerm, Set[Node]] = self._allCandidateTermMatches(workingSet)
90 90 for bindRow in self._product(candidateTermMatches):
91 try:
92 yield BoundLhs(self, bindRow)
93 except EvaluationFailed:
94 stats['permCountFailingEval'] += 1
95
96 def _product(self, candidateTermMatches: Dict[BindableTerm, Set[Node]]) -> Iterator[CandidateBinding]:
91 orderedVars, orderedValueSets = _organize(candidateTermMatches) 97 orderedVars, orderedValueSets = _organize(candidateTermMatches)
92 self._logCandidates(orderedVars, orderedValueSets) 98 self._logCandidates(orderedVars, orderedValueSets)
93
94 log.debug(f'{INDENT*3} trying all permutations:') 99 log.debug(f'{INDENT*3} trying all permutations:')
95 for valueSet in itertools.product(*orderedValueSets): 100 if not orderedValueSets:
96 try: 101 yield CandidateBinding({})
97 yield BoundLhs(self, CandidateBinding(dict(zip(orderedVars, valueSet)))) 102 return
98 except EvaluationFailed: 103 if not orderedValueSets or not all(orderedValueSets):
99 stats['permCountFailingEval'] += 1 104 # some var or bnode has no options at all
105 return
106 rings: List[Iterator[Node]] = [itertools.cycle(valSet) for valSet in orderedValueSets]
107 currentSet: List[Node] = [next(ring) for ring in rings]
108 starts = [valSet[-1] for valSet in orderedValueSets]
109 while True:
110 for col, curr in enumerate(currentSet):
111 currentSet[col] = next(rings[col])
112 log.debug(repr(currentSet))
113 yield CandidateBinding(dict(zip(orderedVars, currentSet)))
114 if curr is not starts[col]:
115 break
116 if col == len(orderedValueSets) - 1:
117 return
100 118
101 def _allCandidateTermMatches(self, workingSet: ReadOnlyWorkingSet) -> Dict[BindableTerm, Set[Node]]: 119 def _allCandidateTermMatches(self, workingSet: ReadOnlyWorkingSet) -> Dict[BindableTerm, Set[Node]]:
102 """the total set of terms each variable could possibly match""" 120 """the total set of terms each variable could possibly match"""
103 121
104 candidateTermMatches: Dict[BindableTerm, Set[Node]] = defaultdict(set) 122 candidateTermMatches: Dict[BindableTerm, Set[Node]] = defaultdict(set)