{
    "cells": [
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Hawksight-AI/semantica/blob/main/cookbook/advanced/08_Reasoning_and_Inference.ipynb)\n",
                "\n",
                "# Reasoning and Inference\n",
                "\n",
                "## Overview\n",
                "\n",
                "Build knowledge graphs, define rules, perform forward/backward chaining, and generate explanations for AI reasoning using the **Semantica Reasoning Module**.\n",
                "\n",
                "\n",
                "**Documentation**: [API Reference](https://semantica.readthedocs.io/reference/reasoning/)\n",
                "\n",
                "## Installation\n",
                "\n",
                "Install Semantica from PyPI:\n",
                "\n",
                "```bash\n",
                "pip install semantica\n",
                "# Or with all optional dependencies:\n",
                "pip install semantica[all]\n",
                "```\n",
                "\n",
                "## Workflow: Build KG → Define Rules → Forward/Backward Chaining → Generate Explanations\n"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "from semantica.kg import GraphBuilder\n",
                "from semantica.reasoning import InferenceEngine, RuleManager, ExplanationGenerator\n"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "## Step 1: Build Knowledge Graph\n"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "builder = GraphBuilder()\n",
                "\n",
                "entities = [\n",
                "    {\"id\": \"alice\", \"type\": \"Person\", \"name\": \"Alice\"},\n",
                "    {\"id\": \"bob\", \"type\": \"Person\", \"name\": \"Bob\"},\n",
                "    {\"id\": \"charlie\", \"type\": \"Person\", \"name\": \"Charlie\"},\n",
                "    {\"id\": \"sf\", \"type\": \"Location\", \"name\": \"San Francisco\"},\n",
                "    {\"id\": \"california\", \"type\": \"Location\", \"name\": \"California\"},\n",
                "]\n",
                "\n",
                "relationships = [\n",
                "    {\"source\": \"alice\", \"target\": \"bob\", \"type\": \"parent_of\"},\n",
                "    {\"source\": \"bob\", \"target\": \"charlie\", \"type\": \"parent_of\"},\n",
                "    {\"source\": \"sf\", \"target\": \"california\", \"type\": \"located_in\"},\n",
                "    {\"source\": \"alice\", \"target\": \"sf\", \"type\": \"lives_in\"},\n",
                "]\n",
                "\n",
                "knowledge_graph = builder.build([{\"entities\": entities, \"relationships\": relationships}])\n"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "## Step 2: Define Rules\n"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "# Initialize Inference Engine\n",
                "engine = InferenceEngine()\n",
                "\n",
                "# Define rules using logic syntax\n",
                "rules = [\n",
                "    \"IF parent_of(?a, ?b) AND parent_of(?b, ?c) THEN grandparent_of(?a, ?c)\",\n",
                "    \"IF lives_in(?x, ?y) AND located_in(?y, ?z) THEN lives_in(?x, ?z)\"\n",
                "]\n",
                "\n",
                "for rule in rules:\n",
                "    engine.add_rule(rule)\n"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "## Step 3: Forward Chaining\n"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "# Load facts from relationships into the engine\n",
                "for rel in relationships:\n",
                "    # Format: predicate(subject, object)\n",
                "    fact_str = f\"{rel['type']}({rel['source']}, {rel['target']})\"\n",
                "    engine.add_fact(fact_str)\n",
                "\n",
                "# Perform forward chaining to derive new facts\n",
                "results = engine.forward_chain()\n",
                "\n",
                "print(f\"Inferred {len(results)} new facts:\")\n",
                "for result in results:\n",
                "    print(f\" - {result.conclusion} (Rule: {result.rule_used.name})\")\n"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "## Step 4: Backward Chaining\n"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "# Define a goal to prove\n",
                "goal = \"grandparent_of(alice, charlie)\"\n",
                "\n",
                "# Perform backward chaining\n",
                "proof = engine.backward_chain(goal)\n",
                "\n",
                "if proof:\n",
                "    print(f\"Goal '{goal}' proven successfully!\")\n",
                "else:\n",
                "    print(f\"Could not prove goal '{goal}'.\")\n"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "## Step 5: Generate Explanations\n"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "generator = ExplanationGenerator()\n",
                "\n",
                "# Explain the last forward chaining inference\n",
                "if results:\n",
                "    explanation = generator.generate_explanation(results[0])\n",
                "    print(\"Explanation for first inferred fact:\")\n",
                "    print(explanation.natural_language)\n",
                "\n",
                "# If we have a proof from backward chaining, explain it\n",
                "if proof:\n",
                "    proof_explanation = generator.generate_explanation(proof)\n",
                "    print(\"\\nExplanation for backward chaining proof:\")\n",
                "    print(proof_explanation.natural_language)\n"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "## Summary\n",
                "\n",
                "Reasoning and inference workflow:\n",
                "- Knowledge Graph Built\n",
                "- Inference Rules Defined\n",
                "- Facts Loaded into Engine\n",
                "- Forward Chaining Performed\n",
                "- Backward Chaining Performed\n",
                "- Explanations Generated\n"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "---\n",
                "\n",
                "### Deep Dive: Reasoning Module\n",
                "\n",
                "This section provides an in-depth guide to Semantica's reasoning capabilities. Learn rule syntax, fact formats, chaining strategies, and explanation generation with robust, reproducible examples.\n",
                "\n",
                "**What you'll practice**\n",
                "- Defining rules with variables and predicates\n",
                "- Loading facts in predicate form\n",
                "- Running forward and backward chaining\n",
                "- Generating human-readable explanations\n"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "from semantica.kg import GraphBuilder\n",
                "from semantica.reasoning import InferenceEngine, ExplanationGenerator\n",
                "\n",
                "builder = GraphBuilder()\n",
                "engine = InferenceEngine()\n",
                "explainer = ExplanationGenerator()\n"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "### Rule Syntax\n",
                "\n",
                "Rules use predicate logic with variables prefixed by `?`.\n",
                "\n",
                "- Example: `IF parent_of(?a, ?b) AND parent_of(?b, ?c) THEN grandparent_of(?a, ?c)`\n",
                "- Variables unify across predicates in the same rule\n",
                "- Conclusions are added as new facts when conditions match\n"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "entities = [\n",
                "    {\"id\": \"alice\", \"type\": \"Person\", \"name\": \"Alice\"},\n",
                "    {\"id\": \"bob\", \"type\": \"Person\", \"name\": \"Bob\"},\n",
                "    {\"id\": \"charlie\", \"type\": \"Person\", \"name\": \"Charlie\"},\n",
                "    {\"id\": \"sf\", \"type\": \"Location\", \"name\": \"San Francisco\"},\n",
                "    {\"id\": \"california\", \"type\": \"Location\", \"name\": \"California\"}\n",
                "]\n",
                "\n",
                "relationships = [\n",
                "    {\"source\": \"alice\", \"target\": \"bob\", \"type\": \"parent_of\"},\n",
                "    {\"source\": \"bob\", \"target\": \"charlie\", \"type\": \"parent_of\"},\n",
                "    {\"source\": \"sf\", \"target\": \"california\", \"type\": \"located_in\"},\n",
                "    {\"source\": \"alice\", \"target\": \"sf\", \"type\": \"lives_in\"}\n",
                "]\n",
                "\n",
                "knowledge_graph = builder.build([{\"entities\": entities, \"relationships\": relationships}])\n",
                "print(len(knowledge_graph.get(\"entities\", [])))\n",
                "print(len(knowledge_graph.get(\"relationships\", [])))\n"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "rules = [\n",
                "    \"IF parent_of(?a, ?b) AND parent_of(?b, ?c) THEN grandparent_of(?a, ?c)\",\n",
                "    \"IF lives_in(?x, ?y) AND located_in(?y, ?z) THEN lives_in(?x, ?z)\"\n",
                "]\n",
                "for r in rules:\n",
                "    engine.add_rule(r)\n"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "for rel in relationships:\n",
                "    fact = f\"{rel['type']}({rel['source']}, {rel['target']})\"\n",
                "    engine.add_fact(fact)\n",
                "\n",
                "derived = engine.forward_chain()\n",
                "print(len(derived))\n",
                "for d in derived:\n",
                "    print(d.conclusion)\n"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "goals = [\n",
                "    \"grandparent_of(alice, charlie)\",\n",
                "    \"lives_in(alice, california)\"\n",
                "]\n",
                "for g in goals:\n",
                "    proof = engine.backward_chain(g)\n",
                "    print(g)\n",
                "    print(bool(proof))\n"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "if derived:\n",
                "    exp = explainer.generate_explanation(derived[0])\n",
                "    print(exp.natural_language)\n",
                "\n",
                "goal = \"grandparent_of(alice, charlie)\"\n",
                "proof = engine.backward_chain(goal)\n",
                "if proof:\n",
                "    pexp = explainer.generate_explanation(proof)\n",
                "    print(pexp.natural_language)\n"
            ]
        }
    ],
    "metadata": {
        "language_info": {
            "name": "python"
        }
    },
    "nbformat": 4,
    "nbformat_minor": 2
}
