Mercurial > code > home > repos > homeauto
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): |