{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "a4c93ebd",
   "metadata": {},
   "source": [
    "# CLIPS Constructs"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3b71cc91",
   "metadata": {},
   "source": [
    "Refer details from lecture notes 6."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ea6fbbe2",
   "metadata": {},
   "source": [
    "# Section A: Agenda"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ab717915",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"(deftemplate person\n",
    "           (multislot name)\n",
    "           (multislot children))\"\"\")\n",
    "\n",
    "env.build(\"\"\"(deffacts some-people\n",
    "           (person (name John Q. Public)\n",
    "                   (children Jane Paul Mary))\n",
    "           (person (name Jack R. Public)\n",
    "                   (children Risk)))\"\"\")\n",
    "\n",
    "env.build(\"\"\"(defrule print-children\n",
    "           (person (name $?name)\n",
    "                   (children $?children))\n",
    "        =>(printout t $?name \" has children \" $?children\n",
    "                     crlf))\"\"\")\n",
    "\n",
    "env.reset()\n",
    "\n",
    "# Method 1: Display agenda\n",
    "# LIFO order for deffacts\n",
    "# active = env.activations()\n",
    "# i = 1\n",
    "# for act in active:\n",
    "#     print(f\"Fire {i} : Rule {act.name}-{act.salience}\")\n",
    "#     i+=1\n",
    "    \n",
    "# Method 2: Use the command in CLIPS\n",
    "env.eval(\"(agenda)\")\n",
    "env.run()\n",
    "\n",
    "# After perform run, the agenda will be cleared automatically\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "95ae9ba7",
   "metadata": {},
   "source": [
    "# Section B: Pattern Matching"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a048c29d",
   "metadata": {},
   "source": [
    "1. **Fire rule unconditionally**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "eb73639f",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"(deffacts startup (animal dog) (animal cat) (animal duck) (animal turtle) \n",
    "                  (warm-blooded dog) (warm-blooded cat) (warm-blooded duck) \n",
    "                  (lays-eggs duck) (lays-eggs turtle) (child-of dog puppy) \n",
    "                  (child-of cat kitten) (child-of turtle hatchling))\"\"\")\n",
    "\n",
    "env.build(\"\"\"(defrule animal\n",
    "  =>\n",
    "  (printout t \"animal found\" crlf))\"\"\")\n",
    "\n",
    "env.reset()\n",
    "env.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a3cb4165",
   "metadata": {},
   "source": [
    "2. **Pattern-matching wildcards**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "200fa087",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"(deffacts startup (animal dog) (animal cat) (animal duck) (animal turtle) \n",
    "                  (warm-blooded dog) (warm-blooded cat) (warm-blooded duck) \n",
    "                  (lays-eggs duck) (lays-eggs turtle) (child-of dog puppy) \n",
    "                  (child-of cat kitten) (child-of turtle hatchling))\"\"\")\n",
    "\n",
    "# single-field wildcard (?). E.g. (animal cat)\n",
    "# multifield wildcard ($?). E.g. (animal cat dog)\n",
    "env.build(\"\"\"(defrule animal\n",
    "  (animal ?)\n",
    "  =>\n",
    "  (printout t \"animal found\" crlf))\"\"\")\n",
    "\n",
    "env.reset()\n",
    "env.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dfba0391",
   "metadata": {},
   "source": [
    "3. Display **pattern-matching variable**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7a60cb35",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"(deffacts startup (animal dog) (animal cat) (animal duck) (animal turtle) \n",
    "                  (warm-blooded dog) (warm-blooded cat) (warm-blooded duck) \n",
    "                  (lays-eggs duck) (lays-eggs turtle) (child-of dog puppy) \n",
    "                  (child-of cat kitten) (child-of turtle hatchling))\"\"\")\n",
    "\n",
    "env.build(\"\"\"(defrule list-animals\n",
    "(animal ?name)\n",
    "=>\n",
    "(printout t ?name \" found\" crlf))\"\"\")\n",
    "\n",
    "env.reset()\n",
    "env.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0b19c602",
   "metadata": {},
   "source": [
    "4. **Fact assertion** for **pattern-matching variable**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f4e1e023",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"(deffacts startup (animal dog) (animal cat) (animal duck) (animal turtle) \n",
    "                  (warm-blooded dog) (warm-blooded cat) (warm-blooded duck) \n",
    "                  (lays-eggs duck) (lays-eggs turtle) (child-of dog puppy) \n",
    "                  (child-of cat kitten) (child-of turtle hatchling))\"\"\")\n",
    "\n",
    "env.build(\"\"\"(defrule mammal\n",
    "  (animal ?name)\n",
    "  (warm-blooded ?name)\n",
    "  (not (lays-eggs ?name))\n",
    "  =>\n",
    "  (assert (mammal ?name))\n",
    "  (printout t ?name \" is a mammal\" crlf))\"\"\")\n",
    "\n",
    "env.reset()\n",
    "env.run()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "36ce1809",
   "metadata": {},
   "source": [
    "5. **Retract fact** in rules"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3334a1fa",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"(deffacts startup (animal dog) (animal cat) (animal duck) (animal turtle) \n",
    "                  (warm-blooded dog) (warm-blooded cat) (warm-blooded duck) \n",
    "                  (lays-eggs duck) (lays-eggs turtle) (child-of dog puppy) \n",
    "                  (child-of cat kitten) (child-of turtle hatchling))\"\"\")\n",
    "\n",
    "env.build(\"\"\"(defrule remove-warm-blooded\n",
    "  ?fact <- (warm-blooded ?)\n",
    "  =>\n",
    "  (printout t \"retracting \" ?fact crlf)\n",
    "  (retract ?fact))\"\"\")\n",
    "\n",
    "env.reset()\n",
    "env.run()\n",
    "\n",
    "for fact in env.facts():\n",
    "    print(fact)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f664b9da-006b-4cf0-8205-841ed5b4e1f5",
   "metadata": {},
   "source": [
    "6. **retract** the user’s input word and replace it with its normalized form. Advanced method, use NLP."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0aa5b509-45d5-4114-b29e-025521deff5a",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"(deffacts dictionary\n",
    "   (base-form ran run)\n",
    "   (base-form running run)\n",
    "   (base-form run run))\"\"\")\n",
    "\n",
    "\n",
    "env.build(\"\"\"(defrule normalize\n",
    "   ?q <- (query ?w)\n",
    "   (base-form ?w ?base)\n",
    "   (test (neq ?w ?base))    ;; Only normalize if different\n",
    "   =>\n",
    "     (retract ?q)\n",
    "     (assert (query ?base))\n",
    "     (printout t \"Normalized: \" ?w \" → \" ?base crlf))\"\"\")\n",
    "\n",
    "env.reset()\n",
    "\n",
    "env.eval(\"(assert (query ran))\")\n",
    "env.eval(\"(facts)\")\n",
    "\n",
    "env.run()\n",
    "\n",
    "# Replacing the facts (query ran) to (query run)\n",
    "env.eval(\"(facts)\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0d37fbe1",
   "metadata": {},
   "source": [
    "# Section C: Field Constraints and Connective Constraints"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "04365fd0",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"(deftemplate person\n",
    "               (slot name)\n",
    "               (slot eyes)\n",
    "               (slot hair))\"\"\")\n",
    "\n",
    "#Find a person with blue eyes.\n",
    "env.build(\"\"\"(defrule find-blue-eyes\n",
    "               (person (name ?name)\n",
    "                       (eyes blue))\n",
    "             =>(printout t ?name \" has blue eyes.\" crlf))\"\"\")\n",
    "\n",
    "# Find a person without brown hair.\n",
    "env.build(\"\"\"(defrule find-without-brown-hair\n",
    "               (person (name ?name)\n",
    "                       (hair ~brown))\n",
    "             =>(printout t ?name \" does not have brown hair\" crlf))\"\"\")\n",
    "\n",
    "#Find a person with either black or brown hair.\n",
    "env.build(\"\"\"(defrule find-black-or-brown-hair\n",
    "               (person (name ?name)\n",
    "                       (hair black|brown))\n",
    "             =>(printout t ?name \" has dark hair\" crlf))\"\"\")\n",
    "\n",
    "#Find a person with either black or brown hair. Specify the color of the hair.\n",
    "env.build(\"\"\"(defrule find-black-or-brown-hair\n",
    "               (person (name ?name)\n",
    "                       (hair ?color& black | brown))\n",
    "             =>(printout t ?name \" has \" ?color \" hair\" crlf))\"\"\")\n",
    "\n",
    "#Find a person with neither black nor brown hair. Specify the color of the hair.\n",
    "env.build(\"\"\"(defrule find-black-nor-brown-hair\n",
    "               (person (name ?name)\n",
    "                       (hair ?color& black & ~brown))\n",
    "             =>(printout t ?name \" has \" ?color \" hair\" crlf))\"\"\")\n",
    "\n",
    "env.reset()\n",
    "\n",
    "env.assert_string('(person (name Tawfeeq)(eyes blue))')\n",
    "env.assert_string('(person (name Kaviraj)(hair black))')\n",
    "env.assert_string('(person (name \"Siti Nabila\")(hair brown))')\n",
    "                  \n",
    "env.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4a27fc54",
   "metadata": {},
   "source": [
    "# Section D: Predicate Field Constraints"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0838c38e",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"(deftemplate rectangle\n",
    "               (slot height)\n",
    "               (slot width))\"\"\")\n",
    "\n",
    "#Predicate Field Constraints, (height ?height&:(< ?height 12))\n",
    "env.build(\"\"\"(defrule sum-rectangles\n",
    "                (rectangle (height ?height&:(> ?height 0)&:(< ?height 12)) (width ?width&:(> ?width 5)))\n",
    "              =>\n",
    "             (printout t \"Rectangle meets the size criteria\" crlf))\"\"\")\n",
    "\n",
    "env.reset()\n",
    "\n",
    "env.assert_string(\"(rectangle (height 5) (width 10))\")\n",
    "\n",
    "env.run()\n",
    "\n",
    "#for fact in env.facts():\n",
    "#    print(fact)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2467b0bf",
   "metadata": {},
   "source": [
    "# Section E: Return Value Constraints"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "510503dd",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"(deftemplate rectangle\n",
    "               (slot height)\n",
    "               (slot width))\"\"\")\n",
    "\n",
    "#Return Value Constraints =, ~=\n",
    "env.build(\"\"\"(defrule check-size\n",
    "               (rectangle (height ?height) (width = (* 2 ?height)))\n",
    "              =>(printout t \"Verified width is double of height\" crlf))\"\"\")\n",
    "\n",
    "env.reset()\n",
    "\n",
    "env.assert_string(\"(rectangle (height 5) (width 10))\")\n",
    "\n",
    "env.run()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5284f2b1",
   "metadata": {},
   "source": [
    "# Section F: Test Construct"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a4d77c7e",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "# Define a simple rule\n",
    "env.build(\"\"\"\n",
    "(defrule example\n",
    "  (test (>= 10 5))\n",
    "  =>\n",
    "  (printout t \"Rule fired!\" crlf))\n",
    "\"\"\")\n",
    "\n",
    "env.reset()\n",
    "\n",
    "env.run()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c8e2922b",
   "metadata": {},
   "source": [
    "# Section G: Modify Fact in Rule ( <- )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4a2fab2c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"(deftemplate rectangle\n",
    "               (slot height)\n",
    "               (slot width))\"\"\")\n",
    "\n",
    "env.build(\"\"\"(defrule sum-rectangles\n",
    "                 ;; assign the fact value to a variable\n",
    "                 ?r<-(rectangle (height ?height) (width ?width))\n",
    "             =>\n",
    "             ;; modify the fact slot value \n",
    "             (modify ?r (width 30)))\"\"\")\n",
    "\n",
    "env.reset()\n",
    "\n",
    "env.assert_string(\"(rectangle (height 5) (width 10))\")\n",
    "\n",
    "env.run()\n",
    "\n",
    "for fact in env.facts():\n",
    "    print(fact)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b5a333df",
   "metadata": {},
   "source": [
    "# Section H: Return Values from Rule"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dbbdb3a8",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"(deftemplate rectangle\n",
    "               (slot height)\n",
    "               (slot width))\"\"\")\n",
    "\n",
    "env.build(\"\"\"(defrule sum-rectangles\n",
    "                 (rectangle (height ?height) (width ?width))\n",
    "              =>\n",
    "             (assert (area (* ?height ?width))))\"\"\")\n",
    "\n",
    "env.reset()\n",
    "\n",
    "env.assert_string(\"(rectangle (height 5) (width 10))\")\n",
    "\n",
    "env.run()\n",
    "\n",
    "for fact in env.facts():\n",
    "    if fact.template.name == \"area\":\n",
    "        print('Area:' + str(fact[0]))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5a20c368",
   "metadata": {},
   "source": [
    "# Section I: Built-in Functions & Expressions"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f79d7bdf",
   "metadata": {},
   "source": [
    "1. Evaluate mathematic **expression**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "52321e02",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "# In CLIPS (assert (sum (+ 3 5 7)))\n",
    "env.eval('(+ 3 5 7)')\n",
    "\n",
    "# Minus\n",
    "env.eval('(- 5 3)')\n",
    "\n",
    "# Multiply\n",
    "env.eval('(* 5 3)')\n",
    "\n",
    "# Division\n",
    "env.eval('(/ 5 2)')\n",
    "\n",
    "# Power of\n",
    "env.eval('(** 2 5)')\n",
    "\n",
    "# Sqrt of\n",
    "env.eval('(sqrt 8)')\n",
    "\n",
    "# Log base 10\n",
    "env.eval('(log10 8)')\n",
    "\n",
    "# Mod\n",
    "env.eval(\"(mod 10 7)\")\n",
    "\n",
    "# Floor Division ??????\n",
    "#env.eval('(// 5 2)')\n",
    "\n",
    "# Floor Division - Mixture Python with CLIPS\n",
    "env.eval(f'(* {5 // 2} 1)')\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "778889ce",
   "metadata": {},
   "source": [
    "2. Evaluate mathematic **expression** with **fact assertion**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5bcd920f",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.reset()\n",
    "\n",
    "value = env.eval('(+ 3 5 7)')\n",
    "env.assert_string(f\"(sum {value})\")\n",
    "\n",
    "# Mixture of Python and clipspy\n",
    "#env.assert_string(f\"(sum {3 + 5 + 7})\")\n",
    "\n",
    "env.run()\n",
    "\n",
    "for fact in env.facts():\n",
    "    print(fact)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fef71525",
   "metadata": {},
   "source": [
    "3. **Summing values** in rules"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "baa5d731",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"(defrule calculate-sum\n",
    "                   (sum ?n1 ?n2)\n",
    "             => (printout t (+ ?n1 ?n2) crlf))\"\"\")\n",
    "\n",
    "env.reset()\n",
    "\n",
    "env.assert_string('(sum 1 2)')\n",
    "\n",
    "env.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7b742ee7",
   "metadata": {},
   "source": [
    "* This will make the infinity loop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d173ba51",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"\n",
    "(deftemplate rectangle\n",
    "    (slot height)\n",
    "    (slot width))\n",
    "\"\"\")\n",
    "\n",
    "env.build(\"\"\"(deffacts initial-information\n",
    "                (rectangle (height 10) (width 6))\n",
    "                (rectangle (height 7) (width 5))\n",
    "                (rectangle (height 6) (width 8))\n",
    "                (rectangle (height 2) (width 5))\n",
    "                (sum 0))\"\"\")\n",
    "\n",
    "env.build(\"\"\"(defrule sum-rectangles\n",
    "                (rectangle (height ?height) (width ?width))\n",
    "                ?sum <- (sum ?total)\n",
    "                =>\n",
    "                (retract ?sum)\n",
    "                (assert (sum (+ ?total (* ?height ?width)))))\n",
    "        \"\"\")\n",
    "\n",
    "\n",
    "env.reset()\n",
    "\n",
    "env.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "47000481",
   "metadata": {},
   "source": [
    "* Fix it!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "02c18325",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"\n",
    "(deftemplate rectangle\n",
    "    (slot height)\n",
    "    (slot width))\n",
    "\"\"\")\n",
    "\n",
    "env.build(\"\"\"(deffacts initial-information\n",
    "                (rectangle (height 10) (width 6))\n",
    "                (rectangle (height 7) (width 5))\n",
    "                (rectangle (height 6) (width 8))\n",
    "                (rectangle (height 2) (width 5))\n",
    "                (sum 0))\"\"\")\n",
    "\n",
    "env.build(\"\"\"(defrule sum-rectangles\n",
    "                (rectangle (height ?height) (width ?width))\n",
    "              => (assert (add-to-sum (* ?height ?width))))\"\"\")\n",
    "\n",
    "env.build(\"\"\"(defrule sum-areas\n",
    "                ?sum<-(sum ?total)\n",
    "                ?new-area<-(add-to-sum ?area)\n",
    "              => (retract ?sum ?new-area)\n",
    "                 (assert (sum (+ ?total ?area))))\"\"\")\n",
    "\n",
    "env.reset()\n",
    "\n",
    "env.run()\n",
    "\n",
    "env.eval('(facts)')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fb821e60",
   "metadata": {},
   "source": [
    "# Section J: Create a User-Defined Function"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a790d126",
   "metadata": {},
   "source": [
    "1. Calling a **user-defined function**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7618286e",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"(deffunction calculate-area \n",
    "                       (?length ?width) (* ?length ?width))\"\"\")\n",
    "\n",
    "# (assert (area (calculate-area 2 3)))\n",
    "env.assert_string(f\"(area (calculate-area 2 3))\")\n",
    "\n",
    "#area= env.eval(f\"(calculate-area 2 3)\")\n",
    "#env.assert_string(f\"(area {area})\")\n",
    "\n",
    "env.run()\n",
    "\n",
    "for fact in env.facts():\n",
    "    print(fact)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f6d90a0b",
   "metadata": {},
   "source": [
    "2. **Passing data** in a **user-defined function** with **parameter values** "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "12a3ffd9",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"(deffunction calculate-area(?x ?y)\n",
    "                       (return (* ?x ?y)))\"\"\")\n",
    "\n",
    "#(deffunction main()\n",
    "#        (printout t \"Area = \" (calculate-area 3 5)))\n",
    "#(main)\"\n",
    "\n",
    "value=env.eval(\"(calculate-area 3 5)\")\n",
    "print(\"Area = \", value)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3787355e",
   "metadata": {},
   "source": [
    "3. Return **tuple** from **user-defined function**. Return more than one values."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "525bbb72",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"(deffunction coordinate(?x ?y)\n",
    "                       (return (create$ ?x ?y)))\"\"\")\n",
    "\n",
    "value=env.eval(\"(coordinate 3 5)\")\n",
    "print(\"Area = \", value)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "461aa608",
   "metadata": {},
   "source": [
    "# Section K: Global Variables"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "23ff449f",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"(defglobal ?*x* = 10)\"\"\")\n",
    "\n",
    "env.reset()\n",
    "\n",
    "env.assert_string(\"\"\"(value (* ?*x* 2))\"\"\")\n",
    "\n",
    "env.run()\n",
    "\n",
    "for fact in env.facts():\n",
    "    print(fact)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8e26b482",
   "metadata": {},
   "source": [
    "# Section L: Bind Functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2958d56c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"(defrule get-name\n",
    "             =>(printout t \"What is your name? \" crlf)\n",
    "               (bind ?response \"Tee Xue Ni\")\n",
    "               (printout t \"I'm \" ?response crlf)\n",
    "               (bind ?response \"Lim Hui Jun\")\n",
    "               (printout t \"Sorry, I'm \" ?response crlf))\"\"\")\n",
    "\n",
    "env.reset()\n",
    "\n",
    "env.run()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "76569838",
   "metadata": {},
   "source": [
    "# Section M: Logical Condition"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "13932020",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.reset()\n",
    "\n",
    "# (assert (status (if (> 2 1) then \"valid\" else \"invalid\"))\n",
    "value = env.eval('(if (> 2 1) then \"valid\" else \"invalid\")')\n",
    "env.assert_string(f\"(status {value}))\")\n",
    "\n",
    "# Mixture of Python and clipspy\n",
    "#env.assert_string(f\"(status {'valid' if 2 > 1 else 'invalid'})\")\n",
    "\n",
    "#py_logical_condition = 'valid' if 2 > 1 else 'invalid'\n",
    "#env.assert_string(f\"(status {py_logical_condition})\")\n",
    "\n",
    "for fact in env.facts():\n",
    "    print(fact)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bd0bf030",
   "metadata": {},
   "source": [
    "# Section N: Exists Condition"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f573330d",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"(deftemplate emergency (slot type))\"\"\")\n",
    "\n",
    "env.build(\"\"\"(defrule operator-alert-for-emergency\n",
    "                (exists (emergency))\n",
    "                (not (operator-alert))\n",
    "             =>\n",
    "                (printout t \"Emergency: Operator Alert\" crlf)\n",
    "                (assert (operator-alert)))\"\"\")\n",
    "\n",
    "env.reset()\n",
    "\n",
    "env.assert_string(\"(emergency (type 'fire'))\")\n",
    "\n",
    "env.run()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "37eda18b",
   "metadata": {},
   "source": [
    "# Section O: Forall"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c9ac2c44",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"\"\"(deftemplate emergency \n",
    "               (slot type)\n",
    "               (slot location))\"\"\")\n",
    "\n",
    "env.build(\"\"\"(deftemplate fire-squad \n",
    "               (slot name)\n",
    "               (slot location))\"\"\")\n",
    "\n",
    "env.build(\"\"\"(deftemplate evacuated \n",
    "               (slot building))\"\"\")\n",
    "\n",
    "# Define the rule using `forall`\n",
    "env.build(\"\"\"\n",
    "(defrule all-fires-handled\n",
    "   (forall\n",
    "      (emergency (type fire) (location ?loc))\n",
    "      (and\n",
    "         (fire-squad (location ?loc))\n",
    "         (evacuated (building ?loc))))\n",
    "   =>\n",
    "   (printout t \"All fire emergencies are handled: firefighters are present, and buildings are evacuated.\" crlf))\n",
    "\"\"\")\n",
    "\n",
    "# Assert facts\n",
    "env.assert_string(\"(emergency (type fire) (location building-1))\")\n",
    "env.assert_string(\"(emergency (type fire) (location building-2))\")\n",
    "env.assert_string(\"(fire-squad (name squad1) (location building-1))\")\n",
    "env.assert_string(\"(fire-squad (name squad2) (location building-2))\")\n",
    "env.assert_string(\"(evacuated (building building-1))\")\n",
    "env.assert_string(\"(evacuated (building building-2))\")\n",
    "\n",
    "env.run()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3c324628-f8f3-49e7-9792-de934d31e8b3",
   "metadata": {},
   "source": [
    "# Section P: logical construct for Truth Maintenance System (TMS)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4e7b9a34-e79e-42a0-a7ed-52743a75bdcc",
   "metadata": {},
   "source": [
    "-   Fact consistency in working memory means that logical dependencies are maintained automatically.\n",
    "    For example, if we define the rule p → q:\n",
    "    - When p is present in working memory, q is derived.\n",
    "    - If p is later retracted, the system must also retract q so that the working memory stays consistent."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a4b5816e-132d-4039-b0f3-c3f32430da1c",
   "metadata": {},
   "source": [
    "1. Fact inconsistency in working memory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "49662b2c-e172-45d5-8f10-6900af5c571e",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"(deftemplate p (slot value))\")\n",
    "\n",
    "env.build(\"(deftemplate q (slot value))\")\n",
    "\n",
    "env.build(\"\"\"\n",
    "(defrule infer-q\n",
    "   (p (value TRUE))   \n",
    "   =>\n",
    "   (assert (q (value TRUE)))   \n",
    ")\"\"\")\n",
    "\n",
    "env.build(\"\"\"\n",
    "(defrule print-q\n",
    "   (q (value ?v))\n",
    "   =>\n",
    "   (printout t \"Q is \" ?v crlf))\"\"\")\n",
    "\n",
    "env.reset()  \n",
    "\n",
    "env.eval(\"(assert (p (value TRUE)))\")\n",
    "\n",
    "env.run()     \n",
    "\n",
    "env.eval(\"(facts)\")\n",
    "\n",
    "env.eval(\"(retract 1)\")\n",
    "env.run() \n",
    "env.eval(\"(facts)\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e9045b95-91c0-4490-9c36-76759312b22e",
   "metadata": {},
   "source": [
    "2. Fact consistency in working memory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f34fe2d9-710c-4d33-ab11-50c1f5ecb5fa",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "env.build(\"(deftemplate p (slot value))\")\n",
    "\n",
    "env.build(\"(deftemplate q (slot value))\")\n",
    "\n",
    "env.build(\"\"\"\n",
    "(defrule infer-q\n",
    "   (logical (p (value TRUE)))   \n",
    "   =>\n",
    "   (assert (q (value TRUE)))   \n",
    ")\"\"\")\n",
    "\n",
    "env.build(\"\"\"\n",
    "(defrule print-q\n",
    "   (q (value ?v))\n",
    "   =>\n",
    "   (printout t \"Q is \" ?v crlf))\"\"\")\n",
    "\n",
    "env.reset()  \n",
    "\n",
    "env.eval(\"(assert (p (value TRUE)))\")\n",
    "\n",
    "env.run()     \n",
    "\n",
    "env.eval(\"(facts)\")\n",
    "\n",
    "env.eval(\"(retract 1)\")\n",
    "env.run() \n",
    "env.eval(\"(facts)\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b3a39a3e",
   "metadata": {},
   "source": [
    "# Exercises:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cd568db7",
   "metadata": {},
   "source": [
    "1. Differentiate **(name ?response)**, **(bind ?response \"abc\")**, **(?response<-(animal 'Garfield'))** in **defrule**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ebcef3f6",
   "metadata": {},
   "outputs": [],
   "source": [
    "#Hints:\n",
    "#1. (name ?response) - \n",
    "#2. (bind ?response \"abc\") - \n",
    "#3. (?response<-(animal 'Garfield')) - "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "621a1e89",
   "metadata": {},
   "source": [
    "2. Rewrite the expression **10+4*19-35/12** in CLIPS notation and verify that you get the **result 83.0833**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c3afbfdd",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "#To Do#\n"
   ]
  },
  {
   "attachments": {
    "image.png": {
     "image/png": "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"
    }
   },
   "cell_type": "markdown",
   "id": "c400d563",
   "metadata": {},
   "source": [
    "3. Write an expert system that gets user input and **gives advice** on the discount rate given.\n",
    "\n",
    "![image.png](attachment:image.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1d6524fa",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "#To Do#"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "af109464",
   "metadata": {},
   "source": [
    "4. Write a rule based expert system to determine **even number** when user provide the inputs. (**Hints**: Must use **defrule** without calling **user-defined function**)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1d7f4c1d",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "#To Do#"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f3d81d22",
   "metadata": {},
   "source": [
    "5. Define two **deftemplate** (**student** and **programme**) and simulate the **left join**, **right join** and **outer join** implementation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "75095b29",
   "metadata": {},
   "outputs": [],
   "source": [
    "import clips \n",
    "import logging\n",
    "\n",
    "# Setup working environment\n",
    "logging.basicConfig(level=logging.INFO,format='%(message)s')\n",
    "    \n",
    "env = clips.Environment()\n",
    "router = clips.LoggingRouter()\n",
    "env.add_router(router)\n",
    "\n",
    "#To Do#"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [conda env:base] *",
   "language": "python",
   "name": "conda-base-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
