I am trying to extract the rules from the rules engine that I build using experta library.
Below is the code
from experta import *
import pydot
class Iris(Fact):
"""IRIS"""
sepal_length = Field(float)
sepal_width = Field(float)
petal_length = Field(float)
petal_width = Field(float)
class Species(Fact):
"""Species characteristics"""
pass
class IrisExpert(KnowledgeEngine):
def __init__(self):
super().__init__()
self.status = None
@Rule(Iris(sepal_length=P(lambda x: x > 5), sepal_width=P(lambda x: x < 3)))
def rule1(self):
self.status = 'Iris Setosa'
return self.declare(Species(flower='Iris Setosa'))
@Rule(AND(
Iris(sepal_length=P(lambda x: x > 5.5)),
Iris(sepal_width=P(lambda x: x > 2.5))
))
def rule2(self):
self.status = 'Iris Versicolor'
return self.declare(Species(flower='Iris Versicolor'))
@Rule(AND(
Iris(petal_length=P(lambda x: x > 4.8)),
Iris(petal_width=P(lambda x: x > 1.8))
))
def rule3(self):
self.status = 'Iris Virginica'
return self.declare(Species(flower='Iris Virginica'))
def execute_fuc(key):
if key == 'rule1':
print('executing rule-1')
engine.rule1()
elif key == 'rule2':
print('executing rule-2')
engine.rule2()
else:
print('executing rule-3')
engine.rule3()
# Create a new knowledge engine instance
engine = IrisExpert()
engine.reset()
# Create a Pydot graph
graph = pydot.Dot(graph_type='digraph', comment='IRIS Expert Rules')
# Add nodes for each rule
for rule_instance in engine.get_rules():
quality = rule_instance()
qual_node = pydot.Node(repr(quality))
graph.add_node(qual_node)
for rule in rule_instance:
print('rule_format: ',repr(rule))
I am getting in the below format
rule_format: Iris(petal_width=P(<function IrisExpert.<lambda> at 0x7fe3fd4788c8>,))
But I am looking for something like
Iris(petal_width=P(<function IrisExpert. x > 5)) (for function "rule1")
You are apparently trying to rewrite the repr
method of your lambda functions. This answer shows how to do it. Applied to your case (both < and > representations), you could do the following:
from experta import *
import pydot
import functools
class reprwrapper(object):
def __init__(self, repr, func):
self._repr = repr
self._func = func
functools.update_wrapper(self, func)
def __call__(self, *args, **kw):
return self._func(*args, **kw)
def __repr__(self):
return self._repr(self._func)
def withrepr(reprfun):
def _wrap(func):
return reprwrapper(reprfun, func)
return _wrap
def x_gt(a):
@withrepr(lambda x: f"function IrisExpert. x > {a}")
def gt_a(x):
return x > a
return gt_a
def x_lt(a):
@withrepr(lambda x: f"function IrisExpert. x < {a}")
def lt_a(x):
return x < a
return lt_a
class Iris(Fact):
"""IRIS"""
sepal_length = Field(float)
sepal_width = Field(float)
petal_length = Field(float)
petal_width = Field(float)
class Species(Fact):
"""Species characteristics"""
pass
class IrisExpert(KnowledgeEngine):
def __init__(self):
super().__init__()
self.status = None
@Rule(Iris(sepal_length=P(x_gt(5)), sepal_width=P(x_lt(3))))
def rule1(self):
self.status = 'Iris Setosa'
return self.declare(Species(flower='Iris Setosa'))
@Rule(AND(
Iris(sepal_length=P(x_gt(5.5))),
Iris(sepal_width=P(x_gt(2.5)))
))
def rule2(self):
self.status = 'Iris Versicolor'
return self.declare(Species(flower='Iris Versicolor'))
@Rule(AND(
Iris(petal_length=P(x_gt(4.8))),
Iris(petal_width=P(x_gt(1.8)))
))
def rule3(self):
self.status = 'Iris Virginica'
return self.declare(Species(flower='Iris Virginica'))
def execute_fuc(key):
if key == 'rule1':
print('executing rule-1')
engine.rule1()
elif key == 'rule2':
print('executing rule-2')
engine.rule2()
else:
print('executing rule-3')
engine.rule3()
# Create a new knowledge engine instance
engine = IrisExpert()
engine.reset()
# Create a Pydot graph
graph = pydot.Dot(graph_type='digraph', comment='IRIS Expert Rules')
# Add nodes for each rule
for rule_instance in engine.get_rules():
quality = rule_instance()
qual_node = pydot.Node(repr(quality))
graph.add_node(qual_node)
for rule in rule_instance:
print('rule_format: ',repr(rule))
Output:
rule_format: Iris(sepal_length=P(function IrisExpert. x > 5,), sepal_width=P(function IrisExpert. x < 3,))
rule_format: AND(Iris(sepal_length=P(function IrisExpert. x > 5.5,)), Iris(sepal_width=P(function IrisExpert. x > 2.5,)))
rule_format: AND(Iris(petal_length=P(function IrisExpert. x > 4.8,)), Iris(petal_width=P(function IrisExpert. x > 1.8,)))