Skip to content

Restructure into the aima package (aima/ + notebooks/ + tests/) + converge all editions into one suffix-free module set (#1188)#1340

Open
dmeoli wants to merge 11 commits into
masterfrom
restructure-aima-package
Open

Restructure into the aima package (aima/ + notebooks/ + tests/) + converge all editions into one suffix-free module set (#1188)#1340
dmeoli wants to merge 11 commits into
masterfrom
restructure-aima-package

Conversation

@dmeoli

@dmeoli dmeoli commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator

What

Implements the #1188 decision — converge on the 4th edition and make the library a proper package — in three stages on this branch.

Stage 1 — aima package

All library modules moved under one importable package: from aima.search import astar_search (or from aima import search). Imports rewired across modules, tests, notebooks, gui/ and the Sphinx config; aima-data lookups fixed; pyproject.toml added (pip install -e .).

Stage 2 + 3 — 3e/4e convergence (all 9 pairs)

The canonical (used) module wins for shared symbols; genuinely-new 4e algorithms are folded in; the *4e duplicate + its tests are deleted; consumers/notebooks repointed.

  • agents, logic, reinforcement_learning — pure duplicates removed.
  • games+ monte_carlo_tree_search, mcts_player.
  • mdp+ pomdp_lookahead, update_belief (Dynamic Decision Networks).
  • nlp+ TextParsingProblem, Tree, astar_search_parsing, beam_search_parsing, subspan.
  • probability+ gaussian_probability, logistic_probability, is_independent, ContinuousBayesNode.
  • utils+ gaussian_kernel(_1D/_2D), conv1D, map_vector, MCT_Node, ucb.
  • learningDataSet.sanitize adopts the 4e convention (drops the target); err_ratio/grade_learner now accept either a callable predictor or a .predict learner object (so the 4e class-learners work through the canonical learning, backward-compatible with the 3e closures). deep_learning4e keeps the recursive vector helpers it needs locally, since the grid/search code needs aima.utils' flat tuple/np versions.

Naming-variant duplicates were skipped (expect_min_max_player, model_selection, KB_AgentProgram, extend). The genuinely 4e-only modules with no 3e counterpart (deep_learning4e, game_theory4e, making_simple_decisions4e, notebook4e, perception4e) stay.

Verification

  • Full test suite: 393 passing.
  • Sphinx docs build with 0 warnings.

⚠️ Breaking change — please review before merge

from search import X no longer works → from aima.search import X. This affects downstream users and any open forks/PRs, so we'd like @norvig (and other maintainers) to review before merging. It directly implements the edition policy from #1188 and pairs naturally with the broader notebooks/ + generate-.py-from-.ipynb restructure idea discussed separately.

dmeoli added 3 commits June 27, 2026 20:06
…ence)

Move all library modules under a single importable package: from search import X
becomes from aima.search import X (or from aima import search), per the decision
on #1188 to make the repo a proper package. This commit is the mechanical
package move; the 3e/4e content convergence (unifying the X/X4e pairs) follows
as Stage 2 on this branch.

- git mv the 31 modules into aima/ and add aima/__init__.py.
- Rewire every intra-package import to from aima.<mod>, and update all tests,
  notebooks, gui/ and the Sphinx automodule directives accordingly.
- Fix the aima-data lookups that were anchored to dirname(__file__) (utils,
  utils4e, text) to resolve from the repo root now that the modules live one
  level down.
- Add pyproject.toml (installable via pip install -e ., deps from
  requirements.txt) and note the new import/usage style in the README.

Full test suite passes (502) and the Sphinx docs build with 0 warnings.

BREAKING: top-level imports like 'from search import X' no longer work; use
'from aima.search import X'.
…einforcement_learning4e)

These 4e modules duplicated the same public symbols as their canonical
counterparts, were imported only by their own tests, and added no unique 4e
algorithms (agents/rl: identical symbol sets; logic4e's only 'unique' names were
naming variants KB_AgentProgram/extend already present as KBAgentProgram and
utils.extend). Per the #1188 convergence (keep the used base, drop the parallel
4e branch), delete them plus their tests and docs entries. Shared-symbol 4e
implementations remain available in git history and can be re-adopted as
deliberate per-algorithm 4e upgrades.
)

