Exemplo n.º 1
0
 def __init__(self, graph_file, agent_file, f):
     self.graph_file = graph_file
     self.time = 0  # track time of the world
     self.evacuated = 0  # total number of people evacuated
     self.f_constant = f
     self.agents_history = []  # search paths of smart agents
     world = World(graph_file=graph_file, k=self.prompt_k())
     self.deadline = world.get_deadline()
     agents = self.get_agents_data(agent_file=agent_file, world=world)
     super(HurricaneEvacuationSimulator, self).__init__(state=world,
                                                        agents=agents)
     self.vandal_records = {}  # pairs of <edge>:<time-of-blocking>
Exemplo n.º 2
0
class HurricaneGameSimulator(Simulator):
    def __init__(self,
                 graph_file,
                 agent_file,
                 cutoff_depth,
                 ping_pong,
                 mode='adversarial'):
        self.ping_pong = ping_pong
        self.graph_file = graph_file
        self.time = 0  # track time of the world
        self.evacuated = 0  # total number of people evacuated
        self.agents_history = []  # search paths of smart agents
        self.cutoff_depth = int(cutoff_depth)
        self.world = World(graph_file=graph_file, k=self.prompt_k())
        self.deadline = self.world.get_deadline()
        self.agents = self.get_agents_data(agent_file=agent_file,
                                           world=self.world)
        self.init_state = self.create_init_states(self.world, self.agents)
        self.mode = mode
        if not ping_pong:
            self.game_tree = GameTree(self.init_state,
                                      self.world,
                                      self.agents,
                                      mode=mode,
                                      cutoff_depth=self.cutoff_depth)
        super(HurricaneGameSimulator, self).__init__(state=self.world,
                                                     agents=self.agents)

    # return num of actions for each agent
    def get_all_actions(self):
        agent_actions = {}
        for agent in self.agents:
            agent_actions[agent.name] = len(agent.get_actions())
        return agent_actions

    # return number of all people evacuated for ALL agents
    def get_total_evacuated(self):
        acc = 0
        for agent in self.agents:
            acc += agent.get_evacuated()
        return acc

    # move agent to the destination
    def move_agent_to(self, agent, dest, edge):
        agent.vertex = dest  # move the agent
        moving_time = self.calculate_price(agent=agent, edge=edge)
        self.time += moving_time  # add total time of simulator
        # if deadline has passed, return
        if self.time > self.deadline:
            return False
        if agent.observation.is_house(agent.vertex):
            agent.pick_up()
        elif agent.get_people_in_car() > 0:  # if in a Shelter vertex
            agent.drop_off()
        return True

    # time it takes to traverse on 'edge'
    def calculate_price(self, agent, edge):
        w = edge.weight
        k = self.state.get_slow_down()
        p = agent.get_people_in_car()
        return w * (1 + k * p)

    # Do a 1step for a Human & Greedy Agent
    def do_agent(self, agent):
        next_move = agent.do()  # do action for Human Agent
        agent.add_action(next_move)
        if next_move == 'NOP':
            self.time += 1
        else:  # Traverse
            if next_move[0].upper() != 'T':
                raise Exception('Unknown action')
            dest = int(next_move[1:])  # number of the destination vertex
            edge_to_traverse = self.state.get_edge(agent.vertex, dest)
            return self.move_agent_to(agent=agent,
                                      edge=edge_to_traverse,
                                      dest=dest)

    # input in the format of : H1 G3;  <Type|Vertex>
    def get_agents_data(self, world, agent_file=None):
        num_human = 0
        num_gamers = 0
        agents = []
        if agent_file is not None:
            with open(agent_file) as agents_file:
                for line in agents_file.readlines():
                    for agent_symbol in line.split():
                        vertex_number = int(agent_symbol[1:])
                        choice = 'MAX' if len(agents) == 0 else 'MIN'
                        if agent_symbol.upper().startswith('H'):
                            name = 'Human-{}'.format(str(num_human))
                            agent = Human(world=world,
                                          name=name,
                                          init_vertex=vertex_number,
                                          choice=choice)
                            agents.append(agent)
                            num_human += 1
                        elif agent_symbol.upper().startswith('G'):

                            choice = 'MAX' if len(agents) == 0 else 'MIN'
                            name = 'Gamer-{}'.format(str(num_gamers))
                            agent = GameTreeAgent(world=world,
                                                  name=name,
                                                  init_vertex=vertex_number,
                                                  choice=choice)
                            agents.append(agent)
                            num_gamers += 1

        return agents

    # prompt the user for the K  -   slow down constant
    def prompt_k(self):
        k = float(input('Enter the slow-down constant: '))
        # 0 < K < 1
        if 0 < k <= 1:
            return k
        raise Exception('K must be in range (0,1)')

    # create a path of states from the final node. the path is the agent's actions.
    def get_state_path(self, final_node):
        path = [final_node]
        if final_node == 'FAILURE':
            return ['FAILURE']
        runner_node = final_node.parent

        while runner_node is not None:
            path.insert(0, runner_node)
            runner_node = runner_node.parent
        return path

    # get the number of people saved by the Agent
    def get_score_from_path(self, state_path):
        score = 0
        for i in range(len(state_path))[1:]:
            in_car = state_path[i].get_people_in_car()
            # if 0 people in car, it means last state was a drop-off
            if in_car is 0:
                score += state_path[i - 1].get_people_in_car()
        return score

    def print_run(self):

        if len(self.agents_history) is 0:
            print('Nothing to print!')
            return
        for agent, state_path in self.agents_history:
            actions = [node.action for node in state_path]
            score = self.get_score_from_path(state_path)
            expands = self.agents[-1].expands
            p = self.f_constant * score + expands
            print('**********\nShowing steps of {}.\nscore:{}\nExpands:{}'.
                  format(agent, score, expands))
            print('Performance: {} = {} * {} + {}'.format(
                p, self.f_constant, score, expands))
            print('Final State: {}\n\n'.format(state_path[len(state_path) -
                                                          1].state))
            print('Action Trace:\n    {}\n'.format(actions))

    # create a state for 2 agent problem
    def create_init_states(self, world, agents):
        state = dict()
        for agent in agents:
            people = world.get_vertex_for_tag(
                agent.vertex).people if world.is_house(agent.vertex) else 0
            state[agent.name] = {
                'position': agent.vertex,
                'people_in_car': people,
                'people_saved': 0
            }
        state['time'] = 0
        return state

    # run each agent in turn. in case of human agent, CHANGE the parent according to the human's choice.
    def run(self):
        print('initial state : {}'.format(self.game_tree.root.get_state()))
        node = self.game_tree.root
        i = 0  # first agent to "run"
        while node.type is not 'CUTOFF' and node.type is not 'TERMINAL':
            agent = self.agents[i]
            action = agent.get_move(node)
            # update to next node
            for child in node.children:
                if child.action == action:
                    child.parent = node
                    node = child
            state_path = self.get_state_path(node)
            print('path here : {}'.format([n.action for n in state_path]))
            print(
                '------\nagent:{} action {}\ntime: {}\nminimax value: {}\nstate: {}\n------\n'
                .format(agent.name, action, node.get_time(),
                        node.get_minimax_value(), node.get_state()))
            # next agent
            i = (i + 1) % len(self.agents)

    def run_ping_pong(self):
        turn = 0
        actions = []
        visited = []
        state = self.create_init_states(self.world, self.agents)
        visited.append(
            state[self.agents[0].name]['position'])  # append initial positions
        visited.append(
            state[self.agents[1].name]['position'])  # append initial positions
        while True:
            current_agent = self.agents[turn]
            if isinstance(current_agent, Human):
                result_node = current_agent.get_move(state=state,
                                                     visited=visited,
                                                     world=self.world)
            else:
                result_node = current_agent.get_move_new_tree(
                    state=state,
                    visited=visited,
                    world=self.world,
                    cutoff_depth=self.cutoff_depth,
                    mode=self.mode)
            actions.append(result_node.action)
            visited.append(result_node.get_position(current_agent.name))
            visited.append(result_node.get_position(current_agent.name))

            print('path here : {}'.format(actions))
            print(
                '------\nagent:{} action {}\ntime: {}\nminimax value: {}\nstate: {}\n------\n'
                .format(self.agents[turn].choice, result_node.action,
                        result_node.get_time(),
                        result_node.get_minimax_value(),
                        result_node.get_state()))

            if result_node.type == 'CUTOFF' or result_node.type == 'TERMINAL':
                print("final state: {}".format(result_node.get_state()))
                break
            turn = (turn + 1) % len(self.agents)  # next agent's turn
            state = result_node.get_state()
            result_node = None
Exemplo n.º 3
0
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
Exemplo n.º 4
0
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