Skip to content

Commit 64fa05b

Browse files
SnShinenorvig
authored andcommitted
Removes obsolete Fig dictionary and modifies the codebase accordingly (aimacode#208)
* removes obsolete Fig dictionary from utils.py * modified rl notebook according to the new Figure conventions * removes 'import Fig' and changed the names of Figures * fixes a small error (by me) in executing the cells in rl notebook
1 parent df97b76 commit 64fa05b

8 files changed

Lines changed: 79 additions & 73 deletions

File tree

learning.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from utils import (
44
removeall, unique, product, argmax, argmax_random_tie, mean, isclose,
55
dotproduct, vector_add, scalar_vector_product, weighted_sample_with_replacement,
6-
weighted_sampler, num_or_str, normalize, clip, sigmoid, print_table, DataFile, Fig
6+
weighted_sampler, num_or_str, normalize, clip, sigmoid, print_table, DataFile
77
)
88

99
import copy
@@ -886,7 +886,11 @@ def T(attrname, branches):
886886
for value, child in list(branches.items()))
887887
return DecisionFork(restaurant.attrnum(attrname), attrname, branches)
888888

889-
Fig[18, 2] = T('Patrons',
889+
""" [Figure 18.2]
890+
A decision tree for deciding whether to wait for a table at a hotel.
891+
"""
892+
893+
waiting_decision_tree = T('Patrons',
890894
{'None': 'No', 'Some': 'Yes', 'Full':
891895
T('WaitEstimate',
892896
{'>60': 'No', '0-10': 'Yes',
@@ -910,7 +914,7 @@ def SyntheticRestaurant(n=20):
910914
"Generate a DataSet with n examples."
911915
def gen():
912916
example = list(map(random.choice, restaurant.values))
913-
example[restaurant.target] = Fig[18, 2](example)
917+
example[restaurant.target] = waiting_decision_tree(example)
914918
return example
915919
return RestaurantDataSet([gen() for i in range(n)])
916920

logic.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
from utils import (
3535
removeall, unique, first, every, argmax, probability, num_or_str,
36-
isnumber, issequence, Symbol, Expr, expr, subexpressions, implies, Fig
36+
isnumber, issequence, Symbol, Expr, expr, subexpressions, implies
3737
)
3838
import agents
3939

@@ -499,7 +499,7 @@ def clauses_with_premise(self, p):
499499
def pl_fc_entails(KB, q):
500500
"""Use forward chaining to see if a PropDefiniteKB entails symbol q.
501501
[Fig. 7.15]
502-
>>> pl_fc_entails(Fig[7,15], expr('Q'))
502+
>>> pl_fc_entails(horn_clauses_KB, expr('Q'))
503503
True
504504
"""
505505
count = dict([(c, len(conjuncts(c.args[0]))) for c in KB.clauses
@@ -518,13 +518,18 @@ def pl_fc_entails(KB, q):
518518
agenda.append(c.args[1])
519519
return False
520520

521-
# Wumpus World example [Fig. 7.13]
522-
Fig[7, 13] = expr("(B11 <=> (P12 | P21)) & ~B11")
521+
""" [Figure 7.13]
522+
Simple inference in a wumpus world example
523+
"""
524+
wumpus_world_inference = expr("(B11 <=> (P12 | P21)) & ~B11")
525+
523526

524-
# Propositional Logic Forward Chaining example [Fig. 7.16]
525-
Fig[7, 15] = PropDefiniteKB()
527+
""" [Figure 7.16]
528+
Propositional Logic Forward Chaining example
529+
"""
530+
horn_clauses_KB = PropDefiniteKB()
526531
for s in "P==>Q; (L&M)==>P; (B&L)==>M; (A&P)==>L; (A&B)==>L; A;B".split(';'):
527-
Fig[7, 15].tell(expr(s))
532+
horn_clauses_KB.tell(expr(s))
528533

529534
# ______________________________________________________________________________
530535
# DPLL-Satisfiable [Fig. 7.17]
@@ -690,7 +695,7 @@ def SAT_plan(init, transition, goal, t_max, SAT_solver=dpll_satisfiable):
690695
def translate_to_SAT(init, transition, goal, time):
691696
clauses = []
692697
states = [state for state in transition]
693-
698+
694699
#Symbol claiming state s at time t
695700
state_counter = itertools.count()
696701
for s in states:

mdp.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
dictionary of {state:number} pairs. We then define the value_iteration
77
and policy_iteration algorithms."""
88

9-
from utils import argmax, vector_add, print_table, Fig
9+
from utils import argmax, vector_add, print_table
1010
from grid import orientations, turn_right, turn_left
1111

1212
import random
@@ -97,8 +97,10 @@ def to_arrows(self, policy):
9797
dict([(s, chars[a]) for (s, a) in list(policy.items())]))
9898

9999
# ______________________________________________________________________________
100-
101-
Fig[17, 1] = GridMDP([[-0.04, -0.04, -0.04, +1],
100+
""" [Figure 17.1]
101+
A 4x3 grid environment that presents the agent with a sequential decision problem.
102+
"""
103+
sequential_decision_environment = GridMDP([[-0.04, -0.04, -0.04, +1],
102104
[-0.04, None, -0.04, -1],
103105
[-0.04, -0.04, -0.04, -0.04]],
104106
terminals=[(3, 2), (3, 1)])
@@ -163,17 +165,17 @@ def policy_evaluation(pi, U, mdp, k=20):
163165
return U
164166

165167
__doc__ += """
166-
>>> pi = best_policy(Fig[17,1], value_iteration(Fig[17,1], .01))
168+
>>> pi = best_policy(sequential_decision_environment, value_iteration(sequential_decision_environment, .01))
167169
168-
>>> Fig[17,1].to_arrows(pi)
170+
>>> sequential_decision_environment.to_arrows(pi)
169171
[['>', '>', '>', '.'], ['^', None, '^', '.'], ['^', '>', '^', '<']]
170172
171-
>>> print_table(Fig[17,1].to_arrows(pi))
173+
>>> print_table(sequential_decision_environment.to_arrows(pi))
172174
> > > .
173175
^ None ^ .
174176
^ > ^ <
175177
176-
>>> print_table(Fig[17,1].to_arrows(policy_iteration(Fig[17,1])))
178+
>>> print_table(sequential_decision_environment.to_arrows(policy_iteration(sequential_decision_environment)))
177179
> > > .
178180
^ None ^ .
179181
^ > ^ <

rl.ipynb

Lines changed: 18 additions & 18 deletions
Large diffs are not rendered by default.

search.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,7 @@ def distance_to_node(n):
700700
g.connect(node, neighbor, int(d))
701701
return g
702702

703-
""" [Fig. 3.2]
703+
""" [Figure 3.2]
704704
Simplified road map of Romania
705705
"""
706706
romania_map = UndirectedGraph(dict(
@@ -726,7 +726,7 @@ def distance_to_node(n):
726726
Sibiu=(207, 457), Timisoara=(94, 410), Urziceni=(456, 350),
727727
Vaslui=(509, 444), Zerind=(108, 531))
728728

729-
""" [Fig. 4.9]
729+
""" [Figure 4.9]
730730
Eight possible states of the vacumm world
731731
Each state is represented as
732732
* "State of the left room" "State of the right room" "Room in which the agent is present"
@@ -750,9 +750,8 @@ def distance_to_node(n):
750750
State_8 = dict(Suck = ['State_8', 'State_6'], Left = ['State_7'])
751751
))
752752

753-
""" [Fig. 4.23]
753+
""" [Figure 4.23]
754754
One-dimensional state space Graph
755-
756755
"""
757756
one_dim_state_space = Graph(dict(
758757
State_1 = dict(Right = 'State_2'),
@@ -770,7 +769,9 @@ def distance_to_node(n):
770769
State_5 = 4,
771770
State_6 = 3)
772771

773-
# Principal states and territories of Australia
772+
""" [Figure 6.1]
773+
Principal states and territories of Australia
774+
"""
774775
australia_map = UndirectedGraph(dict(
775776
T=dict(),
776777
SA=dict(WA=1, NT=1, Q=1, NSW=1, V=1),

tests/test_logic.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import pytest
22
from logic import *
3-
from utils import InfixOp, expr_handle_infix_ops, Fig, count, implies, equiv
3+
from utils import InfixOp, expr_handle_infix_ops, count, implies, equiv
44

55

66
def test_expr():
@@ -109,15 +109,15 @@ def test_dpll():
109109
== {B: False, C: True, A: True, F: False, D: True, E: False})
110110
assert dpll_satisfiable(A&~B) == {A: True, B: False}
111111
assert dpll_satisfiable(P&~P) == False
112-
112+
113113

114114
def test_unify():
115115
assert unify(x, x, {}) == {}
116116
assert unify(x, 3, {}) == {x: 3}
117117

118118
def test_pl_fc_entails():
119-
assert pl_fc_entails(Fig[7,15], expr('Q'))
120-
assert not pl_fc_entails(Fig[7,15], expr('SomethingSilly'))
119+
assert pl_fc_entails(horn_clauses_KB, expr('Q'))
120+
assert not pl_fc_entails(horn_clauses_KB, expr('SomethingSilly'))
121121

122122
def test_tt_entails():
123123
assert tt_entails(P & Q, Q)
@@ -146,7 +146,7 @@ def test_move_not_inwards():
146146
assert repr(move_not_inwards(~(~(A | ~B) | ~~C))) == '((A | ~B) & ~C)'
147147

148148
def test_to_cnf():
149-
assert (repr(to_cnf(Fig[7, 13] & ~expr('~P12'))) ==
149+
assert (repr(to_cnf(wumpus_world_inference & ~expr('~P12'))) ==
150150
"((~P12 | B11) & (~P21 | B11) & (P12 | P21 | ~B11) & ~B11 & P12)")
151151
assert repr(to_cnf((P&Q) | (~P & ~Q))) == '((~P | P) & (~Q | P) & (~P | Q) & (~Q | Q))'
152152
assert repr(to_cnf("B <=> (P1 | P2)")) == '((~P1 | B) & (~P2 | B) & (P1 | P2 | ~B))'
@@ -203,7 +203,7 @@ def test_SAT_plan():
203203
transition = {(0, 0):{'Right': (0, 1), 'Down': (1, 0)},
204204
(0, 1):{'Left': (1, 0), 'Down': (1, 1)},
205205
(1, 0):{'Right': (1, 0), 'Up': (1, 0), 'Left': (1, 0), 'Down': (1, 0)},
206-
(1, 1):{'Left': (1, 0), 'Up': (0, 1)}}
206+
(1, 1):{'Left': (1, 0), 'Up': (0, 1)}}
207207
assert SAT_plan((0, 0), transition, (1, 1), 4) == ['Right', 'Down']
208208

209209

tests/test_mdp.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from mdp import * # noqa
33

44
def test_value_iteration():
5-
assert value_iteration(Fig[17, 1], .01) == {(3, 2): 1.0, (3, 1): -1.0,
5+
assert value_iteration(sequential_decision_environment, .01) == {(3, 2): 1.0, (3, 1): -1.0,
66
(3, 0): 0.12958868267972745, (0, 1): 0.39810203830605462,
77
(0, 2): 0.50928545646220924, (1, 0): 0.25348746162470537,
88
(0, 0): 0.29543540628363629, (1, 2): 0.64958064617168676,
@@ -11,14 +11,14 @@ def test_value_iteration():
1111

1212

1313
def test_policy_iteration():
14-
assert policy_iteration(Fig[17, 1]) == {(0, 0): (0, 1), (0, 1): (0, 1), (0, 2): (1, 0),
14+
assert policy_iteration(sequential_decision_environment) == {(0, 0): (0, 1), (0, 1): (0, 1), (0, 2): (1, 0),
1515
(1, 0): (1, 0), (1, 2): (1, 0),
1616
(2, 0): (0, 1), (2, 1): (0, 1), (2, 2): (1, 0),
1717
(3, 0): (-1, 0), (3, 1): None, (3, 2): None}
1818

1919

2020
def test_best_policy():
21-
pi = best_policy(Fig[17, 1], value_iteration(Fig[17, 1], .01))
22-
assert Fig[17, 1].to_arrows(pi) == [['>', '>', '>', '.'],
21+
pi = best_policy(sequential_decision_environment, value_iteration(sequential_decision_environment, .01))
22+
assert sequential_decision_environment.to_arrows(pi) == [['>', '>', '>', '.'],
2323
['^', None, '^', '.'],
2424
['^', '>', '^', '<']]

utils.py

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def shuffled(iterable):
8181
"Randomly shuffle a copy of iterable."
8282
items = list(iterable)
8383
random.shuffle(items)
84-
return items
84+
return items
8585

8686

8787

@@ -345,16 +345,16 @@ def unimplemented():
345345
# See https://docs.python.org/3/reference/expressions.html#operator-precedence
346346
# See https://docs.python.org/3/reference/datamodel.html#special-method-names
347347

348-
class Expr(object):
348+
class Expr(object):
349349
"""A mathematical expression with an operator and 0 or more arguments.
350350
op is a str like '+' or 'sin'; args are Expressions.
351351
Expr('x') or Symbol('x') creates a symbol (a nullary Expr).
352352
Expr('-', x) creates a unary; Expr('+', x, 1) creates a binary."""
353-
354-
def __init__(self, op, *args):
353+
354+
def __init__(self, op, *args):
355355
self.op = str(op)
356356
self.args = args
357-
357+
358358
# Operator overloads
359359
def __neg__(self): return Expr('-', self)
360360
def __pos__(self): return Expr('+', self)
@@ -374,10 +374,10 @@ def __matmul__(self, rhs): return Expr('@', self, rhs)
374374

375375
def __or__(self, rhs):
376376
if isinstance(rhs, Expression) :
377-
return Expr('|', self, rhs)
377+
return Expr('|', self, rhs)
378378
else:
379379
return NotImplemented # So that InfixOp can handle it
380-
380+
381381
# Reverse operator overloads
382382
def __radd__(self, lhs): return Expr('+', lhs, self)
383383
def __rsub__(self, lhs): return Expr('-', lhs, self)
@@ -393,20 +393,20 @@ def __rlshift__(self, lhs): return Expr('<<', lhs, self)
393393
def __rtruediv__(self, lhs): return Expr('/', lhs, self)
394394
def __rfloordiv__(self, lhs): return Expr('//', lhs, self)
395395
def __rmatmul__(self, lhs): return Expr('@', lhs, self)
396-
397-
def __call__(self, *args):
396+
397+
def __call__(self, *args):
398398
"Call: if 'f' is a Symbol, then f(0) == Expr('f', 0)."
399399
return Expr(self.op, *args)
400400

401401
# Equality and repr
402-
def __eq__(self, other):
402+
def __eq__(self, other):
403403
"'x == y' evaluates to True or False; does not build an Expr."
404-
return (isinstance(other, Expr)
405-
and self.op == other.op
404+
return (isinstance(other, Expr)
405+
and self.op == other.op
406406
and self.args == other.args)
407-
407+
408408
def __hash__(self): return hash(self.op) ^ hash(self.args)
409-
409+
410410
def __repr__(self):
411411
op = self.op
412412
args = [str(arg) for arg in self.args]
@@ -450,7 +450,7 @@ def arity(expression):
450450

451451
class InfixOp:
452452
"""Allow 'P |implies| Q, where P, Q are Exprs and implies is an InfixOp."""
453-
def __init__(self, op, lhs=None): self.op, self.lhs = op, lhs
453+
def __init__(self, op, lhs=None): self.op, self.lhs = op, lhs
454454
def __call__(self, lhs, rhs): return Expr(self.op, lhs, rhs)
455455
def __or__(self, rhs): return Expr(self.op, self.lhs, rhs)
456456
def __ror__(self, lhs): return InfixOp(self.op, lhs)
@@ -489,7 +489,7 @@ class defaultkeydict(collections.defaultdict):
489489
def __missing__(self, key):
490490
self[key] = result = self.default_factory(key)
491491
return result
492-
492+
493493

494494
# ______________________________________________________________________________
495495
# Queues: Stack, FIFOQueue, PriorityQueue
@@ -591,9 +591,3 @@ def __delitem__(self, key):
591591
for i, (value, item) in enumerate(self.A):
592592
if item == key:
593593
self.A.pop(i)
594-
595-
# Fig: The idea is we can define things like Fig[3,10] = ...
596-
# TODO: However, this is deprecated, let's remove it,
597-
# and instead have a comment like # Figure 3.10
598-
599-
Fig = {}

0 commit comments

Comments
 (0)