comparison service/mqtt_to_rdf/inference_test.py @ 1631:2c85a4f5dd9c

big rewrite of infer() using statements not variables as the things to iterate over
author drewp@bigasterisk.com
date Sun, 12 Sep 2021 04:32:52 -0700
parents ea559a846714
children 6107603ed455
comparison
equal deleted inserted replaced
1630:b3132cd02686 1631:2c85a4f5dd9c
135 def testRuleVarBindsToInputBNode(self): 135 def testRuleVarBindsToInputBNode(self):
136 inf = makeInferenceWithRules("{ ?z :a :b . } => { :new :stmt :here } .") 136 inf = makeInferenceWithRules("{ ?z :a :b . } => { :new :stmt :here } .")
137 implied = inf.infer(N3("[] :a :b .")) 137 implied = inf.infer(N3("[] :a :b ."))
138 self.assertGraphEqual(implied, N3(":new :stmt :here .")) 138 self.assertGraphEqual(implied, N3(":new :stmt :here ."))
139 139
140 140 class TestBnodeGenerating(WithGraphEqual):
141 class TestSelfFulfillingRule(WithGraphEqual): 141
142 142 def testRuleBnodeMakesNewBnode(self):
143 def test1(self): 143 inf = makeInferenceWithRules("{ [ :a :b ] . } => { [ :c :d ] } .")
144 inf = makeInferenceWithRules("{ } => { :new :stmt :x } .") 144 implied = inf.infer(N3("[ :a :b ] ."))
145 self.assertGraphEqual(inf.infer(N3("")), N3(":new :stmt :x .")) 145 ruleNode = list(inf.rules[0].rhsGraph)[0]
146 self.assertGraphEqual(inf.infer(N3(":any :any :any .")), N3(":new :stmt :x .")) 146 stmt0Node = list(implied)[0][0]
147 147 self.assertNotEqual(ruleNode, stmt0Node)
148 def test2(self): 148
149 inf = makeInferenceWithRules("{ (2) math:sum ?x } => { :new :stmt ?x } .") 149 def testRuleBnodeMakesNewBnodesEachTime(self):
150 self.assertGraphEqual(inf.infer(N3("")), N3(":new :stmt 2 .")) 150 inf = makeInferenceWithRules("{ [ :a ?x ] . } => { [ :c :d ] } .")
151 151 implied = inf.infer(N3("[ :a :b, :e ] ."))
152 @unittest.skip("too hard for now") 152 ruleNode = list(inf.rules[0].rhsGraph)[0]
153 def test3(self): 153 stmt0Node = list(implied)[0][0]
154 inf = makeInferenceWithRules("{ :a :b :c . :a :b ?x . } => { :new :stmt ?x } .") 154 stmt1Node = list(implied)[1][0]
155 self.assertGraphEqual(inf.infer(N3("")), N3(":new :stmt :c .")) 155
156 156 self.assertNotEqual(ruleNode, stmt0Node)
157 157 self.assertNotEqual(ruleNode, stmt1Node)
158 class TestInferenceWithMathFunctions(WithGraphEqual): 158 self.assertNotEqual(stmt0Node, stmt1Node)
159 159
160 def testBoolFilter(self): 160
161 inf = makeInferenceWithRules("{ :a :b ?x . ?x math:greaterThan 5 } => { :new :stmt ?x } .") 161 # class TestSelfFulfillingRule(WithGraphEqual):
162 self.assertGraphEqual(inf.infer(N3(":a :b 3 .")), N3("")) 162
163 self.assertGraphEqual(inf.infer(N3(":a :b 5 .")), N3("")) 163 # def test1(self):
164 self.assertGraphEqual(inf.infer(N3(":a :b 6 .")), N3(":new :stmt 6 .")) 164 # inf = makeInferenceWithRules("{ } => { :new :stmt :x } .")
165 165 # self.assertGraphEqual(inf.infer(N3("")), N3(":new :stmt :x ."))
166 def testNonFiringMathRule(self): 166 # self.assertGraphEqual(inf.infer(N3(":any :any :any .")), N3(":new :stmt :x ."))
167 inf = makeInferenceWithRules("{ :a :b ?x . (?x 1) math:sum ?y } => { :new :stmt ?y } .") 167
168 self.assertGraphEqual(inf.infer(N3("")), N3("")) 168 # def test2(self):
169 169 # inf = makeInferenceWithRules("{ (2) math:sum ?x } => { :new :stmt ?x } .")
170 def testStatementGeneratingRule(self): 170 # self.assertGraphEqual(inf.infer(N3("")), N3(":new :stmt 2 ."))
171 inf = makeInferenceWithRules("{ :a :b ?x . (?x 1) math:sum ?y } => { :new :stmt ?y } .") 171
172 self.assertGraphEqual(inf.infer(N3(":a :b 3 .")), N3(":new :stmt 4 .")) 172 # @unittest.skip("too hard for now")
173 173 # def test3(self):
174 def test3Operands(self): 174 # inf = makeInferenceWithRules("{ :a :b :c . :a :b ?x . } => { :new :stmt ?x } .")
175 inf = makeInferenceWithRules("{ :a :b ?x . (2 ?x 2) math:sum ?y } => { :new :stmt ?y } .") 175 # self.assertGraphEqual(inf.infer(N3("")), N3(":new :stmt :c ."))
176 self.assertGraphEqual(inf.infer(N3(":a :b 2 .")), N3(":new :stmt 6 .")) 176
177 177
178 def test0Operands(self): 178 # class TestInferenceWithMathFunctions(WithGraphEqual):
179 inf = makeInferenceWithRules("{ :a :b ?x . () math:sum ?y } => { :new :stmt ?y } .") 179
180 self.assertGraphEqual(inf.infer(N3(":a :b 2 .")), N3(":new :stmt 0 .")) 180 # def testBoolFilter(self):
181 181 # inf = makeInferenceWithRules("{ :a :b ?x . ?x math:greaterThan 5 } => { :new :stmt ?x } .")
182 182 # self.assertGraphEqual(inf.infer(N3(":a :b 3 .")), N3(""))
183 class TestInferenceWithCustomFunctions(WithGraphEqual): 183 # self.assertGraphEqual(inf.infer(N3(":a :b 5 .")), N3(""))
184 184 # self.assertGraphEqual(inf.infer(N3(":a :b 6 .")), N3(":new :stmt 6 ."))
185 def testAsFarenheit(self): 185
186 inf = makeInferenceWithRules("{ :a :b ?x . ?x room:asFarenheit ?f } => { :new :stmt ?f } .") 186 # def testNonFiringMathRule(self):
187 self.assertGraphEqual(inf.infer(N3(":a :b 12 .")), N3(":new :stmt 53.6 .")) 187 # inf = makeInferenceWithRules("{ :a :b ?x . (?x 1) math:sum ?y } => { :new :stmt ?y } .")
188 # self.assertGraphEqual(inf.infer(N3("")), N3(""))
189
190 # def testStatementGeneratingRule(self):
191 # inf = makeInferenceWithRules("{ :a :b ?x . (?x 1) math:sum ?y } => { :new :stmt ?y } .")
192 # self.assertGraphEqual(inf.infer(N3(":a :b 3 .")), N3(":new :stmt 4 ."))
193
194 # def test3Operands(self):
195 # inf = makeInferenceWithRules("{ :a :b ?x . (2 ?x 2) math:sum ?y } => { :new :stmt ?y } .")
196 # self.assertGraphEqual(inf.infer(N3(":a :b 2 .")), N3(":new :stmt 6 ."))
197
198 # def test0Operands(self):
199 # inf = makeInferenceWithRules("{ :a :b ?x . () math:sum ?y } => { :new :stmt ?y } .")
200 # self.assertGraphEqual(inf.infer(N3(":a :b 2 .")), N3(":new :stmt 0 ."))
201
202
203 # class TestInferenceWithCustomFunctions(WithGraphEqual):
204
205 # def testAsFarenheit(self):
206 # inf = makeInferenceWithRules("{ :a :b ?x . ?x room:asFarenheit ?f } => { :new :stmt ?f } .")
207 # self.assertGraphEqual(inf.infer(N3(":a :b 12 .")), N3(":new :stmt 53.6 ."))
188 208
189 209
190 class TestUseCases(WithGraphEqual): 210 class TestUseCases(WithGraphEqual):
191 211
192 def testSimpleTopic(self): 212 def testSimpleTopic(self):
219 ''') 239 ''')
220 240
221 out = inf.infer(N3('[] a :MqttMessage ; :body "online" ; :topic ( "frontdoorlock" "status" ) .')) 241 out = inf.infer(N3('[] a :MqttMessage ; :body "online" ; :topic ( "frontdoorlock" "status" ) .'))
222 self.assertIn((EX['frontDoorLockStatus'], EX['connectedStatus'], EX['Online']), out) 242 self.assertIn((EX['frontDoorLockStatus'], EX['connectedStatus'], EX['Online']), out)
223 243
224 def testPerformance0(self): 244 # def testPerformance0(self):
225 inf = makeInferenceWithRules(''' 245 # inf = makeInferenceWithRules('''
226 { 246 # {
227 ?msg a :MqttMessage; 247 # ?msg a :MqttMessage;
228 :topic :topic1; 248 # :topic :topic1;
229 :bodyFloat ?valueC . 249 # :bodyFloat ?valueC .
230 ?valueC math:greaterThan -999 . 250 # ?valueC math:greaterThan -999 .
231 ?valueC room:asFarenheit ?valueF . 251 # ?valueC room:asFarenheit ?valueF .
232 } => { 252 # } => {
233 :airQualityIndoorTemperature :temperatureF ?valueF . 253 # :airQualityIndoorTemperature :temperatureF ?valueF .
234 } . 254 # } .
235 ''') 255 # ''')
236 out = inf.infer( 256 # out = inf.infer(
237 N3(''' 257 # N3('''
238 <urn:uuid:c6e1d92c-0ee1-11ec-bdbd-2a42c4691e9a> a :MqttMessage ; 258 # <urn:uuid:c6e1d92c-0ee1-11ec-bdbd-2a42c4691e9a> a :MqttMessage ;
239 :body "23.9" ; 259 # :body "23.9" ;
240 :bodyFloat 2.39e+01 ; 260 # :bodyFloat 2.39e+01 ;
241 :topic :topic1 . 261 # :topic :topic1 .
242 ''')) 262 # '''))
243 263
244 vlit = cast(Literal, out.value(EX['airQualityIndoorTemperature'], EX['temperatureF'])) 264 # vlit = cast(Literal, out.value(EX['airQualityIndoorTemperature'], EX['temperatureF']))
245 valueF = cast(Decimal, vlit.toPython()) 265 # valueF = cast(Decimal, vlit.toPython())
246 self.assertAlmostEqual(float(valueF), 75.02) 266 # self.assertAlmostEqual(float(valueF), 75.02)
247 267
248 def testPerformance1(self): 268 # def testPerformance1(self):
249 inf = makeInferenceWithRules(''' 269 # inf = makeInferenceWithRules('''
250 { 270 # {
251 ?msg a :MqttMessage; 271 # ?msg a :MqttMessage;
252 :topic ( "air_quality_indoor" "sensor" "bme280_temperature" "state" ); 272 # :topic ( "air_quality_indoor" "sensor" "bme280_temperature" "state" );
253 :bodyFloat ?valueC . 273 # :bodyFloat ?valueC .
254 ?valueC math:greaterThan -999 . 274 # ?valueC math:greaterThan -999 .
255 ?valueC room:asFarenheit ?valueF . 275 # ?valueC room:asFarenheit ?valueF .
256 } => { 276 # } => {
257 :airQualityIndoorTemperature :temperatureF ?valueF . 277 # :airQualityIndoorTemperature :temperatureF ?valueF .
258 } . 278 # } .
259 ''') 279 # ''')
260 out = inf.infer( 280 # out = inf.infer(
261 N3(''' 281 # N3('''
262 <urn:uuid:c6e1d92c-0ee1-11ec-bdbd-2a42c4691e9a> a :MqttMessage ; 282 # <urn:uuid:c6e1d92c-0ee1-11ec-bdbd-2a42c4691e9a> a :MqttMessage ;
263 :body "23.9" ; 283 # :body "23.9" ;
264 :bodyFloat 2.39e+01 ; 284 # :bodyFloat 2.39e+01 ;
265 :topic ( "air_quality_indoor" "sensor" "bme280_temperature" "state" ) . 285 # :topic ( "air_quality_indoor" "sensor" "bme280_temperature" "state" ) .
266 ''')) 286 # '''))
267 vlit = cast(Literal, out.value(EX['airQualityIndoorTemperature'], EX['temperatureF'])) 287 # vlit = cast(Literal, out.value(EX['airQualityIndoorTemperature'], EX['temperatureF']))
268 valueF = cast(Decimal, vlit.toPython()) 288 # valueF = cast(Decimal, vlit.toPython())
269 self.assertAlmostEqual(float(valueF), 75.02) 289 # self.assertAlmostEqual(float(valueF), 75.02)
270 290
271 def testEmitBnodes(self): 291 def testEmitBnodes(self):
272 inf = makeInferenceWithRules(''' 292 inf = makeInferenceWithRules('''
273 { ?s a :AirQualitySensor; :label ?name . } => { 293 { ?s a :AirQualitySensor; :label ?name . } => {
274 [ a :MqttStatementSource; 294 [ a :MqttStatementSource;
276 } . 296 } .
277 ''') 297 ''')
278 out = inf.infer(N3(''' 298 out = inf.infer(N3('''
279 :airQualityOutdoor a :AirQualitySensor; :label "air_quality_outdoor" . 299 :airQualityOutdoor a :AirQualitySensor; :label "air_quality_outdoor" .
280 ''')) 300 '''))
281 301 self.assertEqual(out.serialize(format='n3'), b'''@prefix ns1: <http://example.com/> .
282 self.assertEqual(len(out), 1) 302 @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
303 @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
304 @prefix xml: <http://www.w3.org/XML/1998/namespace> .
305 @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
306
307 [] a ns1:MqttStatementSource ;
308 ns1:mqttTopic ( "air_quality_outdoor" "sensor" "bme280_temperature" "state" ) .
309
310 ''')
283 311
284 312
285 class TestListPerformance(WithGraphEqual): 313 class TestListPerformance(WithGraphEqual):
286 314
287 def testList1(self): 315 def testList1(self):
303 inf = makeInferenceWithRules("{ :a :b (:e0 :e1 :e2 :e3) . } => { :new :stmt :here } .") 331 inf = makeInferenceWithRules("{ :a :b (:e0 :e1 :e2 :e3) . } => { :new :stmt :here } .")
304 implied = inf.infer(N3(":a :b (:e0 :e1 :e2 :e3) .")) 332 implied = inf.infer(N3(":a :b (:e0 :e1 :e2 :e3) ."))
305 self.assertGraphEqual(implied, N3(":new :stmt :here .")) 333 self.assertGraphEqual(implied, N3(":new :stmt :here ."))
306 334
307 335
308 def fakeStats(): 336 # def fakeStats():
309 return defaultdict(lambda: 0) 337 # return defaultdict(lambda: 0)
310 338
311 339
312 class TestLhsFindCandidateBindings(WithGraphEqual): 340 # class TestLhsFindCandidateBindings(WithGraphEqual):
313 341
314 def testBnodeMatchesStmt(self): 342 # def testBnodeMatchesStmt(self):
315 l = Lhs(N3("[] :a :b .")) 343 # l = Lhs(N3("[] :a :b ."))
316 ws = ReadOnlyGraphAggregate([N3("[] :a :b .")]) 344 # ws = ReadOnlyGraphAggregate([N3("[] :a :b .")])
317 cands = list(l.findCandidateBindings(ws, fakeStats())) 345 # cands = list(l.findCandidateBindings(ws, fakeStats()))
318 self.assertEqual(len(cands), 1) 346 # self.assertEqual(len(cands), 1)
319 347
320 def testVarMatchesStmt(self): 348 # def testVarMatchesStmt(self):
321 l = Lhs(N3("?x :a :b .")) 349 # l = Lhs(N3("?x :a :b ."))
322 ws = ReadOnlyGraphAggregate([N3("[] :a :b .")]) 350 # ws = ReadOnlyGraphAggregate([N3("[] :a :b .")])
323 cands = list(l.findCandidateBindings(ws, fakeStats())) 351 # cands = list(l.findCandidateBindings(ws, fakeStats()))
324 self.assertEqual(len(cands), 1) 352 # self.assertEqual(len(cands), 1)
325 353
326 def testListsOnlyMatchEachOther(self): 354 # def testListsOnlyMatchEachOther(self):
327 l = Lhs(N3(":a :b (:e0 :e1) .")) 355 # l = Lhs(N3(":a :b (:e0 :e1) ."))
328 ws = ReadOnlyGraphAggregate([N3(":a :b (:e0 :e1) .")]) 356 # ws = ReadOnlyGraphAggregate([N3(":a :b (:e0 :e1) .")])
329 stats = fakeStats() 357 # stats = fakeStats()
330 cands = list(l.findCandidateBindings(ws, stats)) 358 # cands = list(l.findCandidateBindings(ws, stats))
331 self.assertLess(stats['permCountFailingVerify'], 20) 359 # self.assertLess(stats['permCountFailingVerify'], 20)