changeset 1622:38bd8ef9ef67

add CandidateTermMatches, unused so far
author drewp@bigasterisk.com
date Wed, 08 Sep 2021 18:53:26 -0700
parents da235054caa0
children cf901d219007
files service/mqtt_to_rdf/inference.py
diffstat 1 files changed, 52 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/service/mqtt_to_rdf/inference.py	Wed Sep 08 18:51:18 2021 -0700
+++ b/service/mqtt_to_rdf/inference.py	Wed Sep 08 18:53:26 2021 -0700
@@ -7,7 +7,7 @@
 import time
 from collections import defaultdict
 from dataclasses import dataclass, field
-from typing import Dict, Iterator, List, Set, Tuple, Union, cast
+from typing import Dict, Iterator, List, Optional, Set, Tuple, Union, cast
 
 from prometheus_client import Summary
 from rdflib import BNode, Graph, Namespace, URIRef
@@ -167,6 +167,57 @@
 
 
 @dataclass
+class CandidateTermMatches:
+    """lazily find the possible matches for this term"""
+    term: BindableTerm
+    lhs: Lhs
+    workingSet: Graph
+    boundSoFar: CandidateBinding
+
+    def __post_init__(self):
+        self.results: List[Node] = []  # we have to be able to repeat the results
+
+        res: Set[Node] = set()
+        for trueStmt in self.workingSet:  # all bound
+            lStmts = list(self.lhsStmtsContainingTerm())
+            log.debug(f'{INDENT*4} {trueStmt=} {len(lStmts)}')
+            for pat in self.boundSoFar.apply(lStmts, returnBoundStatementsOnly=False):
+                log.debug(f'{INDENT*4} {pat=}')
+                implied = self._stmtImplies(pat, trueStmt)
+                if implied is not None:
+                    res.add(implied)
+        self.results = list(res)
+        # self.results.sort()
+
+        log.debug(f'{INDENT*3} CandTermMatches: {self.term} {graphDump(self.lhs.graph)} {self.boundSoFar=} ===> {self.results=}')
+
+    def _stmtImplies(self, pat: Triple, trueStmt: Triple) -> Optional[Node]:
+        """what value, if any, do we learn for our term from this LHS pattern statement and this known-true stmt"""
+        r = None
+        for p, t in zip(pat, trueStmt):
+            if isinstance(p, (Variable, BNode)):
+                if p != self.term:
+                    # stmt is unbound in more than just our term
+                    continue  # unsure what to do - err on the side of too many bindings, since they get rechecked later
+                if r is None:
+                    r = t
+                    log.debug(f'{INDENT*4}  implied term value {p=} {t=}')
+                elif r != t:
+                    # (?x c ?x) matched with (a b c) doesn't work
+                    return None
+        return r
+
+    def lhsStmtsContainingTerm(self):
+        # lhs could precompute this
+        for lhsStmt in self.lhs.graph:
+            if self.term in lhsStmt:
+                yield lhsStmt
+
+    def __iter__(self):
+        return iter(self.results)
+
+
+@dataclass
 class BoundLhs:
     lhs: Lhs
     binding: CandidateBinding