Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0ad4c07

Browse files
dmeoliantmarakis
authored andcommitted
added Viterbi algorithm (aimacode#1099)
* changed queue to set in AC3 Changed queue to set in AC3 (as in the pseudocode of the original algorithm) to reduce the number of consistency-check due to the redundancy of the same arcs in queue. For example, on the harder1 configuration of the Sudoku CSP the number consistency-check has been reduced from 40464 to 12562! * re-added test commented by mistake * added the mentioned AC4 algorithm for constraint propagation AC3 algorithm has non-optimal worst case time-complexity O(cd^3 ), while AC4 algorithm runs in O(cd^2) worst case time * added doctest in Sudoku for AC4 and and the possibility of choosing the constant propagation algorithm in mac inference * removed useless doctest for AC4 in Sudoku because AC4's tests are already present in test_csp.py * added map coloring SAT problems * fixed typo errors and removed unnecessary brackets * reformulated the map coloring problem * Revert "reformulated the map coloring problem" This reverts commit 20ab0e5. * Revert "fixed typo errors and removed unnecessary brackets" This reverts commit f743146. * Revert "added map coloring SAT problems" This reverts commit 9e0fa55. * Revert "removed useless doctest for AC4 in Sudoku because AC4's tests are already present in test_csp.py" This reverts commit b3cd24c. * Revert "added doctest in Sudoku for AC4 and and the possibility of choosing the constant propagation algorithm in mac inference" This reverts commit 6986247. * Revert "added the mentioned AC4 algorithm for constraint propagation" This reverts commit 03551fb. * added map coloring SAT problem * fixed build error * Revert "added map coloring SAT problem" This reverts commit 93af259. * Revert "fixed build error" This reverts commit 6641c2c. * added map coloring SAT problem * removed redundant parentheses * added Viterbi algorithm
1 parent fd52c72 commit 0ad4c07

File tree

2 files changed

+139
-77
lines changed

2 files changed

+139
-77
lines changed

probability.py

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,23 @@
1313
from collections import defaultdict
1414
from functools import reduce
1515

16+
1617
# ______________________________________________________________________________
1718

1819

1920
def DTAgentProgram(belief_state):
2021
"""A decision-theoretic agent. [Figure 13.1]"""
22+
2123
def program(percept):
2224
belief_state.observe(program.action, percept)
2325
program.action = argmax(belief_state.actions(),
2426
key=belief_state.expected_outcome_utility)
2527
return program.action
28+
2629
program.action = None
2730
return program
2831

32+
2933
# ______________________________________________________________________________
3034

3135

@@ -132,6 +136,7 @@ def event_values(event, variables):
132136
else:
133137
return tuple([event[var] for var in variables])
134138

139+
135140
# ______________________________________________________________________________
136141

137142

@@ -160,6 +165,7 @@ def enumerate_joint(variables, e, P):
160165
return sum([enumerate_joint(rest, extend(e, Y, y), P)
161166
for y in P.values(Y)])
162167

168+
163169
# ______________________________________________________________________________
164170

165171

@@ -378,6 +384,7 @@ def __repr__(self):
378384
('MaryCalls', 'Alarm', {T: 0.70, F: 0.01})
379385
])
380386

387+
381388
# ______________________________________________________________________________
382389

383390

@@ -409,6 +416,7 @@ def enumerate_all(variables, e, bn):
409416
return sum(Ynode.p(y, e) * enumerate_all(rest, extend(e, Y, y), bn)
410417
for y in bn.variable_values(Y))
411418

419+
412420
# ______________________________________________________________________________
413421

414422

@@ -498,6 +506,7 @@ def all_events(variables, bn, e):
498506
for x in bn.variable_values(X):
499507
yield extend(e1, X, x)
500508

509+
501510
# ______________________________________________________________________________
502511

503512
# [Figure 14.12a]: sprinkler network
@@ -510,6 +519,7 @@ def all_events(variables, bn, e):
510519
('WetGrass', 'Sprinkler Rain',
511520
{(T, T): 0.99, (T, F): 0.90, (F, T): 0.90, (F, F): 0.00})])
512521

522+
513523
# ______________________________________________________________________________
514524

515525

@@ -521,6 +531,7 @@ def prior_sample(bn):
521531
event[node.variable] = node.sample(event)
522532
return event
523533

534+
524535
# _________________________________________________________________________
525536