Fold each X4e's genuinely-new 4e algorithms into the canonical aima/X.py, keep
the used base for shared symbols, then delete the X4e duplicate + reconcile tests:
- games: + monte_carlo_tree_search, mcts_player (MCTS); games4e removed
- mdp: + pomdp_lookahead, update_belief, q_value (DDN); mdp4e removed
- nlp: + Tree, subspan, TextParsingProblem, astar_search_parsing, beam_search_parsing; nlp4e removed
- probability: + is_independent, gen_possible_events, gaussian_probability,
  logistic_probability, ContinuousBayesNode, complied_burglary; probability4e removed
- utils: + gaussian_kernel(_1D/_2D), conv1D, map_vector, MCT_Node, ucb (used by
  the MCTS above); perception4e and making_simple_decisions4e repointed to aima.utils
Notebooks and docs updated to the canonical modules. Skipped naming-variant
duplicates (expect_min_max_player, model_selection, KB_AgentProgram, extend).

DEFERRED: the utils/learning convergence for the 4e ML cluster (utils4e,
learning4e, deep_learning4e) — they are mutually coupled through the 4e
DataSet.sanitize convention (drops the target) and the recursive vector helpers,
so unifying them requires porting that cluster as its own effort. utils4e and
learning4e are kept for now.

Full suite: 407 passed; docs build with 0 warnings.
@dmeoli dmeoli changed the title Restructure modules into the aima package (Stage 1: package move) Restructure into the aima package + converge 7/9 3e-4e module pairs Jun 27, 2026
…1188

Port the last 2 deferred pairs so there is one module per topic:
- learning.DataSet.sanitize now drops the target (the 4e convention) - verified
  it leaves the 3e learning tests green and is what the neural-net learners need.
- learning.err_ratio / grade_learner accept either a callable predictor or a
  learner object with a .predict method (so the 4e class-learners work through
  the canonical learning); backward-compatible with the 3e closures.
- deep_learning4e imports the canonical aima.utils and defines locally the
  recursive vector helpers (element_wise_product/vector_add/scalar_vector_product)
  the neural net needs on nested weights (aima.utils keeps the flat tuple/np
  versions required by the grid/search code).
- Delete utils4e.py and learning4e.py (no genuinely-unique symbols remained -
  model_selection duplicated cross_validation_wrapper); repoint test_deep_learning4e
  and Learners.ipynb to aima.learning; drop the duplicate test_learning4e.

