Skip to content

Commit 58f003c

Browse files
committed
Notebooks: replace per-notebook bootstrap cell with a shared %run bootstrap.ipynb
Per Peter Norvig's review note on #1340: instead of several lines in each notebook's bootstrap cell, use one '%run bootstrap.ipynb'. - Added notebooks/bootstrap.ipynb: walks up to the repo root (the dir containing the aima package) and puts it on sys.path -- no chdir, so it is idempotent and works whether run from notebooks/ or notebooks/chapterNN/. - Replaced the bootstrap cell in all 36 top-level notebooks with '%run bootstrap.ipynb'. - Dropping the chdir means cwd-relative resource paths had to be anchored to the repo root via __file__ (makes the package cwd-independent, also good for 'pip install -e .'): - notebook_utils: load_MNIST path + images/queen_s.png - ipyviews: js/continuousworld.js, js/gridworld.js (opened at import time) - perception: images/stapler1-test.png - improving_sat_algorithms.ipynb: open('aima-data/zebra.cnf') -> open_data('zebra.cnf') Verified: full suite 393 passed; agents/csp/probability/learning_apps/search run clean with the shared bootstrap; modules import correctly from an unrelated cwd.
1 parent a84722e commit 58f003c

40 files changed

Lines changed: 102 additions & 258 deletions

aima/ipyviews.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
from IPython.display import HTML, display, clear_output
22
from collections import defaultdict
33
from aima.agents import PolygonObstacle
4+
import os
45
import time
56
import json
67
import copy
78
import __main__
89

10+
# repo root (the directory containing the `aima` package), so the bundled js/
11+
# files load regardless of the current working directory
12+
_AIMA_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
13+
914
# ______________________________________________________________________________
1015
# Continuous environment
1116

@@ -21,7 +26,7 @@
2126
</script>
2227
''' # noqa
2328

24-
with open('js/continuousworld.js', 'r') as js_file:
29+
with open(os.path.join(_AIMA_ROOT, 'js/continuousworld.js'), 'r') as js_file:
2530
_JS_CONTINUOUS_WORLD = js_file.read()
2631

2732

@@ -88,7 +93,7 @@ def show(self):
8893
</script>
8994
'''
9095

91-
with open('js/gridworld.js', 'r') as js_file:
96+
with open(os.path.join(_AIMA_ROOT, 'js/gridworld.js'), 'r') as js_file:
9297
_JS_GRID_WORLD = js_file.read()
9398

9499

aima/notebook_utils.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import os
12
import time
23
from collections import defaultdict
34
from inspect import getsource
@@ -16,6 +17,10 @@
1617
from aima.logic import parse_definite_clause, standardize_variables, unify_mm, subst
1718
from aima.search import GraphProblem, romania_map
1819

20+
# repo root (the directory containing the `aima` package), so cwd-relative
21+
# data/image paths resolve regardless of where a notebook is launched from
22+
_AIMA_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
23+
1924

2025
# ______________________________________________________________________________
2126
# Magic Words
@@ -109,6 +114,9 @@ def load_MNIST(path="aima-data/MNIST/Digits", fashion=False):
109114
if fashion:
110115
path = "aima-data/MNIST/Fashion"
111116

117+
if not os.path.isabs(path):
118+
path = os.path.join(_AIMA_ROOT, path)
119+
112120
plt.rcParams.update(plt.rcParamsDefault)
113121
plt.rcParams['figure.figsize'] = (10.0, 8.0)
114122
plt.rcParams['image.interpolation'] = 'nearest'
@@ -1122,7 +1130,7 @@ def plot_NQueens(solution):
11221130
"""
11231131
n = len(solution)
11241132
board = np.array([2 * int((i + j) % 2) for j in range(n) for i in range(n)]).reshape((n, n))
1125-
im = Image.open('images/queen_s.png')
1133+
im = Image.open(os.path.join(_AIMA_ROOT, 'images/queen_s.png'))
11261134
height = im.size[1]
11271135
im = np.array(im).astype(float) / 255
11281136
fig = plt.figure(figsize=(7, 7))

aima/perception.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""Perception (Chapter 24)"""
22

3+
import os
4+
35
import cv2
46
import keras
57
import matplotlib.pyplot as plt
@@ -11,6 +13,10 @@
1113

1214
from aima.utils import gaussian_kernel_2D
1315

16+
# repo root (the directory containing the `aima` package), so the bundled sample
17+
# images resolve regardless of the current working directory
18+
_AIMA_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
19+
1420

1521
# ____________________________________________________
1622
# 24.3 Early Image Processing Operators
@@ -366,7 +372,7 @@ def selective_search(image):
366372
:return list of bounding boxes, each element is in form of [x_min, y_min, x_max, y_max]
367373
"""
368374
if not image:
369-
im = cv2.imread("./images/stapler1-test.png")
375+
im = cv2.imread(os.path.join(_AIMA_ROOT, "images/stapler1-test.png"))
370376
elif isinstance(image, str):
371377
im = cv2.imread(image)
372378
else:

notebooks/agents.ipynb

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,7 @@
66
"metadata": {},
77
"outputs": [],
88
"source": [
9-
"# notebooks live under notebooks/; run from the repo root so that\n",
10-
"# `from aima import ...` and the cwd-relative aima-data/ and images/ paths resolve.\n",
11-
"import os, sys\n",
12-
"if os.path.basename(os.getcwd()) == 'notebooks':\n",
13-
" os.chdir('..')\n",
14-
"if os.getcwd() not in sys.path:\n",
15-
" sys.path.insert(0, os.getcwd())"
9+
"%run bootstrap.ipynb"
1610
]
1711
},
1812
{

notebooks/arc_consistency_heuristics.ipynb

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,7 @@
66
"metadata": {},
77
"outputs": [],
88
"source": [
9-
"# notebooks live under notebooks/; run from the repo root so that\n",
10-
"# `from aima import ...` and the cwd-relative aima-data/ and images/ paths resolve.\n",
11-
"import os, sys\n",
12-
"if os.path.basename(os.getcwd()) == 'notebooks':\n",
13-
" os.chdir('..')\n",
14-
"if os.getcwd() not in sys.path:\n",
15-
" sys.path.insert(0, os.getcwd())"
9+
"%run bootstrap.ipynb"
1610
]
1711
},
1812
{

notebooks/bootstrap.ipynb

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Bootstrap\n",
8+
"\n",
9+
"Shared setup for the notebooks: put the repository root (the directory containing the `aima` package) on `sys.path` so `from aima import ...` works regardless of where the notebook is launched. Each notebook runs this with a single `%run bootstrap.ipynb` cell."
10+
]
11+
},
12+
{
13+
"cell_type": "code",
14+
"execution_count": null,
15+
"metadata": {},
16+
"outputs": [],
17+
"source": [
18+
"import os, sys\n",
19+
"# walk up from the current directory to the repo root (the one holding `aima/`)\n",
20+
"_root = os.path.abspath(os.getcwd())\n",
21+
"while _root != os.path.dirname(_root) and not os.path.isdir(os.path.join(_root, 'aima')):\n",
22+
" _root = os.path.dirname(_root)\n",
23+
"if _root not in sys.path:\n",
24+
" sys.path.insert(0, _root)"
25+
]
26+
}
27+
],
28+
"metadata": {
29+
"kernelspec": {
30+
"display_name": "Python 3",
31+
"language": "python",
32+
"name": "python3"
33+
},
34+
"language_info": {
35+
"name": "python"
36+
}
37+
},
38+
"nbformat": 4,
39+
"nbformat_minor": 5
40+
}

notebooks/classical_planning_approaches.ipynb

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,7 @@
66
"metadata": {},
77
"outputs": [],
88
"source": [
9-
"# notebooks live under notebooks/; run from the repo root so that\n",
10-
"# `from aima import ...` and the cwd-relative aima-data/ and images/ paths resolve.\n",
11-
"import os, sys\n",
12-
"if os.path.basename(os.getcwd()) == 'notebooks':\n",
13-
" os.chdir('..')\n",
14-
"if os.getcwd() not in sys.path:\n",
15-
" sys.path.insert(0, os.getcwd())"
9+
"%run bootstrap.ipynb"
1610
]
1711
},
1812
{

notebooks/csp.ipynb

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,7 @@
66
"metadata": {},
77
"outputs": [],
88
"source": [
9-
"# notebooks live under notebooks/; run from the repo root so that\n",
10-
"# `from aima import ...` and the cwd-relative aima-data/ and images/ paths resolve.\n",
11-
"import os, sys\n",
12-
"if os.path.basename(os.getcwd()) == 'notebooks':\n",
13-
" os.chdir('..')\n",
14-
"if os.getcwd() not in sys.path:\n",
15-
" sys.path.insert(0, os.getcwd())"
9+
"%run bootstrap.ipynb"
1610
]
1711
},
1812
{

notebooks/dynamic_decision_network.ipynb

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,7 @@
66
"metadata": {},
77
"outputs": [],
88
"source": [
9-
"# notebooks live under notebooks/; run from the repo root so that\n",
10-
"# `from aima import ...` and the cwd-relative aima-data/ and images/ paths resolve.\n",
11-
"import os, sys\n",
12-
"if os.path.basename(os.getcwd()) == 'notebooks':\n",
13-
" os.chdir('..')\n",
14-
"if os.getcwd() not in sys.path:\n",
15-
" sys.path.insert(0, os.getcwd())"
9+
"%run bootstrap.ipynb"
1610
]
1711
},
1812
{

notebooks/expectation_maximization.ipynb

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,7 @@
66
"metadata": {},
77
"outputs": [],
88
"source": [
9-
"# notebooks live under notebooks/; run from the repo root so that\n",
10-
"# `from aima import ...` and the cwd-relative aima-data/ and images/ paths resolve.\n",
11-
"import os, sys\n",
12-
"if os.path.basename(os.getcwd()) == 'notebooks':\n",
13-
" os.chdir('..')\n",
14-
"if os.getcwd() not in sys.path:\n",
15-
" sys.path.insert(0, os.getcwd())"
9+
"%run bootstrap.ipynb"
1610
]
1711
},
1812
{

0 commit comments

Comments
 (0)