comparison service/mqtt_to_rdf/inference.py @ 1600:89a50242cb5e

cleanup internal names, imports
author drewp@bigasterisk.com
date Sun, 05 Sep 2021 22:50:15 -0700
parents abbf0eb0e640
children 30463df12d89
comparison
equal deleted inserted replaced
1599:abbf0eb0e640 1600:89a50242cb5e
97 def verify(self, lhs: 'Lhs', workingSet: ReadOnlyWorkingSet, usedByFuncs: Graph) -> bool: 97 def verify(self, lhs: 'Lhs', workingSet: ReadOnlyWorkingSet, usedByFuncs: Graph) -> bool:
98 """Can this lhs be true all at once in workingSet? Does it match with these bindings?""" 98 """Can this lhs be true all at once in workingSet? Does it match with these bindings?"""
99 boundLhs = list(self.apply(lhs.graph)) 99 boundLhs = list(self.apply(lhs.graph))
100 boundUsedByFuncs = list(self.apply(usedByFuncs)) 100 boundUsedByFuncs = list(self.apply(usedByFuncs))
101 101
102 self.logVerifyBanner(boundLhs, workingSet, boundUsedByFuncs) 102 self._logVerifyBanner(boundLhs, workingSet, boundUsedByFuncs)
103 103
104 for stmt in boundLhs: 104 for stmt in boundLhs:
105 log.debug(f'{INDENT*4} check for {stmt}') 105 log.debug(f'{INDENT*4} check for {stmt}')
106 106
107 if stmt in boundUsedByFuncs: 107 if stmt in boundUsedByFuncs:
111 else: 111 else:
112 log.debug(f'{INDENT*5} stmt not known to be true') 112 log.debug(f'{INDENT*5} stmt not known to be true')
113 return False 113 return False
114 return True 114 return True
115 115
116 def logVerifyBanner(self, boundLhs, workingSet: ReadOnlyWorkingSet, boundUsedByFuncs): 116 def _logVerifyBanner(self, boundLhs, workingSet: ReadOnlyWorkingSet, boundUsedByFuncs):
117 if not log.isEnabledFor(logging.DEBUG): 117 if not log.isEnabledFor(logging.DEBUG):
118 return 118 return
119 log.debug(f'{INDENT*4}/ verify all bindings against this boundLhs:') 119 log.debug(f'{INDENT*4}/ verify all bindings against this boundLhs:')
120 for stmt in sorted(boundLhs): 120 for stmt in sorted(boundLhs):
121 log.debug(f'{INDENT*4}|{INDENT} {stmt}') 121 log.debug(f'{INDENT*4}|{INDENT} {stmt}')
151 def findCandidateBindings(self, workingSet: ReadOnlyWorkingSet) -> Iterator[CandidateBinding]: 151 def findCandidateBindings(self, workingSet: ReadOnlyWorkingSet) -> Iterator[CandidateBinding]:
152 """bindings that fit the LHS of a rule, using statements from workingSet and functions 152 """bindings that fit the LHS of a rule, using statements from workingSet and functions
153 from LHS""" 153 from LHS"""
154 log.debug(f'{INDENT*3} nodesToBind: {self.lhsBindables}') 154 log.debug(f'{INDENT*3} nodesToBind: {self.lhsBindables}')
155 155
156 if not self.allStaticStatementsMatch(workingSet): 156 if not self._allStaticStatementsMatch(workingSet):
157 return 157 return
158 158
159 candidateTermMatches: Dict[BindableTerm, Set[Node]] = self.allCandidateTermMatches(workingSet) 159 candidateTermMatches: Dict[BindableTerm, Set[Node]] = self._allCandidateTermMatches(workingSet)
160 160
161 orderedVars, orderedValueSets = organize(candidateTermMatches) 161 orderedVars, orderedValueSets = _organize(candidateTermMatches)
162 162
163 self.logCandidates(orderedVars, orderedValueSets) 163 self._logCandidates(orderedVars, orderedValueSets)
164 164
165 log.debug(f'{INDENT*3} trying all permutations:') 165 log.debug(f'{INDENT*3} trying all permutations:')
166 166
167 for perm in itertools.product(*orderedValueSets): 167 for perm in itertools.product(*orderedValueSets):
168 binding = CandidateBinding(dict(zip(orderedVars, perm))) 168 binding = CandidateBinding(dict(zip(orderedVars, perm)))
177 if not binding.verify(self, workingSet, usedByFuncs): 177 if not binding.verify(self, workingSet, usedByFuncs):
178 log.debug(f'{INDENT*4} this binding did not verify') 178 log.debug(f'{INDENT*4} this binding did not verify')
179 continue 179 continue
180 yield binding 180 yield binding
181 181
182 def allStaticStatementsMatch(self, workingSet: ReadOnlyWorkingSet) -> bool: 182 def _allStaticStatementsMatch(self, workingSet: ReadOnlyWorkingSet) -> bool:
183 for ruleStmt in self.staticRuleStmts: 183 for ruleStmt in self.staticRuleStmts:
184 if ruleStmt not in workingSet: 184 if ruleStmt not in workingSet:
185 log.debug(f'{INDENT*3} {ruleStmt} not in working set- skip rule') 185 log.debug(f'{INDENT*3} {ruleStmt} not in working set- skip rule')
186 return False 186 return False
187 return True 187 return True
188 188
189 def allCandidateTermMatches(self, workingSet: ReadOnlyWorkingSet) -> Dict[BindableTerm, Set[Node]]: 189 def _allCandidateTermMatches(self, workingSet: ReadOnlyWorkingSet) -> Dict[BindableTerm, Set[Node]]:
190 """the total set of terms each variable could possibly match""" 190 """the total set of terms each variable could possibly match"""
191 191
192 candidateTermMatches: Dict[BindableTerm, Set[Node]] = defaultdict(set) 192 candidateTermMatches: Dict[BindableTerm, Set[Node]] = defaultdict(set)
193 for lhsStmt in self.graph: 193 for lhsStmt in self.graph:
194 log.debug(f'{INDENT*4} possibles for this lhs stmt: {lhsStmt}') 194 log.debug(f'{INDENT*4} possibles for this lhs stmt: {lhsStmt}')
230 for stmt in self.graph: 230 for stmt in self.graph:
231 if stmt not in usedByFuncs: 231 if stmt not in usedByFuncs:
232 g.add(stmt) 232 g.add(stmt)
233 return g 233 return g
234 234
235 def logCandidates(self, orderedVars, orderedValueSets): 235 def _logCandidates(self, orderedVars, orderedValueSets):
236 if not log.isEnabledFor(logging.DEBUG): 236 if not log.isEnabledFor(logging.DEBUG):
237 return 237 return
238 log.debug(f'{INDENT*3} resulting candidate terms:') 238 log.debug(f'{INDENT*3} resulting candidate terms:')
239 for v, vals in zip(orderedVars, orderedValueSets): 239 for v, vals in zip(orderedVars, orderedValueSets):
240 log.debug(f'{INDENT*4} {v!r} could be:') 240 log.debug(f'{INDENT*4} {v!r} could be:')
252 """ 252 """
253 253
254 @staticmethod 254 @staticmethod
255 def findEvals(graph: Graph) -> Iterator['Evaluation']: 255 def findEvals(graph: Graph) -> Iterator['Evaluation']:
256 for stmt in graph.triples((None, MATH['sum'], None)): 256 for stmt in graph.triples((None, MATH['sum'], None)):
257 operands, operandsStmts = parseList(graph, stmt[0]) 257 operands, operandsStmts = _parseList(graph, stmt[0])
258 yield Evaluation(operands, stmt, operandsStmts) 258 yield Evaluation(operands, stmt, operandsStmts)
259 259
260 for stmt in graph.triples((None, MATH['greaterThan'], None)): 260 for stmt in graph.triples((None, MATH['greaterThan'], None)):
261 yield Evaluation([stmt[0], stmt[2]], stmt, []) 261 yield Evaluation([stmt[0], stmt[2]], stmt, [])
262 262
355 log.info(f'{INDENT*1} {st}') 355 log.info(f'{INDENT*1} {st}')
356 return implied 356 return implied
357 357
358 def _iterateAllRules(self, workingSet: Graph, implied: Graph): 358 def _iterateAllRules(self, workingSet: Graph, implied: Graph):
359 for i, r in enumerate(self.rules): 359 for i, r in enumerate(self.rules):
360 self.logRuleApplicationHeader(workingSet, i, r) 360 self._logRuleApplicationHeader(workingSet, i, r)
361 applyRule(Lhs(r[0]), r[2], workingSet, implied) 361 _applyRule(Lhs(r[0]), r[2], workingSet, implied)
362 362
363 def logRuleApplicationHeader(self, workingSet, i, r): 363 def _logRuleApplicationHeader(self, workingSet, i, r):
364 if not log.isEnabledFor(logging.DEBUG): 364 if not log.isEnabledFor(logging.DEBUG):
365 return 365 return
366 366
367 log.debug('') 367 log.debug('')
368 log.debug(f'{INDENT*2} workingSet:') 368 log.debug(f'{INDENT*2} workingSet:')
373 log.debug(f'{INDENT*2}-applying rule {i}') 373 log.debug(f'{INDENT*2}-applying rule {i}')
374 log.debug(f'{INDENT*3} rule def lhs: {graphDump(r[0])}') 374 log.debug(f'{INDENT*3} rule def lhs: {graphDump(r[0])}')
375 log.debug(f'{INDENT*3} rule def rhs: {graphDump(r[2])}') 375 log.debug(f'{INDENT*3} rule def rhs: {graphDump(r[2])}')
376 376
377 377
378 def applyRule(lhs: Lhs, rhs: Graph, workingSet: Graph, implied: Graph): 378 def _applyRule(lhs: Lhs, rhs: Graph, workingSet: Graph, implied: Graph):
379 for binding in lhs.findCandidateBindings(ReadOnlyGraphAggregate([workingSet])): 379 for binding in lhs.findCandidateBindings(ReadOnlyGraphAggregate([workingSet])):
380 log.debug(f'{INDENT*3} rule has a working binding:') 380 log.debug(f'{INDENT*3} rule has a working binding:')
381 381
382 for lhsBoundStmt in binding.apply(lhs.graphWithoutEvals(binding)): 382 for lhsBoundStmt in binding.apply(lhs.graphWithoutEvals(binding)):
383 log.debug(f'{INDENT*5} adding {lhsBoundStmt=}') 383 log.debug(f'{INDENT*5} adding {lhsBoundStmt=}')
386 log.debug(f'{INDENT*5} adding {newStmt=}') 386 log.debug(f'{INDENT*5} adding {newStmt=}')
387 workingSet.add(newStmt) 387 workingSet.add(newStmt)
388 implied.add(newStmt) 388 implied.add(newStmt)
389 389
390 390
391 def parseList(graph, subj) -> Tuple[List[Node], Set[Triple]]: 391 def _parseList(graph, subj) -> Tuple[List[Node], Set[Triple]]:
392 """"Do like Collection(g, subj) but also return all the 392 """"Do like Collection(g, subj) but also return all the
393 triples that are involved in the list""" 393 triples that are involved in the list"""
394 out = [] 394 out = []
395 used = set() 395 used = set()
396 cur = subj 396 cur = subj
415 lines = cast(bytes, g.serialize(format='n3')).decode('utf8').splitlines() 415 lines = cast(bytes, g.serialize(format='n3')).decode('utf8').splitlines()
416 lines = [line for line in lines if not line.startswith('@prefix')] 416 lines = [line for line in lines if not line.startswith('@prefix')]
417 return ' '.join(lines) 417 return ' '.join(lines)
418 418
419 419
420 def organize(candidateTermMatches: Dict[BindableTerm, Set[Node]]) -> Tuple[List[BindableTerm], List[List[Node]]]: 420 def _organize(candidateTermMatches: Dict[BindableTerm, Set[Node]]) -> Tuple[List[BindableTerm], List[List[Node]]]:
421 items = list(candidateTermMatches.items()) 421 items = list(candidateTermMatches.items())
422 items.sort() 422 items.sort()
423 orderedVars: List[BindableTerm] = [] 423 orderedVars: List[BindableTerm] = []
424 orderedValueSets: List[List[Node]] = [] 424 orderedValueSets: List[List[Node]] = []
425 for v, vals in items: 425 for v, vals in items: