Metadata-Version: 2.4
Name: ai9414
Version: 0.1.1
Summary: Interactive teaching demos for AI search, logic, planning, CSP, uncertainty, and tokenisation.
Project-URL: Homepage, https://github.com/OliverObst/artificial-intelligence
Project-URL: Repository, https://github.com/OliverObst/artificial-intelligence
Project-URL: Issues, https://github.com/OliverObst/artificial-intelligence/issues
Author-email: Oliver Obst <o.obst@unsw.edu.au>
License-Expression: GPL-3.0-only
License-File: LICENSE
Keywords: artificial-intelligence,csp,education,logic,planning,search,teaching
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Education
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Education
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.11
Requires-Dist: fastapi<1.0,>=0.116
Requires-Dist: pydantic<3.0,>=2.11
Requires-Dist: uvicorn<1.0,>=0.35
Provides-Extra: dev
Requires-Dist: build<2.0,>=1.2; extra == 'dev'
Requires-Dist: httpx<1.0,>=0.28; extra == 'dev'
Requires-Dist: pytest<9.0,>=8.4; extra == 'dev'
Requires-Dist: twine<7.0,>=6.1; extra == 'dev'
Description-Content-Type: text/markdown

# AI9414

`ai9414` is a Python teaching toolkit for interactive artificial intelligence demos. It opens small browser-based visualisations for search, logic, uncertainty, constraint satisfaction, planning, and tokenisation, with simple installed commands that are easy to use in class.

