comparison service/mqtt_to_rdf/inference.py @ 1596:4e795ed3a693

more cleanup, especially around Evaluation
author drewp@bigasterisk.com
date Sun, 05 Sep 2021 01:52:53 -0700
parents e58bcfa66093
children 387a9cb66517
comparison
equal deleted inserted replaced
1595:413a280828bf 1596:4e795ed3a693
5 import itertools 5 import itertools
6 import logging 6 import logging
7 from collections import defaultdict 7 from collections import defaultdict
8 from dataclasses import dataclass, field 8 from dataclasses import dataclass, field
9 from decimal import Decimal 9 from decimal import Decimal
10 from typing import Dict, Iterator, List, Set, Tuple, Union, cast 10 from typing import Dict, Iterable, Iterator, List, Set, Tuple, Union, cast
11 11
12 from prometheus_client import Summary 12 from prometheus_client import Summary
13 from rdflib import RDF, BNode, Graph, Literal, Namespace, URIRef 13 from rdflib import RDF, BNode, Graph, Literal, Namespace, URIRef
14 from rdflib.graph import ConjunctiveGraph, ReadOnlyGraphAggregate 14 from rdflib.graph import ConjunctiveGraph, ReadOnlyGraphAggregate
15 from rdflib.term import Node, Variable 15 from rdflib.term import Node, Variable
239 239
240 @staticmethod 240 @staticmethod
241 def findEvals(lhs: Lhs) -> Iterator['Evaluation']: 241 def findEvals(lhs: Lhs) -> Iterator['Evaluation']:
242 for stmt in lhs.graph.triples((None, MATH['sum'], None)): 242 for stmt in lhs.graph.triples((None, MATH['sum'], None)):
243 operands, operandsStmts = parseList(lhs.graph, stmt[0]) 243 operands, operandsStmts = parseList(lhs.graph, stmt[0])
244 g = Graph() 244 yield Evaluation(operands, stmt, operandsStmts)
245 g += operandsStmts
246 yield Evaluation(operands, g, stmt)
247 245
248 for stmt in lhs.graph.triples((None, MATH['greaterThan'], None)): 246 for stmt in lhs.graph.triples((None, MATH['greaterThan'], None)):
249 g = Graph() 247 yield Evaluation([stmt[0], stmt[2]], stmt, [])
250 g.add(stmt)
251 yield Evaluation([stmt[0], stmt[2]], g, stmt)
252 248
253 for stmt in lhs.graph.triples((None, ROOM['asFarenheit'], None)): 249 for stmt in lhs.graph.triples((None, ROOM['asFarenheit'], None)):
254 g = Graph() 250 yield Evaluation([stmt[0]], stmt, [])
255 g.add(stmt)
256 yield Evaluation([stmt[0]], g, stmt)
257 251
258 # internal, use findEvals 252 # internal, use findEvals
259 def __init__(self, operands: List[Node], operandsStmts: Graph, stmt: Triple) -> None: 253 def __init__(self, operands: List[Node], mainStmt: Triple, otherStmts: Iterable[Triple]) -> None:
260 self.operands = operands 254 self.operands = operands
261 self.operandsStmts = operandsStmts # may grow 255 self.operandsStmts = Graph()
262 self.stmt = stmt 256 self.operandsStmts += otherStmts # may grow
257 self.operandsStmts.add(mainStmt)
258 self.stmt = mainStmt
263 259
264 def resultBindings(self, inputBindings) -> Tuple[Dict[BindableTerm, Node], Graph]: 260 def resultBindings(self, inputBindings) -> Tuple[Dict[BindableTerm, Node], Graph]:
265 """under the bindings so far, what would this evaluation tell us, and which stmts would be consumed from doing so?""" 261 """under the bindings so far, what would this evaluation tell us, and which stmts would be consumed from doing so?"""
266 pred = self.stmt[1] 262 pred = self.stmt[1]
267 objVar: Node = self.stmt[2] 263 objVar: Node = self.stmt[2]
268 boundOperands = [] 264 boundOperands = []
269 for o in self.operands: 265 for op in self.operands:
270 if isinstance(o, Variable): 266 if isinstance(op, Variable):
271 try: 267 try:
272 o = inputBindings[o] 268 op = inputBindings[op]
273 except KeyError: 269 except KeyError:
274 return {}, self.operandsStmts 270 return {}, self.operandsStmts
275 271
276 boundOperands.append(o) 272 boundOperands.append(op)
277 273
278 if pred == MATH['sum']: 274 if pred == MATH['sum']:
279 obj = Literal(sum(map(numericNode, boundOperands))) 275 obj = Literal(sum(map(numericNode, boundOperands)))
280 self.operandsStmts.add(self.stmt)
281 if not isinstance(objVar, Variable): 276 if not isinstance(objVar, Variable):
282 raise TypeError(f'expected Variable, got {objVar!r}') 277 raise TypeError(f'expected Variable, got {objVar!r}')
283 return {objVar: obj}, self.operandsStmts 278 res: Dict[BindableTerm, Node] = {objVar: obj}
284 elif pred == ROOM['asFarenheit']: 279 elif pred == ROOM['asFarenheit']:
285 if len(boundOperands) != 1: 280 if len(boundOperands) != 1:
286 raise ValueError(":asFarenheit takes 1 subject operand") 281 raise ValueError(":asFarenheit takes 1 subject operand")
287 f = Literal(Decimal(numericNode(boundOperands[0])) * 9 / 5 + 32) 282 f = Literal(Decimal(numericNode(boundOperands[0])) * 9 / 5 + 32)
288 if not isinstance(objVar, Variable): 283 if not isinstance(objVar, Variable):
289 raise TypeError(f'expected Variable, got {objVar!r}') 284 raise TypeError(f'expected Variable, got {objVar!r}')
290 return {objVar: f}, self.operandsStmts 285 res: Dict[BindableTerm, Node] = {objVar: f}
291 elif pred == MATH['greaterThan']: 286 elif pred == MATH['greaterThan']:
292 if not (numericNode(boundOperands[0]) > numericNode(boundOperands[1])): 287 if not (numericNode(boundOperands[0]) > numericNode(boundOperands[1])):
293 raise EvaluationFailed() 288 raise EvaluationFailed()
294 return {}, self.operandsStmts 289 res: Dict[BindableTerm, Node] = {}
295 else: 290 else:
296 raise NotImplementedError(repr(pred)) 291 raise NotImplementedError(repr(pred))
292
293 return res, self.operandsStmts
297 294
298 295
299 def numericNode(n: Node): 296 def numericNode(n: Node):
300 if not isinstance(n, Literal): 297 if not isinstance(n, Literal):
301 raise TypeError(f'expected Literal, got {n=}') 298 raise TypeError(f'expected Literal, got {n=}')
411 orderedValues: List[Node] = list(vals) 408 orderedValues: List[Node] = list(vals)
412 orderedValues.sort(key=str) 409 orderedValues.sort(key=str)
413 orderedValueSets.append(orderedValues) 410 orderedValueSets.append(orderedValues)
414 411
415 return orderedVars, orderedValueSets 412 return orderedVars, orderedValueSets
416
417
418 def isStatic(spo: Triple):
419 for t in spo:
420 if isinstance(t, (Variable, BNode)):
421 return False
422 return True