Knowledge representation & expert systems
Not every AI system learns from data. Many important systems encode what human experts already know as facts and rules, then reason over them. Tax software, insurance underwriting, medical triage checklists and eligibility engines for government schemes all work this way — and they are attractive precisely because every decision can be explained line by line.
Ways to represent knowledge
| Form | Idea | Example |
|---|---|---|
| Propositional / predicate logic | Statements that are true or false, with variables and quantifiers | supplies_goods(shop) AND turnover > 40L |
| Production rules | IF conditions THEN conclusion | IF fever AND rash THEN suspect viral infection |
| Semantic network | Nodes joined by labelled relations | Mango --is-a--> Fruit --grown-in--> Ratnagiri |
| Frames / objects | Slots with default values for a concept | Loan: tenure = 60 months by default |
| Ontology / knowledge graph | Shared vocabulary of entities and relations, queryable | Product catalogue linked to brands and categories |
Anatomy of an expert system
Three parts, kept deliberately separate:
- Knowledge base — the rules, written and reviewed by domain experts.
- Working memory — the facts known about the current case.
- Inference engine — the code that decides which rules fire and in what order.
Because the rules live outside the code, a GST consultant can update a threshold without a developer touching the inference engine.
Forward chaining in 15 lines
Forward chaining starts from known facts and keeps firing rules until nothing new can be derived (data-driven). Backward chaining starts from a goal and works backwards to see which facts would prove it (goal-driven).
RULES = [
({"supplies_goods", "turnover_above_40l"}, "must_register_for_gst"),
({"supplies_services", "turnover_above_20l"}, "must_register_for_gst"),
({"must_register_for_gst"}, "files_monthly_returns"),
({"files_monthly_returns", "no_accountant"}, "needs_filing_support"),
]
def forward_chain(facts, rules):
facts = set(facts)
changed = True
while changed:
changed = False
for conditions, conclusion in rules:
if conditions <= facts and conclusion not in facts:
facts.add(conclusion)
changed = True
return facts
case = {"supplies_goods", "turnover_above_40l", "no_accountant"}
print(sorted(forward_chain(case, RULES)))
Add a trace (record which rule added which fact) and you get a free explanation: "You need filing support because you must register for GST, which means monthly returns, and you have no accountant."
Rules or machine learning?
Prefer rules when the logic is written down somewhere (law, policy, SOP), decisions must be auditable, and there is little labelled data. Prefer learning when the pattern is fuzzy, examples are plentiful, and nobody can state the rule precisely — recognising a damaged parcel from a photo, for instance. Many production systems combine both: a model scores the case, and hard rules veto anything the policy forbids.
Common mistakes
- Letting the rule base grow to thousands of overlapping rules with no tests; contradictions creep in silently.
- Hard-coding thresholds in Python instead of keeping them as editable data.
- No conflict-resolution strategy when two rules fire and disagree.
- Assuming a rule engine is "not real AI" — auditability is often worth more than accuracy.
Practice
Write 8 rules for a scholarship-eligibility system (income band, marks, category, state of domicile). Extend
forward_chain so it also returns the list of rules that fired, and print a plain-English explanation for one
approved and one rejected applicant.