How to limit/halt inferencing?

83 views
Skip to first unread message

Martin Lambert

unread,
Jun 10, 2016, 10:47:11 AM6/10/16
to pyDatalog
Hi there:

I'm trying to use pyDatalog to simulate a simple fault diagnostic expert system for a BBQ (see code sample below). My idea so far is to use a network to simulate the facts that a problem with either the 'cylinder' or its 'valve' causes a problem with the 'gas', which in turn causes a problem with the 'bbq'. I have rules that traverse the network, to figure out that a 'cylinder' problem causes a 'bbq' problem. I've also added rules to ask the user about the 'cylinder' and 'valve'. So two questions: (a) am I approaching this problem the right way? (b) how can I stop the firing of new rules when I find my first fault? In this example if I tell it the valve is closed it still asks me about the cylinder. I'd like it to stop and report the answer as soon as it has one.

from pyDatalog import pyDatalog, pyEngine
from pyDatalog.pyDatalog import assert_fact, load, ask

import logging
pyEngine
.Logging = True
logging
.basicConfig(level=logging.INFO)

pyDatalog
.create_terms('causes_fault, faulty, find_fault, raw_input, check_empty, check_open, X, Y, Z')

# Fault hierarchy, e.g. fault in 'gas' causes fault in 'bbq'
+causes_fault('gas', 'bbq')
+causes_fault('valve', 'gas')
+causes_fault('cylinder', 'gas')
#+faulty('valve')

# Rules that say faults flow up the 'causes_fault' network
find_fault
(X,Z) <= causes_fault(X,Z) & faulty(X)
find_fault
(X,Z) <= causes_fault(Y,Z) & find_fault(X,Y)

# Rules to prompt user for leaf faults
check_empty
(X) <= (raw_input('Is '+X+' empty ? (Y/N) ')=='Y')
check_open
(X) <= (raw_input('Is '+X+' open ? (Y/N) ')=='Y')
faulty
(X) <= (X == 'cylinder') & check_empty(X)
faulty
(X) <= (X == 'valve') & ~check_open(X)

# Run the query
print(find_fault(X, 'bbq'))

Thanks!

Martin

Martin Lambert

unread,
Jun 14, 2016, 1:42:23 PM6/14/16
to pyDatalog
Hi Pierre:

I've blundered about a bit and sort of got what I wanted working, i.e. stopping inference (and further questions) once I have a solution, but I don't get a good feel whether I am using pyDatalog at all correctly - see below. I especially don't understand the difference between logic functions and logic literals (sets). Is my approach below reasonable? Is there an obviously better way to do this?

from pyDatalog import pyDatalog, pyEngine
from pyDatalog.pyDatalog import assert_fact, load, ask


import logging
pyEngine
.Logging = True
logging
.basicConfig(level=logging.INFO)



pyDatalog
.create_terms('container_of, is_faulty, cause_of, input, check_empty, check_open, X, Y, Z')



# Fault hierarchy, e.g. fault in 'gas' causes fault in 'bbq'
+(container_of['gas']=='bbq')
+(container_of['valve']=='gas')
+(container_of['cylinder']=='gas')
#+(is_faulty['valve']==True)


# Rules that say faults flow up the 'container_of' network
(cause_of[Z]==X) <= (container_of[X]==Z) & (is_faulty[X]==True)
(cause_of[Z]==X) <= (container_of[Y]==Z) & (cause_of[Y]==X)



# Rules to prompt user for leaf faults

check_empty
(X) <= (input('Is '+X+' empty ? (Y/N) ')=='Y')
check_open
(X) <= (input('Is '+X+' open ? (Y/N) ')=='Y')


# Leaf rules
(cause_of['gas']==X) <= ((X == 'cylinder') & check_empty(X))
(cause_of['gas']==X) <= ((X == 'valve') & ~check_open(X))


# Run the query
print(cause_of['bbq']==X)


Regards,

Martin

Pierre Carbonnelle

unread,
Jun 14, 2016, 2:42:07 PM6/14/16
to pyDatalog
Looks good to me.

Some hints :

use : container_of['gas']='bbq'
instead of : +(container_of['gas']=='bbq')

use : is_faulty(X)
instead of : (is_faulty[X]==True)

PC

Reply all
Reply to author
Forward
0 new messages