-
Notifications
You must be signed in to change notification settings - Fork 152
Open
Description
Background, I am new to Pyknow. I want to build a expert system to auto calculate a cell quality score based on some parameters. The score algorithm should be loaded from a json data, such like:
{
"PN": [{
"condition": "pn",
"symbol": "=",
"value": "2PN",
"score": "20",
"weight": "1.0"
}, {
"condition": "time",
"symbol": "<=",
"value": "12",
"score": "20",
"weight": "1.0"
}],
"4C": [{
"condition": "cell",
"symbol": "=",
"value": "4C",
"score": "20",
"weight": "1.0"
}, {
"condition": "even",
"symbol": "=",
"value": true,
"score": "20",
"weight": "1.0"
}, {
"condition": "fragment",
"symbol": "=",
"value": "<5%",
"score": "20",
"weight": "1.0"
}, {
"condition": "fragment",
"symbol": "=",
"value": "5%-10%",
"score": "15",
"weight": "1.0"
}, {
"condition": "fragment",
"symbol": "=",
"value": "10%-20%",
"score": "10",
"weight": "1.0"
}, {
"condition": "time",
"symbol": "<=",
"value": "36",
"score": "20",
"weight": "1.0"
}]
}Here are my codes for this,
from pyknow import *
from functools import partial
class EmbryoScore(KnowledgeEngine):
score = 0
@classmethod
def removeAllRules(cls):
for m in [attr for attr in cls.__dict__ if attr.startswith('rule')]:
delattr(cls, m)
def parse_json_rules(rule_json):
import json
rules = json.loads(rule_json)
sal = 100
index = 0
for stage in rules:
for rule_item in rules[stage]:
rule = {'condition': rule_item['condition']}
rule['stage'] = stage
if rule_item['symbol'] not in ('=', '<', '<=', '>', '>='):
continue
def _cond(value, symbol):
if symbol == '=': return EQ(value)
if symbol == '<': return LT(value)
if symbol == '<=': return LE(value)
if symbol == '>': return GT(value)
if symbol == '>=': return GE(value)
def _add(self, **kwargs):
if 'score' not in kwargs or 'weight' not in kwargs:
raise ValueError('No score or weight specified')
s, w = int(kwargs['score']), float(kwargs['weight'])
self.score += s * w
R = Rule(AND(Fact(**rule, value=MATCH.value &
_cond(rule_item['value'], rule_item['symbol']))),
salience=sal)(partial(_add, score=rule_item['score'],
weight=rule_item['weight']))
setattr(EmbryoScore, f'rule{index}', R)
index += 1
sal -= 1
def init_engine(rule_json):
EmbryoScore.removeAllRules()
parse_json_rules(rule_json)
engine = EmbryoScore()
engine.reset()
return engine
import unittest
class ScoreTest(unittest.TestCase):
def test(self):
engine = init_engine(rule_json)
engine.declare(Fact(condition='pn', stage='PN', value='2PN'))
engine.declare(Fact(stage='4C', condition='cell', value='4C'))
engine.declare(Fact(stage='4C', condition='fragment', value='10%-20%'))
engine.declare(Fact(stage='4C', condition='time', value='32'))
engine.run()
self.assertEqual(engine.score, 70)
if __name__ == '__main__':
unittest.main()It raises a AttributeError: 'Rule' object has no attribute 'name' when engine.run() on engine.py line 162
watchers.RULES.info(
"FIRE %s %s: %s",
execution,
activation.rule.__name__,
", ".join(str(f) for f in activation.facts))I can't find out what the problem is. Wonder if I can get some help here. THANKS.
Metadata
Metadata
Assignees
Labels
No labels