![AI9414 branch-and-bound demo screenshot](https://raw.githubusercontent.com/OliverObst/artificial-intelligence/main/docs/images/bnb-demo.png)

It currently includes fourteen ready-to-run demos:

- labyrinth DFS search
- office delivery DFS search
- spatial graph DFS search
- spatial graph BFS search
- spatial graph greedy best-first search
- spatial graph A* search
- spatial graph uniform-cost search
- spatial graph branch-and-bound search
- propositional logic DPLL
- reasoning with uncertainty belief-state explorer
- foundation models tokenisation explorer
- CSP map colouring
- CSP delivery time-slot assignment
- STRIPS planning

## Available demos

- `labyrinth DFS search`
  Start with `ai9414 demo labyrinth`
- `office delivery DFS search`
  Start with `ai9414 demo delivery`. This demo has fixed office layouts and an action-order control for DFS.
- `spatial graph DFS search`
  Start with `ai9414 demo graph-dfs`
- `spatial graph BFS search`
  Start with `ai9414 demo graph-bfs`
- `spatial graph greedy best-first search`
  Start with `ai9414 demo graph-gbfs`
- `spatial graph A* search`
  Start with `ai9414 demo graph-astar`
- `spatial graph uniform-cost search`
  Start with `ai9414 demo graph-ucs`
- `spatial graph branch-and-bound search`
  Start with `ai9414 demo graph-bnb`
- `propositional logic DPLL`
  Start with `ai9414 demo logic-dpll`
- `reasoning with uncertainty belief-state explorer`
  Start with `ai9414 demo uncertainty`
- `foundation models tokenisation explorer`
  Start with `ai9414 demo foundation-models`
- `CSP map colouring`
  Start with `ai9414 demo csp-map`
- `CSP delivery time-slot assignment`
  Start with `ai9414 demo csp-delivery`
- `STRIPS planning`
  Start with `ai9414 demo strips`

## Why use it

- one installed package with a small command-line interface: `ai9414 ...`
- browser-based visualisations with packaged frontend assets and no separate web build step
- curated examples for search, logic, uncertainty, CSP, planning, and tokenisation
- graph-search examples use conventional `S` and `G` labels for start and goal nodes
- Python APIs for loading custom problems and launching demos directly from code
- replayable traces for classroom walkthroughs and static solution export
- automated tests plus contributor documentation

## Quick start

Install from PyPI:

```bash
uvx ai9414 demo graph-bnb
```

Install directly from this repository:

```bash
uv sync
uv run ai9414 list
uv run ai9414 demo graph-bnb
```

If your environment does not put console scripts on `PATH`, the module entry point works too:

```bash
uv run python -m ai9414 demo graph-bnb
```

To see the curated example names for a demo:

```bash
uv run ai9414 list --examples graph-dfs
```

## For contributors

```bash
uv sync --extra dev
uv run pytest
uv build
uv run ai9414 demo graph-bnb
```

## Direct example scripts

The scripts under `examples/` are still useful when working directly in the repository, but they are no longer the main installed interface.

To start the labyrinth example directly from the repository:

```bash
uv run python examples/labyrinth_demo.py
```

To start the delivery DFS example directly from the repository:

```bash
uv run python examples/delivery_demo.py
```

To start the spatial graph DFS example directly from the repository:

```bash
uv run python examples/graph_dfs_demo.py
```

To start the spatial graph BFS example directly from the repository:

```bash
uv run python examples/graph_bfs_demo.py
```

To start the spatial graph greedy best-first example directly from the repository:

```bash
uv run python examples/graph_gbfs_demo.py
```

To start the spatial graph A* example directly from the repository:

```bash
uv run python examples/graph_astar_demo.py
```

To start the spatial graph uniform-cost example directly from the repository:

```bash
uv run python examples/graph_ucs_demo.py
```

To start the spatial graph branch-and-bound example directly from the repository:

```bash
uv run python examples/graph_branch_and_bound_demo.py
```

To start the DPLL logic example directly from the repository:

```bash
uv run python examples/logic_dpll_demo.py
```

To start the reasoning-with-uncertainty example directly from the repository:

```bash
uv run python examples/uncertainty_demo.py
```

To start the foundation models tokenisation example directly from the repository:

```bash
uv run python examples/foundation_models_demo.py
```

To start the CSP map-colouring example directly from the repository:

```bash
uv run python examples/csp_demo.py
```

To start the CSP delivery scheduling example directly from the repository:

```bash
uv run python examples/delivery_csp_demo.py
```

To start the STRIPS planning example directly from the repository:

```bash
uv run python examples/strips_demo.py
```

The same install is enough for the labyrinth live-Python stub as well. The
student download now uses the built-in `ai9414.search.run_labyrinth_solver(...)`
wrapper, so no separate Flask setup is required.

To export a backend-free replay bundle:

```bash
PYTHONPATH=src uv run python - <<'PY'
from pathlib import Path
from ai9414.search import SearchDemo

app = SearchDemo()
output_dir = app.export_solution_bundle(Path("build/search-solution"))
print(output_dir)
PY
```

## Student-facing examples

Labyrinth example:

```python
from ai9414.labyrinth import LabyrinthDemo

app = LabyrinthDemo()
app.load_example("small")
app.show()
```

Spatial graph DFS example:

```python
from ai9414.graph_dfs import GraphDfsDemo

app = GraphDfsDemo()
app.load_example("small")
app.show()
```

Spatial graph BFS example:

```python
from ai9414.graph_bfs import GraphBfsDemo

app = GraphBfsDemo()
app.load_example("small")
app.show()
```

Spatial graph greedy best-first example:

```python
from ai9414.graph_gbfs import GraphGbfsDemo

app = GraphGbfsDemo()
app.load_example("small")
app.show()
```

Spatial graph A* example:

```python
from ai9414.graph_astar import GraphAStarDemo

app = GraphAStarDemo()
app.load_example("small")
app.show()
```

Spatial graph branch-and-bound example:

```python
from ai9414.search import SearchDemo

app = SearchDemo()
app.load_example("small")
app.set_options(playback_speed=1.0)
app.show()
```

Spatial graph uniform-cost example:

```python
from ai9414.graph_ucs import GraphUcsDemo

app = GraphUcsDemo()
app.load_example("small")
app.show()
```

Visual DPLL example:

```python
from ai9414.logic import DpllDemo

app = DpllDemo()
app.load_example("unit_chain")
app.show()
```

Reasoning with uncertainty example:

```python
from ai9414.uncertainty import BeliefStateExplorer

app = BeliefStateExplorer()
app.load_example("office_localisation_basic")
app.show()
```

Set a custom initial belief:

```python
from ai9414.uncertainty import BeliefStateExplorer

app = BeliefStateExplorer()
app.load_example("office_localisation_basic")
app.set_belief({
    "mail_room": 0.1,
    "office_a": 0.4,
    "corridor": 0.2,
    "office_b": 0.2,
    "lab": 0.1,
})
app.show()
```

Foundation models tokenisation example:

```python
from ai9414.foundation_models import TokenisationExplorer

app = TokenisationExplorer()
app.load_example("simple_sentence")
app.show()
```

Custom tokenisation text:

```python
from ai9414.foundation_models import TokenisationExplorer

app = TokenisationExplorer()
app.load_corpus("office_messages")
app.learn_merges(12)
app.set_text("Deliver parcel to Office A before 10:30.")
app.show()
```

Visual CSP example:

```python
from ai9414.csp import CSPDemo

app = CSPDemo(example="australia")
app.set_algorithm("backtracking_forward_checking")
app.show()
```

Custom CSP map:

```python
from ai9414.csp import CSPDemo

app = CSPDemo()
app.load_map_problem(
    regions=["a", "b", "c", "d"],
    adjacency={
        "a": ["b", "c"],
        "b": ["a", "c", "d"],
        "c": ["a", "b", "d"],
        "d": ["b", "c"],
    },
    colours=["red", "green", "blue"],
)
app.set_variable_ordering("mrv")
app.show()
```

Delivery scheduling CSP example:

```python
from ai9414.delivery_csp import DeliveryCSPDemo

app = DeliveryCSPDemo(example="weekday_schedule")
app.set_algorithm("backtracking_forward_checking")
app.show()
```

Custom delivery scheduling CSP:

```python
from ai9414.delivery_csp import DeliveryCSPDemo

app = DeliveryCSPDemo()
app.load_delivery_problem(
    deliveries=[
        {"id": "a", "label": "Delivery A", "short_label": "A", "colour": "#c75b4a"},
        {"id": "b", "label": "Delivery B", "short_label": "B", "colour": "#4d79ab"},
    ],
    slots=[
        {"id": "slot_1", "label": "09:00", "order": 0},
        {"id": "slot_2", "label": "11:00", "order": 1},
    ],
    rooms=[
        {"id": "dock", "label": "Dock"},
    ],
    values=[
        {"id": "slot_1_dock", "slot": "slot_1", "room": "dock", "label": "09:00 @ Dock"},
        {"id": "slot_2_dock", "slot": "slot_2", "room": "dock", "label": "11:00 @ Dock"},
    ],
    domains={
        "a": ["slot_1_dock", "slot_2_dock"],
        "b": ["slot_2_dock"],
    },
    constraints=[
        {
            "kind": "precedence",
            "left": "a",
            "right": "b",
            "label": "A before B",
            "description": "Delivery A must happen before delivery B.",
        }
    ],
)
app.set_variable_ordering("mrv")
app.show()
```

Visual STRIPS planning example:

```python
from ai9414.strips import StripsDemo

app = StripsDemo()
app.load_example("canonical_delivery")
app.show()
```

Custom STRIPS problem:

```python
from ai9414.strips import StripsDemo, StripsProblem

problem = StripsProblem(
    rooms=["corridor", "mail_room", "office_a", "office_b", "lab"],
    robot_start="corridor",
    parcel_start="mail_room",
    keycard_start="office_a",
    locked_edge=("corridor", "lab"),
    door_locked=True,
    goal=[("at", "parcel", "lab")],
)

app = StripsDemo(problem=problem)
app.solve()
app.show()
```

Suggested STRIPS exercises:

- Move the keycard from office A to office B and predict how the plan changes.
- Start the robot in the mail room and explain why collecting the parcel too early is a bad idea.
- Unlock the lab door at the start and identify which action disappears from the plan.
- Move the locked door to the office B connection and compare the new plan structure.

Custom CNF with DPLL:

```python
from ai9414.logic import DpllDemo

app = DpllDemo()
app.load_cnf([
    ["A", "B"],
    ["~A", "C"],
    ["~B", "C"],
])
app.show()
```

Entailment with DPLL:

```python
from ai9414.logic import DpllDemo

app = DpllDemo(mode="entailment")
app.load_kb(
    formulas=["A -> B", "B -> C", "A"],
    query="C",
)
app.show()
```

Live labyrinth solver wrapper:

```python
from typing import Any
from ai9414.search import run_labyrinth_solver


def solve_dfs(labyrinth: dict[str, Any]) -> dict[str, Any]:
    ...


if __name__ == "__main__":
    run_labyrinth_solver(solve_dfs)
```

Live graph solver wrapper:

```python
from typing import Any
from ai9414.search import run_graph_solver


def solve_dfs(graph: dict[str, Any]) -> dict[str, Any]:
    ...


if __name__ == "__main__":
    run_graph_solver(solve_dfs)
```

Live graph BFS solver wrapper:

```python
from typing import Any
from ai9414.search import run_graph_bfs_solver


def solve_bfs(graph: dict[str, Any]) -> dict[str, Any]:
    ...


if __name__ == "__main__":
    run_graph_bfs_solver(solve_bfs)
```

Live graph A* solver wrapper:

```python
from typing import Any
from ai9414.search import run_graph_astar_solver


def solve_astar(graph: dict[str, Any]) -> dict[str, Any]:
    ...


if __name__ == "__main__":
    run_graph_astar_solver(solve_astar)
```

Live graph UCS solver wrapper:

```python
from typing import Any
from ai9414.search import run_graph_ucs_solver


def solve_ucs(graph: dict[str, Any]) -> dict[str, Any]:
    ...


if __name__ == "__main__":
    run_graph_ucs_solver(solve_ucs)
```

Live graph greedy best-first solver wrapper:

```python
from typing import Any
from ai9414.search import run_graph_gbfs_solver


def solve_gbfs(graph: dict[str, Any]) -> dict[str, Any]:
    ...


if __name__ == "__main__":
    run_graph_gbfs_solver(solve_gbfs)
```

Live spatial graph branch-and-bound solver wrapper:

```python
from typing import Any
from ai9414.search import run_weighted_graph_solver


def solve_dfbb(graph: dict[str, Any]) -> dict[str, Any]:
    ...


if __name__ == "__main__":
    run_weighted_graph_solver(solve_dfbb)
```

Live DPLL solver wrapper:

```python
from typing import Any
from ai9414.logic import run_dpll_solver


def solve_dpll(problem: dict[str, Any], options: dict[str, Any]) -> dict[str, Any]:
    ...


if __name__ == "__main__":
    run_dpll_solver(solve_dpll)
```

## Repository structure

```text
src/ai9414/
  core/
  demo/
  graph_bfs/
  graph_dfs/
  graph_astar/
  graph_gbfs/
  graph_ucs/
  labyrinth/
  logic/
  search/
  frontend/
examples/
tests/
docs/
```
