annotate service/mqtt_to_rdf/lhs_evaluation.py @ 1607:b21885181e35

more modules, types. Maybe less repeated computation on BoundLhs
author drewp@bigasterisk.com
date Mon, 06 Sep 2021 15:38:48 -0700
parents 449746d1598f
children ba59cfc3c747
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1605
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
1 import logging
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
2 from decimal import Decimal
1607
b21885181e35 more modules, types. Maybe less repeated computation on BoundLhs
drewp@bigasterisk.com
parents: 1605
diff changeset
3 from typing import Dict, Iterable, Iterator, List, Set, Tuple
1605
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
4
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
5 from prometheus_client import Summary
1607
b21885181e35 more modules, types. Maybe less repeated computation on BoundLhs
drewp@bigasterisk.com
parents: 1605
diff changeset
6 from rdflib import RDF, Graph, Literal, Namespace, URIRef
1605
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
7 from rdflib.term import Node, Variable
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
8
1607
b21885181e35 more modules, types. Maybe less repeated computation on BoundLhs
drewp@bigasterisk.com
parents: 1605
diff changeset
9 from candidate_binding import CandidateBinding
b21885181e35 more modules, types. Maybe less repeated computation on BoundLhs
drewp@bigasterisk.com
parents: 1605
diff changeset
10 from inference import CandidateBinding
b21885181e35 more modules, types. Maybe less repeated computation on BoundLhs
drewp@bigasterisk.com
parents: 1605
diff changeset
11 from inference_types import BindableTerm, EvaluationFailed, Triple
b21885181e35 more modules, types. Maybe less repeated computation on BoundLhs
drewp@bigasterisk.com
parents: 1605
diff changeset
12
1605
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
13 log = logging.getLogger('infer')
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
14
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
15 INDENT = ' '
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
16
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
17 ROOM = Namespace("http://projects.bigasterisk.com/room/")
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
18 LOG = Namespace('http://www.w3.org/2000/10/swap/log#')
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
19 MATH = Namespace('http://www.w3.org/2000/10/swap/math#')
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
20
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
21 # Graph() makes a BNode if you don't pass
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
22 # identifier, which can be a bottleneck.
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
23 GRAPH_ID = URIRef('dont/care')
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
24
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
25
1607
b21885181e35 more modules, types. Maybe less repeated computation on BoundLhs
drewp@bigasterisk.com
parents: 1605
diff changeset
26 # alternate name LhsComponent
1605
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
27 class Evaluation:
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
28 """some lhs statements need to be evaluated with a special function
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
29 (e.g. math) and then not considered for the rest of the rule-firing
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
30 process. It's like they already 'matched' something, so they don't need
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
31 to match a statement from the known-true working set.
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
32
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
33 One Evaluation instance is for one function call.
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
34 """
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
35
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
36 @staticmethod
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
37 def findEvals(graph: Graph) -> Iterator['Evaluation']:
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
38 for stmt in graph.triples((None, MATH['sum'], None)):
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
39 operands, operandsStmts = _parseList(graph, stmt[0])
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
40 yield Evaluation(operands, stmt, operandsStmts)
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
41
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
42 for stmt in graph.triples((None, MATH['greaterThan'], None)):
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
43 yield Evaluation([stmt[0], stmt[2]], stmt, [])
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
44
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
45 for stmt in graph.triples((None, ROOM['asFarenheit'], None)):
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
46 yield Evaluation([stmt[0]], stmt, [])
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
47
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
48 # internal, use findEvals
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
49 def __init__(self, operands: List[Node], mainStmt: Triple, otherStmts: Iterable[Triple]) -> None:
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
50 self.operands = operands
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
51 self.operandsStmts = Graph(identifier=GRAPH_ID)
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
52 self.operandsStmts += otherStmts # may grow
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
53 self.operandsStmts.add(mainStmt)
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
54 self.stmt = mainStmt
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
55
1607
b21885181e35 more modules, types. Maybe less repeated computation on BoundLhs
drewp@bigasterisk.com
parents: 1605
diff changeset
56 def resultBindings(self, inputBindings: CandidateBinding) -> Tuple[CandidateBinding, Graph]:
1605
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
57 """under the bindings so far, what would this evaluation tell us, and which stmts would be consumed from doing so?"""
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
58 pred = self.stmt[1]
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
59 objVar: Node = self.stmt[2]
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
60 boundOperands = []
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
61 for op in self.operands:
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
62 if isinstance(op, Variable):
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
63 try:
1607
b21885181e35 more modules, types. Maybe less repeated computation on BoundLhs
drewp@bigasterisk.com
parents: 1605
diff changeset
64 op = inputBindings.binding[op]
1605
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
65 except KeyError:
1607
b21885181e35 more modules, types. Maybe less repeated computation on BoundLhs
drewp@bigasterisk.com
parents: 1605
diff changeset
66 return CandidateBinding(binding={}), self.operandsStmts
1605
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
67
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
68 boundOperands.append(op)
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
69
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
70 if pred == MATH['sum']:
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
71 obj = Literal(sum(map(numericNode, boundOperands)))
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
72 if not isinstance(objVar, Variable):
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
73 raise TypeError(f'expected Variable, got {objVar!r}')
1607
b21885181e35 more modules, types. Maybe less repeated computation on BoundLhs
drewp@bigasterisk.com
parents: 1605
diff changeset
74 res = CandidateBinding({objVar: obj})
1605
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
75 elif pred == ROOM['asFarenheit']:
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
76 if len(boundOperands) != 1:
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
77 raise ValueError(":asFarenheit takes 1 subject operand")
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
78 f = Literal(Decimal(numericNode(boundOperands[0])) * 9 / 5 + 32)
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
79 if not isinstance(objVar, Variable):
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
80 raise TypeError(f'expected Variable, got {objVar!r}')
1607
b21885181e35 more modules, types. Maybe less repeated computation on BoundLhs
drewp@bigasterisk.com
parents: 1605
diff changeset
81 res = CandidateBinding({objVar: f})
1605
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
82 elif pred == MATH['greaterThan']:
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
83 if not (numericNode(boundOperands[0]) > numericNode(boundOperands[1])):
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
84 raise EvaluationFailed()
1607
b21885181e35 more modules, types. Maybe less repeated computation on BoundLhs
drewp@bigasterisk.com
parents: 1605
diff changeset
85 res= CandidateBinding({})
1605
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
86 else:
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
87 raise NotImplementedError(repr(pred))
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
88
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
89 return res, self.operandsStmts
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
90
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
91
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
92 def numericNode(n: Node):
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
93 if not isinstance(n, Literal):
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
94 raise TypeError(f'expected Literal, got {n=}')
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
95 val = n.toPython()
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
96 if not isinstance(val, (int, float, Decimal)):
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
97 raise TypeError(f'expected number, got {val=}')
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
98 return val
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
99
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
100
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
101 def _parseList(graph, subj) -> Tuple[List[Node], Set[Triple]]:
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
102 """"Do like Collection(g, subj) but also return all the
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
103 triples that are involved in the list"""
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
104 out = []
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
105 used = set()
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
106 cur = subj
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
107 while cur != RDF.nil:
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
108 out.append(graph.value(cur, RDF.first))
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
109 used.add((cur, RDF.first, out[-1]))
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
110
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
111 next = graph.value(cur, RDF.rest)
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
112 used.add((cur, RDF.rest, next))
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
113
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
114 cur = next
449746d1598f WIP move evaluation to new file
drewp@bigasterisk.com
parents:
diff changeset
115 return out, used