526537

@@ -547,6 +558,7 @@ def consistent_with(event, evidence):
547558
return all(evidence.get(k, v) == v
548559
for k, v in event.items())
549560

561+
550562
# _________________________________________________________________________
551563

552564

@@ -579,6 +591,7 @@ def weighted_sample(bn, e):
579591
event[Xi] = node.sample(event)
580592
return event, w
581593

594+
582595
# _________________________________________________________________________
583596

584597

@@ -612,6 +625,7 @@ def markov_blanket_sample(X, e, bn):
612625
# (assuming a Boolean variable here)
613626
return probability(Q.normalize()[True])
614627

628+
615629
# _________________________________________________________________________
616630

617631

@@ -655,7 +669,7 @@ def forward_backward(HMM, ev, prior):
655669

656670
fv = [[0.0, 0.0] for _ in range(len(ev))]
657671
b = [1.0, 1.0]
658-
bv = [b] # we don't need bv; but we will have a list of all backward messages here
672+
bv = [b] # we don't need bv; but we will have a list of all backward messages here
659673
sv = [[0, 0] for _ in range(len(ev))]
660674

661675
fv[0] = prior
@@ -671,6 +685,33 @@ def forward_backward(HMM, ev, prior):
671685

672686
return sv
673687

688+
689+
def viterbi(HMM, ev, prior):
690+
"""[Figure 15.5]
691+
Viterbi algorithm to find the most likely sequence. Computes the best path,
692+
given an HMM model and a sequence of observations."""
693+
t = len(ev)
694+
ev.insert(0, None)
695+
696+
m = [[0.0, 0.0] for _ in range(len(ev) - 1)]
697+
698+
# the recursion is initialized with m1 = forward(P(X0), e1)
699+
m[0] = forward(HMM, prior, ev[1])
700+
701+
for i in range(1, t):
702+
m[i] = element_wise_product(HMM.sensor_dist(ev[i + 1]),
703+
[max(element_wise_product(HMM.transition_model[0], m[i - 1])),
704+
max(element_wise_product(HMM.transition_model[1], m[i - 1]))])
705+
706+
path = [0.0] * (len(ev) - 1)
707+
# the construction of the most likely sequence starts in the final state with the largest probability,
708+
# and runs backwards; the algorithm needs to store for each xt its best predecessor xt-1
709+
for i in range(t, -1, -1):
710+
path[i - 1] = max(m[i - 1])
711+
712+
return path
713+
714+
674715
# _________________________________________________________________________
675716

676717

@@ -702,6 +743,7 @@ def fixed_lag_smoothing(e_t, HMM, d, ev, t):
702743
else:
703744
return None
704745

746+
705747
# _________________________________________________________________________
706748

707749

@@ -742,13 +784,15 @@ def particle_filtering(e, N, HMM):
742784

743785
return s
744786

787+
745788
# _________________________________________________________________________
746-
## TODO: Implement continuous map for MonteCarlo similar to Fig25.10 from the book
789+
# TODO: Implement continuous map for MonteCarlo similar to Fig25.10 from the book
747790

748791

749792
class MCLmap:
750793
"""Map which provides probability distributions and sensor readings.
751794
Consists of discrete cells which are either an obstacle or empty"""
795+
752796
def __init__(self, m):
753797
self.m = m
754798
self.nrows = len(m)
@@ -772,7 +816,7 @@ def ray_cast(self, sensor_num, kin_state):
772816
# 0
773817
# 3R1
774818
# 2
775-
delta = ((sensor_num % 2 == 0)*(sensor_num - 1), (sensor_num % 2 == 1)*(2 - sensor_num))
819+
delta = ((sensor_num % 2 == 0) * (sensor_num - 1), (sensor_num % 2 == 1) * (2 - sensor_num))
776820
# sensor direction changes based on orientation
777821
for _ in range(orient):
778822
delta = (delta[1], -delta[0])
@@ -790,9 +834,9 @@ def ray_cast(sensor_num, kin_state, m):
790834
return m.ray_cast(sensor_num, kin_state)
791835

792836
M = len(z)
793-
W = [0]*N
794-
S_ = [0]*N
795-
W_ = [0]*N
837+
W = [0] * N
838+
S_ = [0] * N
839+
W_ = [0] * N
796840
v = a['v']
797841
w = a['w']
798842

0 commit comments

Comments
 (0)