Mercurial > code > home > repos > homeauto
annotate service/mqtt_to_rdf/lhs_evaluation.py @ 1673:80f4e741ca4f
redo RHS bnode processing
author | drewp@bigasterisk.com |
---|---|
date | Wed, 22 Sep 2021 01:00:32 -0700 |
parents | 00a5624d1d14 |
children |
rev | line source |
---|---|
1605 | 1 import logging |
2 from decimal import Decimal | |
1673 | 3 from typing import Dict, Iterator, List, Optional, Type, Union, cast |
1605 | 4 |
1673 | 5 from rdflib import Literal, Namespace, URIRef |
1651
20474ad4968e
WIP - functions are broken as i move most layers to work in Chunks not Triples
drewp@bigasterisk.com
parents:
1648
diff
changeset
|
6 from rdflib.term import Node, Variable |
1605 | 7 |
1651
20474ad4968e
WIP - functions are broken as i move most layers to work in Chunks not Triples
drewp@bigasterisk.com
parents:
1648
diff
changeset
|
8 from candidate_binding import CandidateBinding |
1673 | 9 from inference_types import BindableTerm |
10 from stmt_chunk import Chunk | |
1607
b21885181e35
more modules, types. Maybe less repeated computation on BoundLhs
drewp@bigasterisk.com
parents:
1605
diff
changeset
|
11 |
1605 | 12 log = logging.getLogger('infer') |
13 | |
14 INDENT = ' ' | |
15 | |
16 ROOM = Namespace("http://projects.bigasterisk.com/room/") | |
17 LOG = Namespace('http://www.w3.org/2000/10/swap/log#') | |
18 MATH = Namespace('http://www.w3.org/2000/10/swap/math#') | |
19 | |
20 | |
1658 | 21 def _numericNode(n: Node): |
1605 | 22 if not isinstance(n, Literal): |
23 raise TypeError(f'expected Literal, got {n=}') | |
24 val = n.toPython() | |
25 if not isinstance(val, (int, float, Decimal)): | |
26 raise TypeError(f'expected number, got {val=}') | |
27 return val | |
28 | |
29 | |
1637 | 30 class Function: |
31 """any rule stmt that runs a function (not just a statement match)""" | |
1640 | 32 pred: URIRef |
1637 | 33 |
1661 | 34 def __init__(self, chunk: Chunk): |
1651
20474ad4968e
WIP - functions are broken as i move most layers to work in Chunks not Triples
drewp@bigasterisk.com
parents:
1648
diff
changeset
|
35 self.chunk = chunk |
20474ad4968e
WIP - functions are broken as i move most layers to work in Chunks not Triples
drewp@bigasterisk.com
parents:
1648
diff
changeset
|
36 if chunk.predicate != self.pred: |
1637 | 37 raise TypeError |
38 | |
39 def getOperandNodes(self, existingBinding: CandidateBinding) -> List[Node]: | |
40 raise NotImplementedError | |
41 | |
42 def getNumericOperands(self, existingBinding: CandidateBinding) -> List[Union[int, float, Decimal]]: | |
43 out = [] | |
44 for op in self.getOperandNodes(existingBinding): | |
1658 | 45 out.append(_numericNode(op)) |
1637 | 46 |
47 return out | |
48 | |
49 def bind(self, existingBinding: CandidateBinding) -> Optional[CandidateBinding]: | |
50 """either any new bindings this function makes (could be 0), or None if it doesn't match""" | |
51 raise NotImplementedError | |
52 | |
53 def valueInObjectTerm(self, value: Node) -> Optional[CandidateBinding]: | |
1651
20474ad4968e
WIP - functions are broken as i move most layers to work in Chunks not Triples
drewp@bigasterisk.com
parents:
1648
diff
changeset
|
54 objVar = self.chunk.primary[2] |
1637 | 55 if not isinstance(objVar, Variable): |
56 raise TypeError(f'expected Variable, got {objVar!r}') | |
57 return CandidateBinding({cast(BindableTerm, objVar): value}) | |
58 | |
59 | |
60 class SubjectFunction(Function): | |
61 """function that depends only on the subject term""" | |
62 | |
63 def getOperandNodes(self, existingBinding: CandidateBinding) -> List[Node]: | |
1660
31f7dab6a60b
function evaluation uses Chunk lists now and runs fast. Only a few edge cases still broken
drewp@bigasterisk.com
parents:
1658
diff
changeset
|
64 if self.chunk.primary[0] is None: |
31f7dab6a60b
function evaluation uses Chunk lists now and runs fast. Only a few edge cases still broken
drewp@bigasterisk.com
parents:
1658
diff
changeset
|
65 raise ValueError(f'expected one operand on {self.chunk}') |
1651
20474ad4968e
WIP - functions are broken as i move most layers to work in Chunks not Triples
drewp@bigasterisk.com
parents:
1648
diff
changeset
|
66 return [existingBinding.applyTerm(self.chunk.primary[0])] |
1637 | 67 |
68 | |
69 class SubjectObjectFunction(Function): | |
70 """a filter function that depends on the subject and object terms""" | |
71 | |
72 def getOperandNodes(self, existingBinding: CandidateBinding) -> List[Node]: | |
1660
31f7dab6a60b
function evaluation uses Chunk lists now and runs fast. Only a few edge cases still broken
drewp@bigasterisk.com
parents:
1658
diff
changeset
|
73 if self.chunk.primary[0] is None or self.chunk.primary[2] is None: |
31f7dab6a60b
function evaluation uses Chunk lists now and runs fast. Only a few edge cases still broken
drewp@bigasterisk.com
parents:
1658
diff
changeset
|
74 raise ValueError(f'expected one operand on each side of {self.chunk}') |
1651
20474ad4968e
WIP - functions are broken as i move most layers to work in Chunks not Triples
drewp@bigasterisk.com
parents:
1648
diff
changeset
|
75 return [existingBinding.applyTerm(self.chunk.primary[0]), existingBinding.applyTerm(self.chunk.primary[2])] |
1637 | 76 |
77 | |
78 class ListFunction(Function): | |
79 """function that takes an rdf list as input""" | |
80 | |
81 def getOperandNodes(self, existingBinding: CandidateBinding) -> List[Node]: | |
1660
31f7dab6a60b
function evaluation uses Chunk lists now and runs fast. Only a few edge cases still broken
drewp@bigasterisk.com
parents:
1658
diff
changeset
|
82 if self.chunk.subjList is None: |
31f7dab6a60b
function evaluation uses Chunk lists now and runs fast. Only a few edge cases still broken
drewp@bigasterisk.com
parents:
1658
diff
changeset
|
83 raise ValueError(f'expected subject list on {self.chunk}') |
31f7dab6a60b
function evaluation uses Chunk lists now and runs fast. Only a few edge cases still broken
drewp@bigasterisk.com
parents:
1658
diff
changeset
|
84 return [existingBinding.applyTerm(x) for x in self.chunk.subjList] |
31f7dab6a60b
function evaluation uses Chunk lists now and runs fast. Only a few edge cases still broken
drewp@bigasterisk.com
parents:
1658
diff
changeset
|
85 |
31f7dab6a60b
function evaluation uses Chunk lists now and runs fast. Only a few edge cases still broken
drewp@bigasterisk.com
parents:
1658
diff
changeset
|
86 |
31f7dab6a60b
function evaluation uses Chunk lists now and runs fast. Only a few edge cases still broken
drewp@bigasterisk.com
parents:
1658
diff
changeset
|
87 _registeredFunctionTypes: List[Type['Function']] = [] |
1637 | 88 |
1660
31f7dab6a60b
function evaluation uses Chunk lists now and runs fast. Only a few edge cases still broken
drewp@bigasterisk.com
parents:
1658
diff
changeset
|
89 |
31f7dab6a60b
function evaluation uses Chunk lists now and runs fast. Only a few edge cases still broken
drewp@bigasterisk.com
parents:
1658
diff
changeset
|
90 def register(cls: Type['Function']): |
31f7dab6a60b
function evaluation uses Chunk lists now and runs fast. Only a few edge cases still broken
drewp@bigasterisk.com
parents:
1658
diff
changeset
|
91 _registeredFunctionTypes.append(cls) |
31f7dab6a60b
function evaluation uses Chunk lists now and runs fast. Only a few edge cases still broken
drewp@bigasterisk.com
parents:
1658
diff
changeset
|
92 return cls |
31f7dab6a60b
function evaluation uses Chunk lists now and runs fast. Only a few edge cases still broken
drewp@bigasterisk.com
parents:
1658
diff
changeset
|
93 |
31f7dab6a60b
function evaluation uses Chunk lists now and runs fast. Only a few edge cases still broken
drewp@bigasterisk.com
parents:
1658
diff
changeset
|
94 |
31f7dab6a60b
function evaluation uses Chunk lists now and runs fast. Only a few edge cases still broken
drewp@bigasterisk.com
parents:
1658
diff
changeset
|
95 import inference_functions # calls register() on some classes |
1637 | 96 |
1658 | 97 _byPred: Dict[URIRef, Type[Function]] = dict((cls.pred, cls) for cls in _registeredFunctionTypes) |
1651
20474ad4968e
WIP - functions are broken as i move most layers to work in Chunks not Triples
drewp@bigasterisk.com
parents:
1648
diff
changeset
|
98 |
20474ad4968e
WIP - functions are broken as i move most layers to work in Chunks not Triples
drewp@bigasterisk.com
parents:
1648
diff
changeset
|
99 |
1640 | 100 def functionsFor(pred: URIRef) -> Iterator[Type[Function]]: |
101 try: | |
102 yield _byPred[pred] | |
103 except KeyError: | |
104 return |