CS156
Chris Pollett
Feb 15, 2012
try: statement_block_0 except SomeError1 as error_name1: statement_block_1 #executed if a SomeError1 occurs except SomeError2 as error_name2: statement_block_2 ... finally: statement_block_n # always gets executed
try: f = open("file.txt", "r") except IOError as e: print e
raise RuntimeError("Something bad just happened")
class MyException(Exception): pass #now could use as: raise MyException("Whoa! A MyException occurred!") #more control can be had by overriding __init__ #here we define an exception taking two arguments class MyException2(Exception): def __init__(self, errno, msg): self.args = (errno, msg) self.errno = errno self.errmsg = msg raise MyException2(403, "Access Forbidden")
import div #notice not div.py a, b = div.divide(198, 15) #notice function in div.py have to be prefixed with div.
import div as foo #now foo is the prefix
from div import divide #from div import *; would import all functions print divide(198, 15)
def fact(n): "This function computes a factorial" #can use triple quoted strings if(n <= 1): return 1 else: return n * fact(n - 1)
print fact.__doc__
We argue the case where the nodes might form a DAG, the admissible case is similar.
Lemma. Suppose `h(n)` is a consistent heuristic, then the values of `f(n)` along any path are nondecreasing.
Proof. Suppose `n'` is a successor of `n`, then `g(n') = g(n) + c(n, a, n')` for some action `a` and we have:
`f(n') = g(n') + h(n') = g(n) + c(n, a, n') + h(n') mbox( (by consistency) ) geq g(n) + h(n) = f(n)`. QED.
Lemma. Whenever `A^star` selects a node `n` for expansion, the optimal path to that node has been found.
Proof. If this were not the case, there would have to be another frontier node `n'` on the optimal path from the start node to `n`. Here `n'` is on the frontier, as the frontier nodes of the graph always separate the unexplored region of the graph from the explored region, and if it was in the explored region we would have selected `n'` already on the path to `n` to get a lower solution. Since `f` is nondecreasing along any path, `n'` would have lower `f`-cost that `n` and would have been selected before `n`. QED.
It follows from these two lemmas that the sequence of nodes expanded by `A^star` is in non-decreasing order of `f(n)`. Hence, the first goal node selected for expansion must be optimal because `f` is the true cost for goal nodes and all later goal nodes will be at least as expensive. (QED optimality proof).
This algorithm is similar to recursive depth-first-search:
function RBF-SEARCH(problem) returns a solution, or failure return RBFS(problem, MAKE-NODE(problem.INITIAL_STATE), infty) function RBFS(problem, node, f_limit) returns a solution, or failure and a new f-cost limit if problem.GOAL-TEST(node.STATE) then return SOLUTION(node) successors := [] for each action in problem.ACTIONS(node.STATE) do add CHILD-NODE(problem, node, action) into successors if successors is empty then return failure, infty for each s in successors do /* update f with value from previous search, if any */ s.f = max(s.g + s.h, node.f) loop do best := the lowest f-value node in successors if best.f > f_limit then return failure, best.f alternative := the second-lowest f-value among successors result, best.f := RBFS(problem, best, min(f_limit, alternative)) if result != failure then return result