@@ -111,6 +111,30 @@ def values(self, var):
111
111
def __repr__ (self ):
112
112
return "P(%s)" % self .variables
113
113
114
+ #______________________________________________________________________________
115
+
116
+ def enumerate_joint_ask (X , e , P ):
117
+ """Return a probability distribution over the values of the variable X,
118
+ given the {var:val} observations e, in the JointProbDist P.
119
+ Works for Boolean variables only. [Fig. 13.4].
120
+
121
+ X is a string (variable name).
122
+ e is a dictionary of variable-name value pairs.
123
+ P is an instance of JointProbDist."""
124
+
125
+ Q = ProbDist (X ) # probability distribution for X, initially empty
126
+ Y = [v for v in P .variables if v != X and v not in e ] # hidden vars.
127
+ for xi in P .values (X ):
128
+ Q [xi ] = enumerate_joint (Y , extend (e , X , xi ), P )
129
+ return Q .normalize ()
130
+
131
+ def enumerate_joint (vars , values , P ):
132
+ "As in Fig 13.4, except x and e are already incorporated in values."
133
+ if not vars :
134
+ return P [values ]
135
+ Y , rest = vars [0 ], vars [1 :]
136
+ return sum ([enumerate_joint (rest , extend (values , Y , y ), P )
137
+ for y in P .values (Y )])
114
138
115
139
#______________________________________________________________________________
116
140
@@ -119,20 +143,20 @@ class BoolCpt:
119
143
"""Conditional probability table for a boolean (True/False)
120
144
random variable conditioned on its parents."""
121
145
122
- def __init__ (self , table_data ):
146
+ def __init__ (self , table ):
123
147
"""Initialize the table.
124
148
125
- table_data may have one of three forms, depending on the
149
+ table may have one of three forms, depending on the
126
150
number of parents:
127
151
128
- 1. If the variable has no parents, table_data MAY be
152
+ 1. If the variable has no parents, table MAY be
129
153
a single number (float), representing P(X = True).
130
154
131
- 2. If the variable has one parent, table_data MAY be
155
+ 2. If the variable has one parent, table MAY be
132
156
a dictionary containing items of the form v: p,
133
157
where p is P(X = True | parent = v).
134
158
135
- 3. If the variable has n parents, n > 1, table_data MUST be
159
+ 3. If the variable has n parents, n > 1, table MUST be
136
160
a dictionary containing items (v1, ..., vn): p,
137
161
where p is P(P = True | parent1 = v1, ..., parentn = vn).
138
162
@@ -144,24 +168,21 @@ def __init__(self, table_data):
144
168
>>> cpt = BoolCpt({(T, T): 0.2, (T, F): 0.3, (F, T): 0.5, (F, F): 0.7})
145
169
"""
146
170
# A little work here makes looking up values MUCH simpler
147
- # later on. We transform table_data into the standard form
171
+ # later on. We transform table into the standard form
148
172
# of a dictionary {(value, ...): number, ...} even if
149
173
# the tuple has just 0 or 1 value.
150
- if type (table_data ) == float : # no parents, 0-tuple
151
- self .table_data = {(): table_data }
152
- elif type (table_data ) == dict :
153
- keys = table_data .keys ()
154
- if type (keys [0 ]) == bool : # one parent, 1-tuple
155
- d = {}
156
- for k in keys :
157
- d [(k ,)] = table_data [k ]
158
- self .table_data = d
159
- elif type (keys [0 ]) == tuple : # normal case, n-tuple
160
- self .table_data = table_data
174
+ if isinstance (table , (float , int )): # no parents, 0-tuple
175
+ self .table = {(): table }
176
+ elif isinstance (table , dict ):
177
+ key = table .keys ()[0 ] if table else None
178
+ if isinstance (key , bool ): # one parent, 1-tuple
179
+ self .table = dict (((k ,), v ) for k , v in table .items ())
180
+ elif isinstance (key , tuple ): # normal case, n-tuple
181
+ self .table = table
161
182
else :
162
- raise Exception ("wrong key type: %s" % table_data )
183
+ raise Exception ("wrong key type: %s" % table )
163
184
else :
164
- raise Exception ("wrong table_data type: %s" % table_data )
185
+ raise Exception ("wrong table type: %s" % table )
165
186
166
187
def p (self , value , parent_vars , event ):
167
188
"""Return the conditional probability P(value | parent_vars =
@@ -210,7 +231,7 @@ def p_values(self, xvalue, parent_values):
210
231
>>> cpt.p_values(F, (F, F))
211
232
0.38
212
233
"""
213
- ptrue = self .table_data [parent_values ] # True or False
234
+ ptrue = self .table [parent_values ] # True or False
214
235
if xvalue :
215
236
return ptrue
216
237
else :
@@ -243,34 +264,9 @@ def event_values(event, vars):
243
264
"""
244
265
if isinstance (event , tuple ) and len (event ) == len (vars ):
245
266
return event
246
- return tuple ([event [parent ] for parent in vars ])
247
-
248
-
249
- #______________________________________________________________________________
250
-
251
- def enumerate_joint_ask (X , e , P ):
252
- """Return a probability distribution over the values of the variable X,
253
- given the {var:val} observations e, in the JointProbDist P.
254
- Works for Boolean variables only. [Fig. 13.4].
255
-
256
- X is a string (variable name).
257
- e is a dictionary of variable-name value pairs.
258
- P is an instance of JointProbDist."""
259
-
260
- Q = ProbDist (X ) # probability distribution for X, initially empty
261
- Y = [v for v in P .variables if v != X and v not in e ] # hidden vars.
262
- for xi in P .values (X ):
263
- ext = extend (e , X , xi ) # copies e and adds X: xi
264
- Q [xi ] = enumerate_joint (Y , ext , P )
265
- return Q .normalize ()
267
+ else :
268
+ return tuple ([event [var ] for var in vars ])
266
269
267
- def enumerate_joint (vars , values , P ):
268
- "As in Fig 13.4, except x and e are already incorporated in values."
269
- if not vars :
270
- return P [values ]
271
- Y = vars [0 ]; rest = vars [1 :]
272
- return sum ([enumerate_joint (rest , extend (values , Y , y ), P )
273
- for y in P .values (Y )])
274
270
275
271
#______________________________________________________________________________
276
272
@@ -290,7 +286,7 @@ def observe(self, var, val):
290
286
self .evidence [var ] = val
291
287
292
288
def variable_node (self , var ):
293
- """Returns the node for the variable named var.
289
+ """Return the node for the variable named var.
294
290
>>> burglary.variable_node('Burglary').variable
295
291
'Burglary'"""
296
292
for n in self .nodes :
@@ -299,7 +295,7 @@ def variable_node(self, var):
299
295
raise Exception ("No such variable: %s" % var )
300
296
301
297
def variables (self ):
302
- """Returns the list of names of the variables.
298
+ """Return the list of names of the variables.
303
299
>>> burglary.variables()
304
300
['Burglary', 'Earthquake', 'Alarm', 'JohnCalls', 'MaryCalls']"""
305
301
return [n .variable for n in self .nodes ]
@@ -332,7 +328,7 @@ def __init__(self, variable, parents, cpt):
332
328
333
329
#______________________________________________________________________________
334
330
335
- def enumeration_ask (X , e , bn ):
331
+ def enumeration_ask (X , e , bn ):
336
332
"""Returns a distribution of X given e from bayes net bn. [Fig. 14.9]
337
333
338
334
X is a string (variable name).
@@ -354,7 +350,7 @@ def enumeration_ask (X, e, bn):
354
350
# may be unspecified.
355
351
return Q .normalize ()
356
352
357
- def enumerate_all (vars , e , bn ):
353
+ def enumerate_all (vars , e , bn ):
358
354
"""Returns the probability that X = xi given e.
359
355
360
356
vars is a list of variables, the parents of X in bn.
@@ -365,24 +361,22 @@ def enumerate_all (vars, e, bn):
365
361
if vars == []:
366
362
return 1.0
367
363
else :
368
- Y = vars [0 ]
369
- rest = vars [1 :]
364
+ Y , rest = vars [0 ], vars [1 :]
370
365
371
366
Ynode = bn .variable_node (Y )
372
367
parents = Ynode .parents
373
368
cpt = Ynode .cpt
374
369
375
- if e . has_key ( Y ) :
370
+ if Y in e :
376
371
y = e [Y ]
377
372
cp = cpt .p (y , parents , e ) # P(y | parents(Y))
378
- result = cp * enumerate_all (rest , e , bn )
373
+ return cp * enumerate_all (rest , e , bn )
379
374
else :
380
375
result = 0
381
376
for y in bn .variable_values (Y ):
382
377
cp = cpt .p (y , parents , e ) # P(y | parents(Y))
383
378
result += cp * enumerate_all (rest , extend (e , Y , y ), bn )
384
-
385
- return result
379
+ return result
386
380
387
381
#______________________________________________________________________________
388
382
@@ -440,7 +434,7 @@ def prior_sample(bn):
440
434
441
435
#_______________________________________________________________________________
442
436
443
- def rejection_sampling (X , e , bn , N ):
437
+ def rejection_sampling (X , e , bn , N ):
444
438
"""Estimates probability distribution of X given evidence e
445
439
in BayesNet bn, using N samples. [Fig. 14.13]
446
440
@@ -473,7 +467,7 @@ def rejection_sampling (X, e, bn, N):
473
467
474
468
return ProbDist (X , counts )
475
469
476
- def consistent_with (sample , evidence ):
470
+ def consistent_with (sample , evidence ):
477
471
"""Returns True if sample is consistent with evidence, False otherwise.
478
472
479
473
sample is a dictionary of variable-name: value pairs.
@@ -498,7 +492,7 @@ def consistent_with (sample, evidence):
498
492
499
493
#_______________________________________________________________________________
500
494
501
- def likelihood_weighting (X , e , bn , N ):
495
+ def likelihood_weighting (X , e , bn , N ):
502
496
"""Returns an estimate of P(X | e). [Fig. 14.14]
503
497
504
498
Arguments:
@@ -527,7 +521,7 @@ def likelihood_weighting (X, e, bn, N):
527
521
528
522
return ProbDist (X , weights )
529
523
530
- def weighted_sample (bn , e ):
524
+ def weighted_sample (bn , e ):
531
525
"""Returns an event (a sample) and a weight."""
532
526
533
527
event = {} # boldface x in Fig. 14.14
0 commit comments