Mercurial > code > home > repos > homeauto
changeset 1636:3252bdc284bc
rm dead code from previous tries
author | drewp@bigasterisk.com |
---|---|
date | Mon, 13 Sep 2021 00:18:47 -0700 |
parents | 22d481f0a924 |
children | ec3f98d0c1d8 |
files | service/mqtt_to_rdf/inference.py service/mqtt_to_rdf/lhs_evaluation.py |
diffstat | 2 files changed, 7 insertions(+), 253 deletions(-) [+] |
line wrap: on
line diff
--- a/service/mqtt_to_rdf/inference.py Mon Sep 13 00:06:00 2021 -0700 +++ b/service/mqtt_to_rdf/inference.py Mon Sep 13 00:18:47 2021 -0700 @@ -15,8 +15,8 @@ from rdflib.term import Literal, Node, Variable from candidate_binding import CandidateBinding -from inference_types import (BindableTerm, BindingUnknown, EvaluationFailed, ReadOnlyWorkingSet, Triple) -from lhs_evaluation import Decimal, Evaluation, numericNode, parseList +from inference_types import (BindableTerm, BindingUnknown, ReadOnlyWorkingSet, Triple) +from lhs_evaluation import Decimal, numericNode, parseList log = logging.getLogger('infer') INDENT = ' ' @@ -233,10 +233,6 @@ raise NotImplementedError() return self._current - def newLhsStmts(self) -> List[Triple]: - """under the curent bindings, what new stmts beyond workingSet are also true? includes all `prev`""" - return [] - def pastEnd(self) -> bool: return self._pastEnd @@ -253,24 +249,7 @@ graph: Graph def __post_init__(self): - # do precomputation in here that's not specific to the workingSet - # self.staticRuleStmts = Graph() - # self.nonStaticRuleStmts = Graph() - - # self.lhsBindables: Set[BindableTerm] = set() - # self.lhsBnodes: Set[BNode] = set() - # for ruleStmt in self.graph: - # varsAndBnodesInStmt = [term for term in ruleStmt if isinstance(term, (Variable, BNode))] - # self.lhsBindables.update(varsAndBnodesInStmt) - # self.lhsBnodes.update(x for x in varsAndBnodesInStmt if isinstance(x, BNode)) - # if not varsAndBnodesInStmt: - # self.staticRuleStmts.add(ruleStmt) - # else: - # self.nonStaticRuleStmts.add(ruleStmt) - - # self.nonStaticRuleStmtsSet = set(self.nonStaticRuleStmts) - - self.evaluations = list(Evaluation.findEvals(self.graph)) + pass def __repr__(self): return f"Lhs({graphDump(self.graph)})" @@ -380,151 +359,12 @@ log.debug(f'{INDENT*5} some rings started at pastEnd {stmtStack}') raise NoOptions() - def _allStaticStatementsMatch(self, knownTrue: ReadOnlyWorkingSet) -> bool: - # bug: see TestSelfFulfillingRule.test3 for a case where this rule's - # static stmt is matched by a non-static stmt in the rule itself - for ruleStmt in self.staticRuleStmts: - if ruleStmt not in knownTrue: - log.debug(f'{INDENT*3} {ruleStmt} not in working set- skip rule') - return False - return True - - def _possibleBindings(self, workingSet, stats) -> Iterator['BoundLhs']: - """this yields at least the working bindings, and possibly others""" - candidateTermMatches: Dict[BindableTerm, Set[Node]] = self._allCandidateTermMatches(workingSet) - for bindRow in self._product(candidateTermMatches): - try: - yield BoundLhs(self, bindRow) - except EvaluationFailed: - stats['permCountFailingEval'] += 1 - - def _allCandidateTermMatches(self, workingSet: ReadOnlyWorkingSet) -> Dict[BindableTerm, Set[Node]]: - """the total set of terms each variable could possibly match""" - - candidateTermMatches: Dict[BindableTerm, Set[Node]] = defaultdict(set) - for lhsStmt in self.graph: - log.debug(f'{INDENT*4} possibles for this lhs stmt: {lhsStmt}') - for i, trueStmt in enumerate(workingSet): - # log.debug(f'{INDENT*5} consider this true stmt ({i}): {trueStmt}') - - for v, vals in self._bindingsFromStatement(lhsStmt, trueStmt): - candidateTermMatches[v].update(vals) - - return candidateTermMatches - - def _bindingsFromStatement(self, stmt1: Triple, stmt2: Triple) -> Iterator[Tuple[Variable, Set[Node]]]: - """if these stmts match otherwise, what BNode or Variable mappings do we learn? - - e.g. stmt1=(?x B ?y) and stmt2=(A B C), then we yield (?x, {A}) and (?y, {C}) - or stmt1=(_:x B C) and stmt2=(A B C), then we yield (_:x, {A}) - or stmt1=(?x B C) and stmt2=(A B D), then we yield nothing - """ - bindingsFromStatement = {} - for term1, term2 in zip(stmt1, stmt2): - if isinstance(term1, (BNode, Variable)): - bindingsFromStatement.setdefault(term1, set()).add(term2) - elif term1 != term2: - break - else: - for v, vals in bindingsFromStatement.items(): - log.debug(f'{INDENT*5} {v=} {vals=}') - yield v, vals - - def _product(self, candidateTermMatches: Dict[BindableTerm, Set[Node]]) -> Iterator[CandidateBinding]: - orderedVars, orderedValueSets = _organize(candidateTermMatches) - self._logCandidates(orderedVars, orderedValueSets) - log.debug(f'{INDENT*3} trying all permutations:') - if not orderedValueSets: - yield CandidateBinding({}) - return - - if not orderedValueSets or not all(orderedValueSets): - # some var or bnode has no options at all - return - rings: List[Iterator[Node]] = [itertools.cycle(valSet) for valSet in orderedValueSets] - currentSet: List[Node] = [next(ring) for ring in rings] - starts = [valSet[-1] for valSet in orderedValueSets] - while True: - for col, curr in enumerate(currentSet): - currentSet[col] = next(rings[col]) - log.debug(f'{INDENT*4} currentSet: {repr(currentSet)}') - yield CandidateBinding(dict(zip(orderedVars, currentSet))) - if curr is not starts[col]: - break - if col == len(orderedValueSets) - 1: - return - - def _logCandidates(self, orderedVars, orderedValueSets): - if not log.isEnabledFor(logging.DEBUG): - return - log.debug(f'{INDENT*3} resulting candidate terms:') - for v, vals in zip(orderedVars, orderedValueSets): - log.debug(f'{INDENT*4} {v!r} could be:') - for val in vals: - log.debug(f'{INDENT*5}{val!r}') - @dataclass class BoundLhs: lhs: Lhs binding: CandidateBinding - def __post_init__(self): - self.usedByFuncs = Graph() - # self._applyFunctions() - - def lhsStmtsWithoutEvals(self): - for stmt in self.lhs.graph: - if stmt in self.usedByFuncs: - continue - yield stmt - - def _applyFunctions(self): - """may grow the binding with some results""" - while True: - delta = self._applyFunctionsIteration() - if delta == 0: - break - - def _applyFunctionsIteration(self): - before = len(self.binding.binding) - delta = 0 - for ev in self.lhs.evaluations: - newBindings, usedGraph = ev.resultBindings(self.binding) - self.usedByFuncs += usedGraph - self.binding.addNewBindings(newBindings) - delta = len(self.binding.binding) - before - log.debug(f'{INDENT*4} eval rules made {delta} new bindings') - return delta - - def verify(self, workingSet: ReadOnlyWorkingSet) -> bool: - """Can this bound lhs be true all at once in workingSet?""" - rem = cast(Set[Triple], self.lhs.nonStaticRuleStmtsSet.difference(self.usedByFuncs)) - boundLhs = self.binding.apply(rem) - - if log.isEnabledFor(logging.DEBUG): - boundLhs = list(boundLhs) - self._logVerifyBanner(boundLhs, workingSet) - - for stmt in boundLhs: - log.debug(f'{INDENT*4} check for %s', stmt) - - if stmt not in workingSet: - log.debug(f'{INDENT*5} stmt not known to be true') - return False - return True - - def _logVerifyBanner(self, boundLhs, workingSet: ReadOnlyWorkingSet): - log.debug(f'{INDENT*4}/ verify all bindings against this boundLhs:') - for stmt in sorted(boundLhs): - log.debug(f'{INDENT*4}|{INDENT} {stmt}') - - # log.debug(f'{INDENT*4}| and against this workingSet:') - # for stmt in sorted(workingSet): - # log.debug(f'{INDENT*4}|{INDENT} {stmt}') - - log.debug(f'{INDENT*4}\\') - @dataclass class Rule: @@ -647,17 +487,3 @@ lines = cast(bytes, g.serialize(format='n3')).decode('utf8').splitlines() lines = [line.strip() for line in lines if not line.startswith('@prefix')] return ' '.join(lines) - - -def _organize(candidateTermMatches: Dict[BindableTerm, Set[Node]]) -> Tuple[List[BindableTerm], List[List[Node]]]: - items = list(candidateTermMatches.items()) - items.sort() - orderedVars: List[BindableTerm] = [] - orderedValueSets: List[List[Node]] = [] - for v, vals in items: - orderedVars.append(v) - orderedValues: List[Node] = list(vals) - orderedValues.sort(key=str) - orderedValueSets.append(orderedValues) - - return orderedVars, orderedValueSets
--- a/service/mqtt_to_rdf/lhs_evaluation.py Mon Sep 13 00:06:00 2021 -0700 +++ b/service/mqtt_to_rdf/lhs_evaluation.py Mon Sep 13 00:18:47 2021 -0700 @@ -1,14 +1,12 @@ import logging from decimal import Decimal -from typing import Dict, Iterable, Iterator, List, Set, Tuple +from typing import List, Set, Tuple from prometheus_client import Summary -from rdflib import RDF, Graph, Literal, Namespace, URIRef -from rdflib.term import Node, Variable +from rdflib import RDF, Literal, Namespace, URIRef +from rdflib.term import Node -from candidate_binding import CandidateBinding -from inference import CandidateBinding -from inference_types import BindableTerm, EvaluationFailed, Triple +from inference_types import Triple log = logging.getLogger('infer') @@ -18,76 +16,6 @@ LOG = Namespace('http://www.w3.org/2000/10/swap/log#') MATH = Namespace('http://www.w3.org/2000/10/swap/math#') -# Graph() makes a BNode if you don't pass -# identifier, which can be a bottleneck. -GRAPH_ID = URIRef('dont/care') - - -# alternate name LhsComponent -class Evaluation: - """some lhs statements need to be evaluated with a special function - (e.g. math) and then not considered for the rest of the rule-firing - process. It's like they already 'matched' something, so they don't need - to match a statement from the known-true working set. - - One Evaluation instance is for one function call. - """ - - @staticmethod - def findEvals(graph: Graph) -> Iterator['Evaluation']: - for stmt in graph.triples((None, MATH['sum'], None)): - operands, operandsStmts = parseList(graph, stmt[0]) - yield Evaluation(operands, stmt, operandsStmts) - - for stmt in graph.triples((None, MATH['greaterThan'], None)): - yield Evaluation([stmt[0], stmt[2]], stmt, []) - - for stmt in graph.triples((None, ROOM['asFarenheit'], None)): - yield Evaluation([stmt[0]], stmt, []) - - # internal, use findEvals - def __init__(self, operands: List[Node], mainStmt: Triple, otherStmts: Iterable[Triple]) -> None: - self.operands = operands - self.operandsStmts = Graph(identifier=GRAPH_ID) - self.operandsStmts += otherStmts # may grow - self.operandsStmts.add(mainStmt) - self.stmt = mainStmt - - def resultBindings(self, inputBindings: CandidateBinding) -> Tuple[CandidateBinding, Graph]: - """under the bindings so far, what would this evaluation tell us, and which stmts would be consumed from doing so?""" - pred = self.stmt[1] - objVar: Node = self.stmt[2] - boundOperands = [] - for op in self.operands: - if isinstance(op, Variable): - try: - op = inputBindings.binding[op] - except KeyError: - return CandidateBinding(binding={}), self.operandsStmts - - boundOperands.append(op) - - if pred == MATH['sum']: - obj = Literal(sum(map(numericNode, boundOperands))) - if not isinstance(objVar, Variable): - raise TypeError(f'expected Variable, got {objVar!r}') - res = CandidateBinding({objVar: obj}) - elif pred == ROOM['asFarenheit']: - if len(boundOperands) != 1: - raise ValueError(":asFarenheit takes 1 subject operand") - f = Literal(Decimal(numericNode(boundOperands[0])) * 9 / 5 + 32) - if not isinstance(objVar, Variable): - raise TypeError(f'expected Variable, got {objVar!r}') - res = CandidateBinding({objVar: f}) - elif pred == MATH['greaterThan']: - if not (numericNode(boundOperands[0]) > numericNode(boundOperands[1])): - raise EvaluationFailed() - res= CandidateBinding({}) - else: - raise NotImplementedError(repr(pred)) - - return res, self.operandsStmts - def numericNode(n: Node): if not isinstance(n, Literal):