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