Skip to content

Instantly share code, notes, and snippets.

@webpigeon
Created August 8, 2012 22:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save webpigeon/3299260 to your computer and use it in GitHub Desktop.
Save webpigeon/3299260 to your computer and use it in GitHub Desktop.
Foward Chaining expert system
#! /usr/bin/env python2
##
# Implementation of MyCIN-like expert system
# Copyright (c) 2012, Joseph Walton-Rivers <joseph@webpigeon.me.uk>
##
from collections import defaultdict
CV_TRUE = +1.0
CV_UNKNOWN = 0
CV_FALSE = -1.0
class Solver(object):
def __init__(self):
self.facts = defaultdict(lambda: defaultdict(float))
self.rules = set()
def run(self):
while self.rules:
currRule = None
# look at rules
for rule in self.rules:
if self.canFire(rule):
currRule = rule
break
# No rule can be executed
if not currRule:
break
# Update the fact for this rule
self.rules.remove(currRule)
self.addFact(currRule[1][0], currRule[1][1], currRule[1][2])
def canFire(self, rule):
for (fact,value) in rule[0]:
if fact not in self.facts:
return False
if value not in self.facts[fact]:
return False
return True
def addFact(self, fact, value, cRule):
cCurr = self.facts[fact][value]
cNew = cCurr + cRule * (1 - cCurr)
self.facts[fact][value] = cNew
def prettyPrint(goal, facts):
items = facts[goal].items()
items = filter(lambda x: x[1] > 0.2, items)
items = sorted(items, key=lambda x: -x[1])
if not items:
print("Sorry, I couldn't figure it out")
return
for (p, value) in items:
print value, p
def main():
solver = Solver()
solver.addFact("ears", "pointy", 1)
solver.addFact("tail", "waggy", 1)
solver.addFact("noise", "meow", 1)
solver.addFact("size", "small", 1)
solver.rules.add( ((("ears", "pointy"),), ("animal", "cat", 0.7)) )
solver.rules.add( ((("tail", "waggy"),), ("animal", "dog", 0.5)) )
solver.rules.add( ((("noise", "meow"),), ("animal", "cat", 0.9)) )
solver.rules.add( ((("noise", "woof"),), ("animal", "dog", 1)) )
solver.rules.add( ((("size", "small"),), ("animal", "cat", 0.9)) )
solver.rules.add( ((("size", "small"),), ("animal", "dog", 0.3)) )
solver.run()
prettyPrint("animal", solver.facts)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment