comparison service/mqtt_to_rdf/inference.py @ 1632:bd79a2941cab

just (a lot of) debug changes
author drewp@bigasterisk.com
date Sun, 12 Sep 2021 21:46:39 -0700
parents 2c85a4f5dd9c
children 6107603ed455
comparison
equal deleted inserted replaced
1631:2c85a4f5dd9c 1632:bd79a2941cab
43 43
44 class Inconsistent(ValueError): 44 class Inconsistent(ValueError):
45 """adding this stmt would be inconsistent with an existing binding""" 45 """adding this stmt would be inconsistent with an existing binding"""
46 46
47 47
48 _stmtLooperShortId = itertools.count()
49
50
48 @dataclass 51 @dataclass
49 class StmtLooper: 52 class StmtLooper:
53 """given one LHS stmt, iterate through the possible matches for it,
54 returning what bindings they would imply. Only distinct bindings are
55 returned. The bindings build on any `prev` StmtLooper's results.
56
57 This iterator is restartable."""
50 lhsStmt: Triple 58 lhsStmt: Triple
51 prev: Optional['StmtLooper'] 59 prev: Optional['StmtLooper']
52 workingSet: ReadOnlyWorkingSet 60 workingSet: ReadOnlyWorkingSet
53 61
54 def __repr__(self): 62 def __repr__(self):
55 return f'StmtLooper({graphDump([self.lhsStmt])} {"<pastEnd>" if self.pastEnd() else ""})' 63 return f'StmtLooper{self._shortId}({graphDump([self.lhsStmt])} {"<pastEnd>" if self.pastEnd() else ""})'
56 64
57 def __post_init__(self): 65 def __post_init__(self):
66 self._shortId = next(_stmtLooperShortId)
58 self._myWorkingSetMatches = self._myMatches(self.workingSet) 67 self._myWorkingSetMatches = self._myMatches(self.workingSet)
59 68
60 self._current = CandidateBinding({}) 69 self._current = CandidateBinding({})
61 self._pastEnd = False 70 self._pastEnd = False
62 self._seenBindings: List[Dict[BindableTerm, Node]] = [] 71 self._seenBindings: List[Dict[BindableTerm, Node]] = []
84 try: 93 try:
85 outBinding = self._totalBindingIfThisStmtWereTrue(stmt) 94 outBinding = self._totalBindingIfThisStmtWereTrue(stmt)
86 except Inconsistent: 95 except Inconsistent:
87 log.debug(f'{INDENT*7} {self} - {stmt} would be inconsistent with prev bindings') 96 log.debug(f'{INDENT*7} {self} - {stmt} would be inconsistent with prev bindings')
88 continue 97 continue
89 log.debug(f'seen {outBinding.binding} in {self._seenBindings}') 98
99 log.debug(f'{INDENT*6} {outBinding=} {self._seenBindings=}')
90 if outBinding.binding not in self._seenBindings: 100 if outBinding.binding not in self._seenBindings:
91 self._seenBindings.append(outBinding.binding.copy()) 101 self._seenBindings.append(outBinding.binding.copy())
92 log.debug(f'no, adding')
93 self._current = outBinding 102 self._current = outBinding
94 log.debug(f'{INDENT*7} {self} - Looper matches {stmt} which tells us {outBinding}') 103 log.debug(f'{INDENT*7} new binding from {self} -> {outBinding}')
95 return 104 return
96 log.debug(f'yes we saw') 105 log.debug(f'yes we saw')
97 106
98 log.debug(f'{INDENT*6} {self} mines rules') 107 log.debug(f'{INDENT*6} {self} mines rules')
99 108
100 if self.lhsStmt[1] == ROOM['asFarenheit']: 109 if self.lhsStmt[1] == ROOM['asFarenheit']:
101 pb: Dict[BindableTerm, Node] = self._prevBindings() 110 pb: Dict[BindableTerm, Node] = self._prevBindings()
111 log.debug(f'{INDENT*6} {self} consider ?x faren ?y where ?x={self.lhsStmt[0]} and {pb=}')
112
102 if self.lhsStmt[0] in pb: 113 if self.lhsStmt[0] in pb:
103 operands = [pb[cast(BindableTerm, self.lhsStmt[0])]] 114 operands = [pb[cast(BindableTerm, self.lhsStmt[0])]]
104 f = cast(Literal, Literal(Decimal(numericNode(operands[0])) * 9 / 5 + 32)) 115 f = cast(Literal, Literal(Decimal(numericNode(operands[0])) * 9 / 5 + 32))
105 objVar = self.lhsStmt[2] 116 objVar = self.lhsStmt[2]
106 if not isinstance(objVar, Variable): 117 if not isinstance(objVar, Variable):
180 prev: Optional[StmtLooper] = None 191 prev: Optional[StmtLooper] = None
181 for s in sorted(self.graph): # order of this matters! :( 192 for s in sorted(self.graph): # order of this matters! :(
182 stmtStack.append(StmtLooper(s, prev, knownTrue)) 193 stmtStack.append(StmtLooper(s, prev, knownTrue))
183 prev = stmtStack[-1] 194 prev = stmtStack[-1]
184 except NoOptions: 195 except NoOptions:
185 log.debug(f'{INDENT*5} no options; 0 bindings') 196 log.debug(f'{INDENT*5} start up with no options; 0 bindings')
186 return 197 return
187 198 self._debugStmtStack('initial odometer', stmtStack)
188 log.debug(f'{INDENT*5} initial odometer:') 199
189 for l in stmtStack:
190 log.debug(f'{INDENT*6} {l}')
191 200
192 if any(ring.pastEnd() for ring in stmtStack): 201 if any(ring.pastEnd() for ring in stmtStack):
193 log.debug(f'{INDENT*5} some rings started at pastEnd {stmtStack}') 202 log.debug(f'{INDENT*5} some rings started at pastEnd {stmtStack}')
194 203
195 raise NoOptions() 204 raise NoOptions()
200 if iterCount > 10: 209 if iterCount > 10:
201 raise ValueError('stuck') 210 raise ValueError('stuck')
202 211
203 log.debug(f'{INDENT*4} vv findCandBindings iteration {iterCount}') 212 log.debug(f'{INDENT*4} vv findCandBindings iteration {iterCount}')
204 213
205 log.debug(f'{INDENT*5} <<<')
206 yield BoundLhs(self, sl.currentBinding()) 214 yield BoundLhs(self, sl.currentBinding())
207 log.debug(f'{INDENT*5} >>>') 215
208 216 self._debugStmtStack('odometer', stmtStack)
209 log.debug(f'{INDENT*5} odometer:')
210 for l in stmtStack:
211 log.debug(f'{INDENT*6} {l} curbind={l.currentBinding() if not l.pastEnd() else "<end>"}')
212 217
213 done = self._advanceAll(stmtStack) 218 done = self._advanceAll(stmtStack)
214 219
215 log.debug(f'{INDENT*5} odometer after ({done=}):') 220 self._debugStmtStack('odometer after ({done=})', stmtStack)
216 for l in stmtStack:
217 log.debug(f'{INDENT*6} {l} curbind={l.currentBinding() if not l.pastEnd() else "<end>"}')
218 221
219 log.debug(f'{INDENT*4} ^^ findCandBindings iteration done') 222 log.debug(f'{INDENT*4} ^^ findCandBindings iteration done')
220 if done: 223 if done:
221 break 224 break
225
226 def _debugStmtStack(self, label, stmtStack):
227 log.debug(f'{INDENT*5} {label}:')
228 for l in stmtStack:
229 log.debug(f'{INDENT*6} {l} curbind={l.currentBinding() if not l.pastEnd() else "<end>"}')
222 230
223 def _advanceAll(self, stmtStack: List[StmtLooper]) -> bool: 231 def _advanceAll(self, stmtStack: List[StmtLooper]) -> bool:
224 carry = True # 1st elem always must advance 232 carry = True # 1st elem always must advance
225 for i, ring in enumerate(stmtStack): 233 for i, ring in enumerate(stmtStack):
226 # unlike normal odometer, advancing any earlier ring could invalidate later ones 234 # unlike normal odometer, advancing any earlier ring could invalidate later ones
385 393
386 @dataclass 394 @dataclass
387 class Rule: 395 class Rule:
388 lhsGraph: Graph 396 lhsGraph: Graph
389 rhsGraph: Graph 397 rhsGraph: Graph
390 398
391 def __post_init__(self): 399 def __post_init__(self):
392 self.lhs = Lhs(self.lhsGraph) 400 self.lhs = Lhs(self.lhsGraph)
393 # 401 #
394 self.rhsBnodeMap = {} 402 self.rhsBnodeMap = {}
395 403
396 def applyRule(self, workingSet: Graph, implied: Graph, stats: Dict): 404 def applyRule(self, workingSet: Graph, implied: Graph, stats: Dict):
397 for bound in self.lhs.findCandidateBindings(ReadOnlyGraphAggregate([workingSet]), stats): 405 for bound in self.lhs.findCandidateBindings(ReadOnlyGraphAggregate([workingSet]), stats):
398 log.debug(f'{INDENT*5} +rule has a working binding: {bound}') 406 log.debug(f'{INDENT*5} +rule has a working binding: {bound}')
402 for stmt in self.rhsGraph: 410 for stmt in self.rhsGraph:
403 for t in stmt: 411 for t in stmt:
404 if isinstance(t, BNode): 412 if isinstance(t, BNode):
405 existingRhsBnodes.add(t) 413 existingRhsBnodes.add(t)
406 # if existingRhsBnodes: 414 # if existingRhsBnodes:
407 # log.debug(f'{INDENT*6} mapping rhs bnodes {existingRhsBnodes} to new ones') 415 # log.debug(f'{INDENT*6} mapping rhs bnodes {existingRhsBnodes} to new ones')
408 416
409 for b in existingRhsBnodes: 417 for b in existingRhsBnodes:
410 418
411 key = tuple(sorted(bound.binding.binding.items())), b 419 key = tuple(sorted(bound.binding.binding.items())), b
412 self.rhsBnodeMap.setdefault(key, BNode()) 420 self.rhsBnodeMap.setdefault(key, BNode())
413
414 421
415 bound.binding.addNewBindings(CandidateBinding({b: self.rhsBnodeMap[key]})) 422 bound.binding.addNewBindings(CandidateBinding({b: self.rhsBnodeMap[key]}))
416 423
417 # for lhsBoundStmt in bound.binding.apply(bound.lhsStmtsWithoutEvals()): 424 # for lhsBoundStmt in bound.binding.apply(bound.lhsStmtsWithoutEvals()):
418 # log.debug(f'{INDENT*6} adding to workingSet {lhsBoundStmt=}') 425 # log.debug(f'{INDENT*6} adding to workingSet {lhsBoundStmt=}')
487 for j, stmt in enumerate(sorted(workingSet)): 494 for j, stmt in enumerate(sorted(workingSet)):
488 log.debug(f'{INDENT*3} ({j}) {stmt}') 495 log.debug(f'{INDENT*3} ({j}) {stmt}')
489 496
490 log.debug('') 497 log.debug('')
491 log.debug(f'{INDENT*2}-applying rule {i}') 498 log.debug(f'{INDENT*2}-applying rule {i}')
492 log.debug(f'{INDENT*3} rule def lhs: {graphDump(r.lhsGraph)}') 499 log.debug(f'{INDENT*3} rule def lhs:')
500 for stmt in r.lhsGraph:
501 log.debug(f'{INDENT*4} {stmt}')
493 log.debug(f'{INDENT*3} rule def rhs: {graphDump(r.rhsGraph)}') 502 log.debug(f'{INDENT*3} rule def rhs: {graphDump(r.rhsGraph)}')
494 503
495 504
496 def graphDump(g: Union[Graph, List[Triple]]): 505 def graphDump(g: Union[Graph, List[Triple]]):
497 if not isinstance(g, Graph): 506 if not isinstance(g, Graph):