All 9 X/X4e pairs are now unified. Full suite: 393 passed; docs 0 warnings.
@dmeoli dmeoli changed the title Restructure into the aima package + converge 7/9 3e-4e module pairs Restructure into the aima package + converge all 3e/4e module pairs (#1188) Jun 27, 2026
@dmeoli dmeoli marked this pull request as ready for review June 27, 2026 23:36
@dmeoli dmeoli requested a review from norvig June 27, 2026 23:36
@dmeoli

dmeoli commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator Author

@norvig this is ready for your review before merge. It implements the edition policy you set in #1188 (converge on 4e, stop maintaining two trees) and turns the library into an importable aima package:

  • Package: from aima.search import astar_search (or from aima import search); pip install -e . via a new pyproject.toml.
  • Convergence: all 9 X.py/X4e.py pairs unified into one canonical module each — keeping the mature/used implementation for shared symbols and folding in the genuinely-new 4e algorithms (MCTS, DDN, 4e parsing, continuous-variable Bayes nets, etc.).
  • Verification: full test suite 393 passing; Sphinx docs build with 0 warnings.

The one thing to weigh is that it's a breaking import change (from search import Xfrom aima.search import X), which affects downstream users and open forks — hence holding for your sign-off rather than merging directly. It also dovetails with the notebooks/ split + auto-generated .py idea we discussed. Happy to adjust naming/scope however you prefer.

Now that every topic has a single version, rename the 4e-only modules (which had
no 3e counterpart) to plain topic names, and converge the notebook helper pair:
- deep_learning4e -> deep_learning, game_theory4e -> game_theory,
  making_simple_decisions4e -> making_simple_decisions, perception4e -> perception
  (modules + their tests renamed).
- notebook4e folded into notebook_utils (it was a superset: + plot_model_boundary);
  notebook4e deleted. (notebook_utils keeps the Jupyter-collision-safe name from #1294.)
- Repointed every import across modules, tests, notebooks, gui and the Sphinx docs;
  renamed game_theory4e.ipynb -> game_theory.ipynb.

No '*4e' modules remain. Full suite: 393 passed; docs build with 0 warnings.
@dmeoli dmeoli changed the title Restructure into the aima package + converge all 3e/4e module pairs (#1188) Restructure into the aima package + converge all editions into one suffix-free module set (#1188) Jun 28, 2026
@dmeoli

dmeoli commented Jun 28, 2026

Copy link
Copy Markdown
Collaborator Author

Pushed a follow-up commit completing the convergence: now that every topic has a single version, all remaining 4e suffixes are dropped — deep_learning4edeep_learning, game_theory4egame_theory, making_simple_decisions4emaking_simple_decisions, perception4eperception, and notebook4e folded into notebook_utils. No *4e modules remain — one unsuffixed module per topic. Full suite still 393 passing, docs 0 warnings.

Note: moving the top-level notebooks under notebooks/ and the GitHub Action to generate .py from .ipynb are intentionally left as a separate follow-up (they need per-notebook cwd/path fixes and a decision on making the notebook the source of truth — the survey you mentioned).

Complete the folder restructure discussed with Peter Norvig: the importable
code lives in aima/, the tests in tests/, and now every notebook lives under
notebooks/ (alongside the existing notebooks/chapterNN/ chapter demos).

- git mv all 40 top-level *.ipynb into notebooks/ (history preserved as renames).
- Prepend a small bootstrap cell to each moved notebook: when run from the
  notebooks/ folder it chdirs to the repo root, so 'from aima import ...' and the
  cwd-relative aima-data/ and images/ paths resolve unchanged (works on Binder
  too, without needing an editable install).
- README: document the aima/ + notebooks/ + tests/ layout; mark the 3e/4e
  convergence as done (single version per module, no *4e.py files remain).
- CONTRIBUTING: fix the example notebook link to its new notebooks/ path.

The GitHub Action to generate a .py from each .ipynb (making the notebook the
source of truth) is intentionally left out -- it inverts the current
direct-.py workflow and Peter wanted a contributor survey first.
@dmeoli dmeoli changed the title Restructure into the aima package + converge all editions into one suffix-free module set (#1188) Restructure into the aima package (aima/ + notebooks/ + tests/) + converge all editions into one suffix-free module set (#1188) Jun 28, 2026
@dmeoli

dmeoli commented Jun 28, 2026

Copy link
Copy Markdown
Collaborator Author

Folder restructure now complete on this branch too: all 40 top-level *.ipynb moved under notebooks/ (alongside the existing notebooks/chapterNN/ demos), so the layout is now aima/ (package) + notebooks/ + tests/. Each moved notebook gets a tiny bootstrap cell that chdirs to the repo root when run from notebooks/, so from aima import ... and the cwd-relative aima-data//images/ paths keep working unchanged (and it works on Binder without an editable install). History preserved (git renames). README/CONTRIBUTING updated.

The only piece of the restructure deliberately not included is the GitHub Action to generate a .py from each .ipynb — that inverts the current direct-.py workflow and, per your note, wants a contributor survey first. Happy to do it as a follow-up once the survey settles.

The *4e.ipynb notebooks were standalone parallel notebooks that imported nothing
from the package and re-defined the whole API inline (search4e: 110 defs/16
classes, games4e: 59/7, probability4e: 20/8) -- Norvig's self-contained 4e
teaching notebooks. The base search/games/probability.ipynb notebooks instead
demo the converged aima package (from aima.<module> import *) and are 3-5x more
comprehensive, so they are the canonical single version per topic -- mirroring
the module-level convergence.

- Removed search4e.ipynb, games4e.ipynb, probability4e.ipynb and the explicitly
  obsolete obsolete_search4e.ipynb.
- Dropped the duplicate 'Search - 4th edition' link from notebooks/index.ipynb.

No '*4e' files of any kind remain in the repo.
@dmeoli

dmeoli commented Jun 28, 2026

Copy link
Copy Markdown
Collaborator Author

Unified the 4e notebooks into the base ones — the repo now has no 4e files of any kind (modules, tests, or notebooks).

The *4e.ipynb notebooks turned out to be standalone parallel notebooks that imported nothing from the package and re-defined the whole API inline (search4e: 110 defs/16 classes, games4e: 59/7, probability4e: 20/8 — Norvig's self-contained 4e teaching notebooks). The base search/games/probability.ipynb instead demo the converged aima package (from aima.<module> import *) and are 3–5× more comprehensive, so they're the canonical single notebook per topic — mirroring the module-level convergence. Removed search4e/games4e/probability4e and the explicitly-obsolete obsolete_search4e, and dropped the duplicate index link.

dmeoli added 2 commits June 28, 2026 13:45
Audit found genuine cross-module duplication (the rest of the 16 same-name
collisions are different-by-design: Graph x3 distinct classes, turn_left/right
logic-proposition vs heading-rotation, the deep_learning recursive vector
helpers, etc.):
- making_simple_decisions.py was a 100%-duplicate, zero-importer module ->
  now a thin re-export of probability's canonical DecisionNetwork /
  InformationGatheringAgent.
- csp.flatten duplicated utils.flatten (identical) -> import from utils.

Latent bugs (uncovered while making the notebooks run, both in
previously-untested paths; full suite still 393 passed):
- notebook_utils.Canvas_min_max.__init__ called 'super.__init__' (missing
  parens) -> 'super().__init__'.
- planning.RealWorldPlanningProblem.angelic_search called decompose() with 3
  args but its signature needs 4 (missing 'plan') -> fixed.
…structure

The notebooks carried name/API drift from the earlier snake_case-rename and the
edition convergence that was never propagated to them. Updated them to the
canonical API (no duplicate aliases added):
- games: minimax_decision->minmax_decision, alphabeta_*->alpha_beta_*,
  Canvas_minimax/alphabeta->Canvas_min_max/alpha_beta, 'alphabeta'->'alpha_beta'.
- knowledge_foil: FOIL_container->FOILContainer. arc_consistency: all_diff->all_diff_constraint.
- planning x4: Problem->PlanningProblem (graph_plan) / RealWorldPlanningProblem
  (angelic+hierarchical), Angelic_HLA->AngelicHLA, Angelic_Node->AngelicNode,
  *_graphplan->*_graph_plan, refinements(hla,prob,lib)->refinements(hla,lib),
  prob.init->prob.initial, cake plan reordered to satisfy preconditions.
- probability: dropped invalid forward_backward(prior=...) kwarg.
- chapter19: Learners import order (deep_learning's class learners win),
  Loss sigmoid()->Sigmoid()/.f->.function/activation=Sigmoid,
  Optimizer gradient_descent->stochastic_gradient_descent, adam_optimizer->adam.
- chapter21 Active/Passive: 'from rl4e import *' -> aima.reinforcement_learning.
- chapter22 nlp_apps/Parsing: add the missing sys.path + import bootstrap.
- chapter24 Image Edge Detection: define gaussian_filter = gaussian_kernel_2D().

Docs (file repositioning + convergence): README algorithm-index links repointed
to aima/ and de-suffixed (mdp4e->mdp, game_theory4e->game_theory, FOIL_container
->FOILContainer); edition wording marks the convergence done; CONTRIBUTING and
the Sphinx index updated for the single-version aima/ layout.
@dmeoli

dmeoli commented Jun 28, 2026

Copy link
Copy Markdown
Collaborator Author

Completed a no-loss / no-duplicate audit + full notebook QA on the branch:

Algorithm audit (zero loss): AST-compared every original 3e and 4e file's top-level functions/classes/methods against the merged modules — every symbol is present (the few apparent gaps were naming-variants like expect_min_max_playerexpect_minmax_player, KB_AgentProgramKBAgentProgram).

Cross-module duplicates: of 16 same-name collisions, only 2 were genuine duplication and are now resolved — making_simple_decisions.py (was a 100%-duplicate, zero-importer module → thin re-export of probability's canonical versions) and csp.flatten (→ import from utils). The other 14 are different-by-design (e.g. Graph is three distinct classes; turn_left is a logic proposition in logic vs a heading rotation in utils; the deep-learning recursive vector helpers are intentional) — merging those would be incorrect.

Notebooks: executed all 54 (headless). The failures were pre-existing name/API drift the old snake_case-rename never propagated to the notebooks (not a restructure regression). Updated ~18 notebooks to the canonical API (no duplicate aliases) and fixed 2 real latent module bugs found in the process — Canvas_min_max super.super() and angelic_search's decompose() call missing its plan arg. Full test suite stays 393 passed.

Remaining notebook failures are environmental or pre-existing, not restructure-related: dot/opencv-contrib system binaries (viterbi, chapter24/Objects), an ipywidgets interact(visualize=) version issue (mdp, learning_apps, chapter16-17), genuinely-slow training cells (improving_sat, RNN), and a few pre-existing notebook logic bugs (search two_opt, Parsing float.leaves).

Docs: README algorithm-index links repointed to aima/ and de-suffixed, edition wording marks the convergence done; CONTRIBUTING + Sphinx index updated.

- search.ipynb: cell 112 redefines hill_climbing as a TSP-specific version
  (using two_opt), shadowing the library's generic one; the later Peak-Finding
  section then called it on a PeakFindingProblem (no two_opt) and failed.
  Re-import the library hill_climbing right before that section.
- chapter22/Parsing.ipynb: CYK_parse returns a probability table
  (defaultdict(float)), but the cells called .leaves on the float values.
  Display the probabilities instead (full table; VP entries).
- chapter19/Optimizer and Backpropagation.ipynb: pseudocode() is a string API
  (e.g. pseudocode('Back-Prop-Learning')); pseudocode(adam) passed a function
  and Adam has no aima-pseudocode entry. Dropped it; psource(adam) still shows
  the implementation.

All three now run clean headless; no module changes (test suite unaffected).
@dmeoli

dmeoli commented Jun 28, 2026

Copy link
Copy Markdown
Collaborator Author

Fixed the 3 pre-existing notebook logic bugs (commit 0fec505):

  • search.ipynb — a cell redefined hill_climbing as a TSP-specific version (using two_opt), shadowing the library's generic one; the later Peak-Finding section then called it on a PeakFindingProblem and failed. Re-import the library hill_climbing right before that section.
  • chapter22/Parsing.ipynbCYK_parse returns a probability table (defaultdict(float)), but the cells called .leaves on the float values; now they display the probabilities.
  • chapter19/Optimizer and Backpropagation.ipynbpseudocode is a string API (pseudocode('Back-Prop-Learning')); pseudocode(adam) passed a function and Adam has no pseudocode entry — dropped it (psource(adam) still shows the source).

All three now run clean headless; no module changes, test suite still 393 passed.

…dgets, kNN)

(a) Dependencies:
- requirements.txt: opencv-python -> opencv-contrib-python (provides cv2.ximgproc,
  needed by chapter24/Objects in Images), and add graphviz (viterbi_algorithm).
- README: note that the graphviz PyPI pkg is only a wrapper; the 'dot' system
  binary must be installed separately for notebook rendering.

(b) Version-compat / logic:
- mdp.ipynb & chapter16-17/Algorithms for MDPs.ipynb: the interactive() call passed
  'Visualize=' but make_visualize's callback parameter is 'visualize' (lowercase);
  newer ipywidgets errors on the unmatched name. Fixed the case.
- aima/learning.py NearestNeighborLearner: heapq.nsmallest compared (distance, example)
  tuples, so equal-distance ties compared the examples themselves -> numpy arrays
  (e.g. MNIST images) raise 'truth value is ambiguous'. Add an enumerate() index as
  a tiebreaker so payloads are never compared. Fixes learning_apps.ipynb; full suite
  still 393 passed.

mdp, chapter16-17/Algorithms and learning_apps now run clean. chapter24/Objects'
cv2.ximgproc gap is resolved (remaining failure is a slow model/selective-search
cell); viterbi now only needs the system 'dot' binary.
@dmeoli

dmeoli commented Jun 28, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed the remaining notebook deps + version-compat issues (commit fd17215):

  • requirements.txt: opencv-pythonopencv-contrib-python (provides cv2.ximgproc, needed by chapter24/Objects) and added graphviz. README now notes the dot system binary must be installed separately (the PyPI graphviz is only a wrapper).
  • ipywidgets (mdp, chapter16-17/Algorithms): interactive(..., Visualize=...) didn't match make_visualize's lowercase visualize parameter; newer ipywidgets errors on the unmatched name — fixed the case. Both green now.
  • numpy / k-NN (learning_apps): NearestNeighborLearner did heapq.nsmallest over (distance, example) tuples, so equal-distance ties compared the examples — numpy arrays (MNIST) raise 'truth value is ambiguous'. Added an enumerate() index tiebreaker so payloads are never compared (general fix; full suite still 393 passed). learning_apps green now.

Net: mdp, chapter16-17/Algorithms, learning_apps now run clean. chapter24/Objects' ximgproc gap is resolved (only a slow model/selective-search cell remains); viterbi now needs only the system dot binary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant