class HurricaneEvacuationSimulator(object): def __init__(self, graph_file, start_vertex): self.graph_file = graph_file self.world = World(graph_file=graph_file) self.deadline = self.world.get_deadline() self.shelter_tag = self.world.get_shelter_tag() # create agent self.start_vertex = start_vertex self.time = 0 # track time of the world self.evacuated = 0 # total number of people evacuated self.belief_space = self.init_belief_space() self.val_iterator = ValueIteration(self.belief_space, self.world) self.utilities = self.val_iterator.value_iteration() print(self.utilities.values()) # initialize the belief space for the graph def init_belief_space(self): bs = BeliefSpace(self.world, init_vertex=int(args.start_vertex)) bs.create_all_belief_states(self.start_vertex) return bs # generate all possible blockage combinations def all_blockage_instances(self): # edge that can be blocked maybe_blocked = map( lambda e: e.edge_num, filter(lambda e: e.prob_blockage > 0, self.world.get_edges(one_way=True))) blockages = set(product({True, False}, repeat=len(maybe_blocked))) return [dict(zip(maybe_blocked, blockage)) for blockage in blockages] def random_blockage(self): # blockable edges blockables = map( lambda e: e.edge_num, filter(lambda e: e.prob_blockage > 0, self.world.get_edges(one_way=True))) # NONE at first blockage_dict = {key: None for key in blockables} for e in blockage_dict: prob = self.world.get_edge_for_num(e).prob_blockage blockage_dict[e] = self.true_in_prob(prob) return blockage_dict # return 'True' in probability of 'prob' def true_in_prob(self, prob): rand = random.random() return True if rand <= prob else False def run_an_agent(self, times=10000): util_acc = 0.0 init_s = None for i in range(times): blockage_instance = self.random_blockage() init_states = self.belief_space.init_states # remove from init state/s init_state = filter( lambda d: self.consistent_state(d, blockage_instance), init_states)[0] init_s = init_state agent = PlanningAgent(world=self.world, belief_space=self.belief_space, utilities=self.utilities, \ init_state=init_state, init_vertex=self.start_vertex, blockage=blockage_instance) next_state = agent.state while not self.belief_space.goal_state(next_state) and not (len( next_state.successors) == 0): next_state = agent.do() util_acc += self.utilities[ next_state] #self.belief_space.states.index(next_state)] print('i: {}\nacc: {}'.format(i, util_acc)) #print('accumulated: {}'.format(util_acc)) print('average: {}'.format(util_acc / times)) print('init value: {}'.format( self.utilities[self.belief_space.states[0]])) def consistent_state(self, belief_state, blockage_instance): state_blocked = belief_state.blocked_edges for edge_num in state_blocked: if blockage_instance[edge_num] != state_blocked[edge_num]: return False return True
class Main(object): def __init__(self, graph_file): self.graph_file = graph_file self.world = World(graph_file=graph_file) self.deadline = self.world.get_deadline() self.bayes_network = BayesNetwork(world=self.world) self.reports = {} def clear_screen(self, stupid=False): if stupid: print('\n') * 100 else: os.system('cls' if os.name == 'nt' else 'clear') def get_numbers(self, prompt, smallest, biggest): while True: choice = raw_input(prompt).split() if 'exit' in choice or 'quit' in choice or 'q' in choice: exit() elif not any( int(x) < smallest or int(x) > biggest for x in choice) and not len(choice) == 0: # self.clear_screen(stupid=True) return choice else: # self.clear_screen(stupid=True) print('illegal input.') return False # get query evidence from user def prompt_query_evidence(self): all_reports = {} num_edges = len(self.world.get_edges(one_way=True)) num_vertices = len(self.world.get_vertices()) report_prompt = 'What would you like to report? \n 1. Flood\n 2. Blockage\n 3. Evacuees\n-------\n ' \ '4. No Flood\n 5. No Blockage\n 6. No Evacuees\n-------\n 7. Non-Blocked Path\n 8. Print Reasoning\n 9. Bonus\n 10. Reset\n choice: ' short_report_prompt = '\nAnother report?' blockage_prompt = 'report Blocking at edges : range-({},{}) '.format( 1, num_edges) flooding_prompt = 'report Flooding at vertices range-({},{}) : '.format( 1, num_vertices) evacuees_prompt = 'report Evacuees at vertices range-({},{}): '.format( 1, num_vertices) non_blockage_prompt = 'report NON Blocking at edges : range-({},{}) '.format( 1, num_edges) non_flooding_prompt = 'report NON Flooding at vertices range-({},{}) : '.format( 1, num_vertices) non_evacuees_prompt = 'report NON Evacuees at vertices range-({},{}): '.format( 1, num_vertices) iteration = 0 while True: iteration += 1 print( '\n----------------\nReported so far : \n{}\n----------------' .format(all_reports)) if iteration is 1: report_choice = int( self.get_numbers(report_prompt, smallest=1, biggest=10)[0]) else: report_choice = int( self.get_numbers(short_report_prompt, smallest=1, biggest=10)[0]) if report_choice == 1: floodings = set( self.get_numbers(flooding_prompt, smallest=1, biggest=num_vertices)) floodings = set(['flooding ' + str(num) for num in floodings]) for report in floodings: all_reports[report] = True elif report_choice == 2: blockages = set( self.get_numbers(blockage_prompt, smallest=1, biggest=num_edges)) blockages = set(['blockage ' + str(num) for num in blockages]) for report in blockages: all_reports[report] = True elif report_choice == 3: evacuees = set( self.get_numbers(evacuees_prompt, smallest=1, biggest=num_vertices)) evacuees = set(['evacuees ' + str(num) for num in evacuees]) for report in evacuees: all_reports[report] = True elif report_choice == 4: floodings = set( self.get_numbers(non_flooding_prompt, smallest=1, biggest=num_vertices)) floodings = set(['flooding ' + str(num) for num in floodings]) for report in floodings: all_reports[report] = False elif report_choice == 5: blockages = set( self.get_numbers(non_blockage_prompt, smallest=1, biggest=num_edges)) blockages = set(['blockage ' + str(num) for num in blockages]) for report in blockages: all_reports[report] = False elif report_choice == 6: evacuees = set( self.get_numbers(non_evacuees_prompt, smallest=1, biggest=num_vertices)) evacuees = set(['evacuees ' + str(num) for num in evacuees]) for report in evacuees: all_reports[report] = False elif report_choice == 7: print('Overall Reported: {}'.format(all_reports)) prompt = 'Enter a set of Edges as a path. range-({},{}) '.format( 1, num_edges) path = set( int(n) for n in self.get_numbers( prompt, smallest=1, biggest=num_edges)) if len(path) > 1: self.reports = all_reports p = self.get_probability_path_free(path) non_blocked = ', '.join( ['not blockage {}'.format(str(e)) for e in path]) given = self.evidence_as_string(all_reports) s = 'P({of} | {given} ) = {p}'.format(of=non_blocked, given=given, p=p) print(s) else: print('A single edge can computed normally') elif report_choice == 8: print('Overall Reported: {}'.format(all_reports)) self.reports = all_reports self.perform_reasoning() elif report_choice == 9: self.reports = all_reports print('Overall Reported: {}'.format(all_reports)) prompt = 'Enter a source Vertex and a Destination Vertex. range-({},{}) '.format( 1, num_vertices) user_input = [ int(n) for n in self.get_numbers( prompt, smallest=1, biggest=num_vertices) ] if len(user_input) is not 2: print('usage : <source> <destination>') else: self.reports = all_reports self.do_bonus(source=user_input[0], destination=user_input[1]) elif report_choice == 10: all_reports = dict() # print the network def print_network(self): self.bayes_network.print_network() def perform_reasoning(self): self.query_type('evacuees') self.query_type('flooding') self.query_type('blockage') def query_type(self, node_type, for_print=True): nodes = self.bayes_network.get_nodes_of_type(node_type) vals = [] for node in nodes: # self.enumerate_prob(node) if node.node_type != 'blockage': vals.append((node.get_vertex().tag, self.enumerate_prob(node))) else: vals.append( (node.get_edge().edge_num, self.enumerate_prob(node))) return vals def do_bonus(self, source, destination): paths = self.world.all_paths(source=source, destination=destination) probabilities = [self.get_probability_path_free(p) for p in paths] print( 'Printing the Probability of free from blockages - path from {} to {} :' .format(source, destination)) min_path = ([], 0.0) for (path, prob) in zip(paths, probabilities): if prob >= min_path[1]: min_path = (path, prob) print('Path: {} , Probability(free) = {}'.format(path, prob)) print('\n===========================\n') if min_path[1] == 0.0: print('all paths from {} to {} are blocked with probability 1'. format(source, destination)) else: print('Best path is : {} with probability {}'.format( min_path[0], min_path[1])) # and print def enumerate_prob(self, node): enumerator = Enumerator(query_var=node, evidence=self.reports, network=self.bayes_network) p = enumerator.pretty_string(query_value=True) p_val = enumerator.enumeration_ask() s = p + str(p_val[0]) print(s) # print("\n") return p_val[0] def get_probability_path_free(self, path): reported_evidence = self.reports.copy() query_vars = filter(lambda n: n.get_edge().edge_num in path, self.bayes_network.get_nodes_of_type('blockage')) multi_query = MultiQuery(query_vars=query_vars, evidence=reported_evidence, network=self.bayes_network) # vars_true is False - we want blockages to be false. p = multi_query.query_to_value(vars_true=False) return p def evidence_as_string(self, evidence): s = '' for e in evidence.keys(): if s != '': s += ',' if evidence[e]: s += e else: s += 'not ' + e return s