Mercurial > code > home > repos > homeauto
comparison service/mqtt_to_rdf/lhs_evaluation.py @ 1651:20474ad4968e
WIP - functions are broken as i move most layers to work in Chunks not Triples
A Chunk is a Triple plus any rdf lists.
author | drewp@bigasterisk.com |
---|---|
date | Sat, 18 Sep 2021 23:57:20 -0700 |
parents | 3059f31b2dfa |
children | 7ec2483d61b5 |
comparison
equal
deleted
inserted
replaced
1650:2061df259224 | 1651:20474ad4968e |
---|---|
1 from dataclasses import dataclass | |
2 import logging | 1 import logging |
3 from decimal import Decimal | 2 from decimal import Decimal |
4 from candidate_binding import CandidateBinding | 3 from typing import (Dict, Iterator, List, Optional, Set, Tuple, Type, Union, cast) |
5 from typing import Dict, Iterator, List, Optional, Set, Tuple, Type, Union, cast | |
6 | 4 |
7 from prometheus_client import Summary | 5 from prometheus_client import Summary |
8 from rdflib import RDF, Literal, Namespace, URIRef | 6 from rdflib import RDF, Literal, Namespace, URIRef |
9 from rdflib.graph import Graph | 7 from rdflib.term import Node, Variable |
10 from rdflib.term import BNode, Node, Variable | |
11 | 8 |
9 from candidate_binding import CandidateBinding | |
12 from inference_types import BindableTerm, Triple | 10 from inference_types import BindableTerm, Triple |
11 from stmt_chunk import Chunk, ChunkedGraph | |
13 | 12 |
14 log = logging.getLogger('infer') | 13 log = logging.getLogger('infer') |
15 | 14 |
16 INDENT = ' ' | 15 INDENT = ' ' |
17 | 16 |
27 if not isinstance(val, (int, float, Decimal)): | 26 if not isinstance(val, (int, float, Decimal)): |
28 raise TypeError(f'expected number, got {val=}') | 27 raise TypeError(f'expected number, got {val=}') |
29 return val | 28 return val |
30 | 29 |
31 | 30 |
32 def parseList(graph, subj) -> Tuple[List[Node], Set[Triple]]: | 31 def parseList(graph: ChunkedGraph, subj: Node) -> Tuple[List[Node], Set[Triple]]: |
33 """"Do like Collection(g, subj) but also return all the | 32 """"Do like Collection(g, subj) but also return all the |
34 triples that are involved in the list""" | 33 triples that are involved in the list""" |
35 out = [] | 34 out = [] |
36 used = set() | 35 used = set() |
37 cur = subj | 36 cur = subj |
61 | 60 |
62 class Function: | 61 class Function: |
63 """any rule stmt that runs a function (not just a statement match)""" | 62 """any rule stmt that runs a function (not just a statement match)""" |
64 pred: URIRef | 63 pred: URIRef |
65 | 64 |
66 def __init__(self, stmt: Triple, ruleGraph: Graph): | 65 def __init__(self, chunk: Chunk, ruleGraph: ChunkedGraph): |
67 self.stmt = stmt | 66 self.chunk = chunk |
68 if stmt[1] != self.pred: | 67 if chunk.predicate != self.pred: |
69 raise TypeError | 68 raise TypeError |
70 self.ruleGraph = ruleGraph | 69 self.ruleGraph = ruleGraph |
71 | 70 |
72 def getOperandNodes(self, existingBinding: CandidateBinding) -> List[Node]: | 71 def getOperandNodes(self, existingBinding: CandidateBinding) -> List[Node]: |
73 raise NotImplementedError | 72 raise NotImplementedError |
82 def bind(self, existingBinding: CandidateBinding) -> Optional[CandidateBinding]: | 81 def bind(self, existingBinding: CandidateBinding) -> Optional[CandidateBinding]: |
83 """either any new bindings this function makes (could be 0), or None if it doesn't match""" | 82 """either any new bindings this function makes (could be 0), or None if it doesn't match""" |
84 raise NotImplementedError | 83 raise NotImplementedError |
85 | 84 |
86 def valueInObjectTerm(self, value: Node) -> Optional[CandidateBinding]: | 85 def valueInObjectTerm(self, value: Node) -> Optional[CandidateBinding]: |
87 objVar = self.stmt[2] | 86 objVar = self.chunk.primary[2] |
88 if not isinstance(objVar, Variable): | 87 if not isinstance(objVar, Variable): |
89 raise TypeError(f'expected Variable, got {objVar!r}') | 88 raise TypeError(f'expected Variable, got {objVar!r}') |
90 return CandidateBinding({cast(BindableTerm, objVar): value}) | 89 return CandidateBinding({cast(BindableTerm, objVar): value}) |
91 | 90 |
92 def usedStatements(self) -> Set[Triple]: | 91 def usedStatements(self) -> Set[Triple]: |
93 '''stmts in self.graph (not including self.stmt, oddly) that are part of | 92 '''stmts in self.graph (not including self.stmt, oddly) that are part of |
94 this function setup and aren't to be matched literally''' | 93 this function setup and aren't to be matched literally''' |
95 return set() | 94 return set() |
96 | 95 |
97 | 96 |
98 class SubjectFunction(Function): | 97 class SubjectFunction(Function): |
99 """function that depends only on the subject term""" | 98 """function that depends only on the subject term""" |
100 | 99 |
101 def getOperandNodes(self, existingBinding: CandidateBinding) -> List[Node]: | 100 def getOperandNodes(self, existingBinding: CandidateBinding) -> List[Node]: |
102 return [existingBinding.applyTerm(self.stmt[0])] | 101 return [existingBinding.applyTerm(self.chunk.primary[0])] |
103 | 102 |
104 | 103 |
105 class SubjectObjectFunction(Function): | 104 class SubjectObjectFunction(Function): |
106 """a filter function that depends on the subject and object terms""" | 105 """a filter function that depends on the subject and object terms""" |
107 | 106 |
108 def getOperandNodes(self, existingBinding: CandidateBinding) -> List[Node]: | 107 def getOperandNodes(self, existingBinding: CandidateBinding) -> List[Node]: |
109 return [existingBinding.applyTerm(self.stmt[0]), existingBinding.applyTerm(self.stmt[2])] | 108 return [existingBinding.applyTerm(self.chunk.primary[0]), existingBinding.applyTerm(self.chunk.primary[2])] |
110 | 109 |
111 | 110 |
112 class ListFunction(Function): | 111 class ListFunction(Function): |
113 """function that takes an rdf list as input""" | 112 """function that takes an rdf list as input""" |
114 | 113 |
115 def usedStatements(self) -> Set[Triple]: | 114 def usedStatements(self) -> Set[Triple]: |
116 _, used = parseList(self.ruleGraph, self.stmt[0]) | 115 _, used = parseList(self.ruleGraph, self.chunk.primary[0]) |
117 return used | 116 return used |
118 | 117 |
119 def getOperandNodes(self, existingBinding: CandidateBinding) -> List[Node]: | 118 def getOperandNodes(self, existingBinding: CandidateBinding) -> List[Node]: |
120 operands, _ = parseList(self.ruleGraph, self.stmt[0]) | 119 operands, _ = parseList(self.ruleGraph, self.chunk.primary[0]) |
121 return [existingBinding.applyTerm(x) for x in operands] | 120 return [existingBinding.applyTerm(x) for x in operands] |
122 | 121 |
123 | 122 |
124 @register | 123 @register |
125 class Gt(SubjectObjectFunction): | 124 class Gt(SubjectObjectFunction): |
147 | 146 |
148 def bind(self, existingBinding: CandidateBinding) -> Optional[CandidateBinding]: | 147 def bind(self, existingBinding: CandidateBinding) -> Optional[CandidateBinding]: |
149 f = Literal(sum(self.getNumericOperands(existingBinding))) | 148 f = Literal(sum(self.getNumericOperands(existingBinding))) |
150 return self.valueInObjectTerm(f) | 149 return self.valueInObjectTerm(f) |
151 | 150 |
151 | |
152 ### registration is done | 152 ### registration is done |
153 | 153 |
154 _byPred: Dict[URIRef, Type[Function]] = dict((cls.pred, cls) for cls in registeredFunctionTypes) | 154 _byPred: Dict[URIRef, Type[Function]] = dict((cls.pred, cls) for cls in registeredFunctionTypes) |
155 | |
156 | |
155 def functionsFor(pred: URIRef) -> Iterator[Type[Function]]: | 157 def functionsFor(pred: URIRef) -> Iterator[Type[Function]]: |
156 try: | 158 try: |
157 yield _byPred[pred] | 159 yield _byPred[pred] |
158 except KeyError: | 160 except KeyError: |
159 return | 161 return |
160 | 162 |
161 | 163 |
162 def lhsStmtsUsedByFuncs(graph: Graph) -> Set[Triple]: | 164 # def lhsStmtsUsedByFuncs(graph: ChunkedGraph) -> Set[Chunk]: |
163 usedByFuncs: Set[Triple] = set() # don't worry about matching these | 165 # usedByFuncs: Set[Triple] = set() # don't worry about matching these |
164 for s in graph: | 166 # for s in graph: |
165 for cls in functionsFor(pred=s[1]): | 167 # for cls in functionsFor(pred=s[1]): |
166 usedByFuncs.update(cls(s, graph).usedStatements()) | 168 # usedByFuncs.update(cls(s, graph).usedStatements()) |
167 return usedByFuncs | 169 # return usedByFuncs |
168 | 170 |
169 | 171 |
170 def rulePredicates() -> Set[URIRef]: | 172 def rulePredicates() -> Set[URIRef]: |
171 return set(c.pred for c in registeredFunctionTypes) | 173 return set(c.pred for c in registeredFunctionTypes) |