Created
July 4, 2015 17:32
-
-
Save mkowoods/79dd955a29584aee5801 to your computer and use it in GitHub Desktop.
Generic Lowes Cost Search with Examples
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ----------------- | |
# User Instructions | |
# | |
# In this problem, you will generalize the bridge problem | |
# by writing a function bridge_problem3, that makes a call | |
# to lowest_cost_search. | |
def bridge_problem3(here): | |
"""Find the fastest (least elapsed time) path to | |
the goal in the bridge problem.""" | |
# your code here | |
return lowest_cost_search(start = (frozenset(here) | frozenset(['light']), frozenset()), | |
successors = bsuccessors2, | |
is_goal = lambda state : state[0] == frozenset(), | |
action_cost = bcost) # <== your arguments here | |
# your code here if necessary | |
def lowest_cost_search(start, successors, is_goal, action_cost): | |
"""Return the lowest cost path, starting from start state, | |
and considering successors(state) => {state:action,...}, | |
that ends in a state for which is_goal(state) is true, | |
where the cost of a path is the sum of action costs, | |
which are given by action_cost(action).""" | |
Fail = [] | |
explored = set() # set of states we have visited | |
frontier = [ [start] ] # ordered list of paths we have blazed | |
while frontier: | |
path = frontier.pop(0) | |
state1 = final_state(path) | |
if is_goal(state1): | |
return path | |
explored.add(state1) | |
pcost = path_cost(path) | |
#print state1 | |
for (state, action) in successors(state1).items(): | |
if state not in explored: | |
total_cost = pcost + action_cost(action) | |
path2 = path + [(action, total_cost), state] | |
add_to_frontier(frontier, path2) | |
return Fail | |
def final_state(path): return path[-1] | |
def path_cost(path): | |
"The total cost of a path (which is stored in a tuple with the final action)." | |
if len(path) < 3: | |
return 0 | |
else: | |
action, total_cost = path[-2] | |
return total_cost | |
def add_to_frontier(frontier, path): | |
"Add path to frontier, replacing costlier path if there is one." | |
# (This could be done more efficiently.) | |
# Find if there is an old path to the final state of this path. | |
old = None | |
for i,p in enumerate(frontier): | |
if final_state(p) == final_state(path): | |
old = i | |
break | |
if old is not None and path_cost(frontier[old]) < path_cost(path): | |
return # Old path was better; do nothing | |
elif old is not None: | |
del frontier[old] # Old path was worse; delete it | |
## Now add the new path and re-sort | |
frontier.append(path) | |
frontier.sort(key=path_cost) | |
def bsuccessors2(state): | |
"""Return a dict of {state:action} pairs. A state is a (here, there) tuple, | |
where here and there are frozensets of people (indicated by their times) and/or | |
the light.""" | |
here, there = state | |
if 'light' in here: | |
return dict(((here - frozenset([a, b, 'light']), | |
there | frozenset([a, b, 'light'])), | |
(a, b, '->')) | |
for a in here if a is not 'light' | |
for b in here if b is not 'light') | |
else: | |
return dict(((here | frozenset([a, b, 'light']), | |
there - frozenset([a, b, 'light'])), | |
(a, b, '<-')) | |
for a in there if a is not 'light' | |
for b in there if b is not 'light') | |
def bcost(action): | |
"Returns the cost (a number) of an action in the bridge problem." | |
# An action is an (a, b, arrow) tuple; a and b are times; arrow is a string | |
a, b, arrow = action | |
return max(a, b) | |
def test(): | |
here = [1, 2, 5, 10] | |
assert bridge_problem3(here) == [ | |
(frozenset([1, 2, 'light', 10, 5]), frozenset([])), | |
((2, 1, '->'), 2), | |
(frozenset([10, 5]), frozenset([1, 2, 'light'])), | |
((2, 2, '<-'), 4), | |
(frozenset(['light', 10, 2, 5]), frozenset([1])), | |
((5, 10, '->'), 14), | |
(frozenset([2]), frozenset([1, 10, 5, 'light'])), | |
((1, 1, '<-'), 15), | |
(frozenset([1, 2, 'light']), frozenset([10, 5])), | |
((2, 1, '->'), 17), | |
(frozenset([]), frozenset([1, 10, 2, 5, 'light']))] | |
return 'test passes' | |
print 'output', bridge_problem3([1, 2, 5, 10]) | |
print test() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment