Beispiel #1
0
class TestSpaceNonToroidal(unittest.TestCase):
    '''
    Testing a toroidal continuous space.
    '''

    def setUp(self):
        '''
        Create a test space and populate with Mock Agents.
        '''
        self.space = ContinuousSpace(70, 20, False, -30, -30, 100, 100)
        self.agents = []
        for i, pos in enumerate(TEST_AGENTS):
            a = MockAgent(i, None)
            self.agents.append(a)
            self.space.place_agent(a, pos)

    def test_agent_positions(self):
        '''
        Ensure that the agents are all placed properly.
        '''
        for i, pos in enumerate(TEST_AGENTS):
            a = self.agents[i]
            assert a.pos == pos

    def test_distance_calculations(self):
        '''
        Test toroidal distance calculations.
        '''

        pos_2 = (70, 20)
        pos_3 = (-30, -20)
        assert self.space.get_distance(pos_2, pos_3) == 107.70329614269008

    def test_neighborhood_retrieval(self):
        '''
        Test neighborhood retrieval
        '''
        neighbors_1 = self.space.get_neighbors((-20, -20), 1)
        assert len(neighbors_1) == 2

        neighbors_2 = self.space.get_neighbors((40, -10), 10)
        assert len(neighbors_2) == 0

        neighbors_3 = self.space.get_neighbors((-30, -30), 10)
        assert len(neighbors_3) == 0

    def test_bounds(self):
        '''
        Test positions outside of boundary
        '''
        for i, pos in enumerate(OUTSIDE_POSITIONS):
            a = MockAgent(len(self.agents) + i, None)
            with self.assertRaises(Exception):
                self.space.place_agent(a, pos)

        a = self.agents[0]
        for pos in OUTSIDE_POSITIONS:
            assert self.space.out_of_bounds(pos)
            with self.assertRaises(Exception):
                self.space.move_agent(a, pos)
Beispiel #2
0
class TestSpaceToroidal(unittest.TestCase):
    '''
    Testing a toroidal continuous space.
    '''
    def setUp(self):
        '''
        Create a test space and populate with Mock Agents.
        '''
        self.space = ContinuousSpace(70, 20, True, -30, -30)
        self.agents = []
        for i, pos in enumerate(TEST_AGENTS):
            a = MockAgent(i, None)
            self.agents.append(a)
            self.space.place_agent(a, pos)

    def test_agent_positions(self):
        '''
        Ensure that the agents are all placed properly.
        '''
        for i, pos in enumerate(TEST_AGENTS):
            a = self.agents[i]
            assert a.pos == pos

    def test_agent_matching(self):
        '''
        Ensure that the agents are all placed and indexed properly.
        '''
        for i, agent in self.space._index_to_agent.items():
            assert agent.pos == tuple(self.space._agent_points[i, :])
            assert i == self.space._agent_to_index[agent]

    def test_distance_calculations(self):
        '''
        Test toroidal distance calculations.
        '''
        pos_1 = (-30, -30)
        pos_2 = (70, 20)
        assert self.space.get_distance(pos_1, pos_2) == 0

        pos_3 = (-30, -20)
        assert self.space.get_distance(pos_1, pos_3) == 10

        pos_4 = (20, -5)
        pos_5 = (20, -15)
        assert self.space.get_distance(pos_4, pos_5) == 10

        pos_6 = (-30, -29)
        pos_7 = (21, -5)
        assert self.space.get_distance(pos_6, pos_7) == np.sqrt(49**2 + 24**2)

    def test_heading(self):
        pos_1 = (-30, -30)
        pos_2 = (70, 20)
        self.assertEqual((0, 0), self.space.get_heading(pos_1, pos_2))

        pos_1 = (65, -25)
        pos_2 = (-25, -25)
        self.assertEqual((10, 0), self.space.get_heading(pos_1, pos_2))

    def test_neighborhood_retrieval(self):
        '''
        Test neighborhood retrieval
        '''
        neighbors_1 = self.space.get_neighbors((-20, -20), 1)
        assert len(neighbors_1) == 2

        neighbors_2 = self.space.get_neighbors((40, -10), 10)
        assert len(neighbors_2) == 0

        neighbors_3 = self.space.get_neighbors((-30, -30), 10)
        assert len(neighbors_3) == 1

    def test_bounds(self):
        '''
        Test positions outside of boundary
        '''
        boundary_agents = []
        for i, pos in enumerate(OUTSIDE_POSITIONS):
            a = MockAgent(len(self.agents) + i, None)
            boundary_agents.append(a)
            self.space.place_agent(a, pos)

        for a, pos in zip(boundary_agents, OUTSIDE_POSITIONS):
            adj_pos = self.space.torus_adj(pos)
            assert a.pos == adj_pos

        a = self.agents[0]
        for pos in OUTSIDE_POSITIONS:
            assert self.space.out_of_bounds(pos)
            self.space.move_agent(a, pos)
Beispiel #3
0
class TestSpaceNonToroidal(unittest.TestCase):
    """
    Testing a toroidal continuous space.
    """

    def setUp(self):
        """
        Create a test space and populate with Mock Agents.
        """
        self.space = ContinuousSpace(70, 20, False, -30, -30)
        self.agents = []
        for i, pos in enumerate(TEST_AGENTS):
            a = MockAgent(i, None)
            self.agents.append(a)
            self.space.place_agent(a, pos)

    def test_agent_positions(self):
        """
        Ensure that the agents are all placed properly.
        """
        for i, pos in enumerate(TEST_AGENTS):
            a = self.agents[i]
            assert a.pos == pos

    def test_agent_matching(self):
        """
        Ensure that the agents are all placed and indexed properly.
        """
        for i, agent in self.space._index_to_agent.items():
            assert agent.pos == tuple(self.space._agent_points[i, :])
            assert i == self.space._agent_to_index[agent]

    def test_distance_calculations(self):
        """
        Test toroidal distance calculations.
        """

        pos_2 = (70, 20)
        pos_3 = (-30, -20)
        assert self.space.get_distance(pos_2, pos_3) == 107.70329614269008

    def test_heading(self):
        pos_1 = (-30, -30)
        pos_2 = (70, 20)
        self.assertEqual((100, 50), self.space.get_heading(pos_1, pos_2))

        pos_1 = (65, -25)
        pos_2 = (-25, -25)
        self.assertEqual((-90, 0), self.space.get_heading(pos_1, pos_2))

    def test_neighborhood_retrieval(self):
        """
        Test neighborhood retrieval
        """
        neighbors_1 = self.space.get_neighbors((-20, -20), 1)
        assert len(neighbors_1) == 2

        neighbors_2 = self.space.get_neighbors((40, -10), 10)
        assert len(neighbors_2) == 0

        neighbors_3 = self.space.get_neighbors((-30, -30), 10)
        assert len(neighbors_3) == 0

    def test_bounds(self):
        """
        Test positions outside of boundary
        """
        for i, pos in enumerate(OUTSIDE_POSITIONS):
            a = MockAgent(len(self.agents) + i, None)
            with self.assertRaises(Exception):
                self.space.place_agent(a, pos)

        a = self.agents[0]
        for pos in OUTSIDE_POSITIONS:
            assert self.space.out_of_bounds(pos)
            with self.assertRaises(Exception):
                self.space.move_agent(a, pos)
Beispiel #4
0
class PredatorPreyModel(Model):
    def __init__(self,
                 height=100,
                 width=100,
                 init_prey=100,
                 prey_reproduction=0.03,
                 init_predator=10,
                 predator_vision=1,
                 predator_reproduction=0.5,
                 predator_death=0.02,
                 local_offspring=False,
                 max_iters=500,
                 seed=None):

        super().__init__()

        self.height = height
        self.width = width
        self.init_prey = init_prey
        self.prey_reproduction = prey_reproduction
        self.init_predator = init_predator
        self.predator_vision = predator_vision
        self.predator_reproduction = predator_reproduction
        self.predator_death = predator_death
        self.local_offspring = local_offspring
        self.iteration = 0
        self.max_iters = max_iters
        self.schedule = RandomActivation(self)
        self.space = ContinuousSpace(height, width, torus=True)
        model_reporters = {
            'Prey': lambda model: self.count('Prey'),
            'Predator': lambda model: self.count('Predator'),
        }

        self.datacollector = DataCollector(model_reporters=model_reporters)

        # Place prey
        for i in range(self.init_prey):
            x = self.random.uniform(0, self.width)
            y = self.random.uniform(0, self.height)
            # next_id() starts at 1
            prey = Prey(self.next_id(), self, (x, y), self.prey_reproduction)
            self.space.place_agent(prey, (x, y))
            self.schedule.add(prey)

        # Place predators
        for i in range(self.init_predator):
            x = self.random.uniform(0, self.width)
            y = self.random.uniform(0, self.height)
            predator = Predator(self.next_id(), self, (x, y),
                                self.predator_reproduction,
                                self.predator_death, self.predator_vision)
            self.space.place_agent(predator, (x, y))
            self.schedule.add(predator)

        self.running = True
        self.datacollector.collect(self)

    def step(self):
        """
        Advance the model by one step and collect data.

        Returns
        -------
        None.

        """

        self.schedule.step()
        self.iteration += 1

        self.datacollector.collect(self)

        # Stop system if maximum of iterations is reached
        if self.iteration > self.max_iters:
            self.running = False
            return None

    def count(self, breed):
        """
        Count agent by breed.

        Parameters
        ----------
        breed : string
            Breed of agent Can be 'Prey' or 'Predator'.

        Returns
        -------
        count : int
            Number of agents of type breed.

        """

        count = 0
        for agent in self.schedule.agents:
            if agent.breed == breed:
                count += 1

        if breed == 'Predator' and count == 0:
            self.running = False

        return count

    def warm_up(self):
        for agent in self.schedule.agents:
            if agent.breed == 'Prey':
                continue

            neighbors = self.space.get_neighbors(agent.pos,
                                                 radius=agent.vision)

            for prey in neighbors:
                if prey.breed == 'Prey':
                    x = self.random.uniform(0, self.width)
                    y = self.random.uniform(0, self.height)
                    self.space.move_agent(prey, (x, y))
Beispiel #5
0
class ChaosModel(Model):
    '''
    The stochastic highway simulation model
    '''

    #################################################################
    ## INITIALIZATION FUNCTIONS
    #################################################################

    def __init__(self,
                 agent_type,
                 width=500,
                 height=500,
                 num_adversaries=8,
                 road_width=60,
                 frozen=True,
                 epsilon=0,
                 episode_duration=100,
                 Q=None,
                 N=None):
        self.num_adversaries = num_adversaries
        self.road_width = road_width
        self.episode_duration = episode_duration
        self.schedule = RandomActivation(self)

        self.space = ContinuousSpace(width, height, True)
        self.cars = []

        self.make_agents(AgentType(agent_type), frozen, epsilon, Q, N)
        self.running = True

        self.step_count = 0
        self.count = 0
        self.curr_reward = 0

        self.reset()

        self.datacollector = DataCollector(
            model_reporters={"Agent rewards sum": get_rewards_sum_log})

    def agent_start_state(self):
        pos = np.array((self.space.x_max / 2, self.space.y_max / 2 + 100))
        target_speed = 10
        speed = target_speed
        heading = np.radians(-90)
        return (pos, target_speed, speed, heading)

    def reset(self):
        (pos, target_speed, speed, heading) = self.agent_start_state()
        # speed = util.rand_min_max(target_speed*.8, target_speed*1.2)
        # speed = util.rand_min_max(6,14)
        # speed = 0
        # heading = util.rand_min_max(np.radians(-89),np.radians(-91))
        # heading = np.radians(-85)
        self.learn_agent.speed = speed
        self.learn_agent.heading = heading
        self.space.move_agent(self.learn_agent, pos)
        self.step_count = 0
        self.rewards_sum = -1

    def make_adversary(self, unique_id):
        # Initial speed and heading
        speed = util.rand_min_max(0, 3)
        heading = np.radians(-90)

        # Randomly add large (blue), medium (orange), or small (green) car
        val = random.random()
        if val < 0.33:
            color = "Blue"
            target_speed = util.rand_min_max(2, 4)
            width = util.rand_min_max(8, 9)
            length = util.rand_min_max(35, 45)
        elif val < 0.66:
            color = "Orange"
            target_speed = util.rand_min_max(3, 6)
            width = util.rand_min_max(7, 8)
            length = util.rand_min_max(16, 30)
        else:
            color = "Green"
            target_speed = util.rand_min_max(6, 7)
            width = util.rand_min_max(5, 6)
            length = util.rand_min_max(12, 16)

        # Add car to a random position if not overlapping within a margin
        # Try (num_adversaries * 2) times before giving up
        pos = None
        for _ in range(self.num_adversaries * 2):
            x = util.rand_center_spread(self.space.x_max / 2, self.road_width)
            y = random.uniform(self.space.y_min + 1, self.space.y_max - 1)
            if not util.is_overlapping(x, y, width, length, self.cars):
                pos = np.array((x, y))
                break
        if pos is None:
            return None

        return Car(unique_id,
                   self,
                   pos,
                   speed,
                   heading,
                   color,
                   target_speed=target_speed,
                   width=width,
                   length=length)

    def make_learn_agent(self, agent_type, unique_id, epsilon, Q, N):
        (pos, target_speed, speed, heading) = self.agent_start_state()
        width = 6
        length = 12
        color = "Black"

        if agent_type == AgentType.QLEARN:
            return QCar(unique_id,
                        self,
                        pos,
                        speed,
                        heading,
                        color,
                        target_speed=target_speed,
                        length=length,
                        width=width,
                        Q=Q,
                        N=N)

        elif agent_type == AgentType.DEEPQ:
            return DeepQCar(unique_id,
                            self,
                            pos,
                            speed,
                            heading,
                            color,
                            target_speed=target_speed,
                            width=width,
                            length=length,
                            epsilon=epsilon)

        else:  # agent_type == AgentType.BASIC
            return Car(unique_id,
                       self,
                       pos,
                       speed,
                       heading,
                       color,
                       target_speed=target_speed,
                       width=width,
                       length=length)

    def make_frozen(self, unique_id):
        pos = np.array((self.space.x_max / 2, self.space.y_max / 2))
        return Car(unique_id,
                   self,
                   pos,
                   0,
                   np.radians(-90),
                   "Indigo",
                   target_speed=0,
                   width=6,
                   length=12)

    def make_agents(self, agent_type, frozen, epsilon, Q, N):
        '''
        Add all agents to model space
        '''
        # Car agents
        for i in range(0, self.num_adversaries + 1):
            if i == 0:
                car = self.make_learn_agent(agent_type, i, epsilon, Q, N)
            elif frozen:
                car = self.make_frozen(i)
                frozen = False
            else:
                car = self.make_adversary(i)
            if car is None:
                print("WARNING: Could only add %d adversaries" % (i - 1))
                break
            self.cars.append(car)
            self.space.place_agent(car, car.pos)
            self.schedule.add(car)

        # Barriers
        x = (self.space.x_max + self.road_width + 10) / 2
        self.add_barrier(len(self.cars), x)
        self.add_barrier(len(self.cars) + 1, x - self.road_width - 10)

    def add_barrier(self, unique_id, x):
        y = self.space.y_max / 2
        barrier = Barrier(unique_id, self, np.array([x, y]), "Black", 1,
                          self.space.y_max)
        self.schedule.add(barrier)

    #################################################################
    ## RUNNING SIMULATION FUNCTIONS
    #################################################################

    @property
    def learn_agent(self):
        return self.cars[0]

    def step(self):
        self.step_count += 1
        if self.step_count > self.episode_duration and \
                type(self.learn_agent) is not DeepQCar:
            self.reset()

        self.datacollector.collect(self)
        # First loop through and have all cars choose an action
        # before the action is actually propagated forward
        for car in self.cars:
            car.choose_action()

        # Propagate forward one step based on chosen actions
        self.schedule.step()
        self.curr_reward = self.reward()
        self.rewards_sum += self.curr_reward

        agent = self.learn_agent
        left = (self.space.x_max - self.road_width) / 2
        # if type(agent) is DeepQCar and \
        #         (agent.pos[0] - agent.length / 2 <= left or \
        #          agent.pos[0] + agent.length / 2 >= left + self.road_width):
        #     self.running = False
        if type(agent) is DeepQCar and \
                (agent.pos[0] - agent.length / 2 <= left or \
                 agent.pos[0] + agent.length / 2 >= left + self.road_width or \
                 util.is_overlapping(agent.pos[0], agent.pos[1],
                                     agent.width, agent.length,
                                     agent.get_neighbors(), margin=0)):
            self.running = False

    def reward(self):
        agent = self.learn_agent
        # heading_cost = np.abs(agent.heading - agent.target_heading) * -2
        # steering_cost = np.abs(agent.steer) * -2
        # acceleration_cost = np.abs(agent.accel) * -1
        vy = -agent.speed * np.sin(agent.heading)
        speed_reward = 0
        if (vy > agent.target_speed * 1.1):
            speed_reward = -20
        elif (vy > agent.target_speed * 1.05):
            speed_reward = -2
        elif (vy > agent.target_speed * 0.90):
            speed_reward = 0
        else:
            speed_reward = -3
        # penalizes collisoins from the front more
        collision_cost = agent.collided * -500

        # Alternate speed reward
        speed_reward = np.abs(vy - agent.target_speed) * -1
        if speed_reward > -0.5:
            speed_reward = 0
        elif speed_reward < -agent.target_speed / 2:
            speed_reward = -20

        # Try to reward position
        # pos_cost = 0
        # if agent.pos[1] < self.space.y_max/2 - 70 or vy < agent.target_speed/2:
        #     pos_cost = -10
        # print(pos_reward)

        # print("speed reward {}, accel cost {}, steer cost {}, collision cost {}".format(
        # speed_reward, acceleration_cost, steering_cost, collision_cost))
        # return speed_reward + acceleration_cost + steering_cost + \
        # collision_cost + heading_cost
        # print(speed_reward, collision_cost, heading_cost)

        # print(vy, agent.target_speed, speed_reward, collision_cost, a, agent.steer, agent.accel)

        return speed_reward + collision_cost

    def deepq_reward(self, agent):
        left = (self.space.x_max - self.road_width) / 2
        # Large negative reward for collision
        if agent.pos[0] - agent.length / 2 <= left or \
                agent.pos[0] + agent.length / 2 >= left + self.road_width:
            return -1
        if util.is_overlapping(agent.pos[0],
                               agent.pos[1],
                               agent.width,
                               agent.length,
                               agent.get_neighbors(),
                               margin=0):
            return -0.5
        return 0
        # Large positive reward for staying at target speed and heading
        # Linearly decreases based on magnitude of difference from actual
        # Reward of 0.5 for staying at average (y) speed of all cars
        # Assumes target speed > average speed
        # Reward of 0.5 for changing lanes within one time step (TEST THIS)
        # Assumes actions have no cost, but rather cause cost by changing
        #     resulting velocity (THIS MAY CHANGE)
        average_speed = np.mean([-car.speed * np.sin(car.heading) \
                                 for car in self.cars])
        agent_vel = agent.vel_components()
        x_cost = abs(agent_vel[0]) / 20
        y_cost = abs(-agent_vel[1] - agent.target_speed) / \
                 (agent.target_speed - average_speed) / 2
        return max(1 - x_cost - y_cost, -1)
Beispiel #6
0
class TestSpaceToroidal(unittest.TestCase):
    '''
    Testing a toroidal continuous space.
    '''

    def setUp(self):
        '''
        Create a test space and populate with Mock Agents.
        '''
        self.space = ContinuousSpace(70, 20, True, -30, -30, 100, 100)
        self.agents = []
        for i, pos in enumerate(TEST_AGENTS):
            a = MockAgent(i, None)
            self.agents.append(a)
            self.space.place_agent(a, pos)

    def test_agent_positions(self):
        '''
        Ensure that the agents are all placed properly.
        '''
        for i, pos in enumerate(TEST_AGENTS):
            a = self.agents[i]
            assert a.pos == pos

    def test_distance_calculations(self):
        '''
        Test toroidal distance calculations.
        '''
        pos_1 = (-30, -30)
        pos_2 = (70, 20)
        assert self.space.get_distance(pos_1, pos_2) == 0

        pos_3 = (-30, -20)
        assert self.space.get_distance(pos_1, pos_3) == 10

    def test_heading(self):
        pos_1 = (-30, -30)
        pos_2 = (70, 20)
        self.assertEqual((0, 0), self.space.get_heading(pos_1, pos_2))

        pos_1 = (65, -25)
        pos_2 = (-25, -25)
        self.assertEqual((10, 0), self.space.get_heading(pos_1, pos_2))

    def test_neighborhood_retrieval(self):
        '''
        Test neighborhood retrieval
        '''
        neighbors_1 = self.space.get_neighbors((-20, -20), 1)
        assert len(neighbors_1) == 2

        neighbors_2 = self.space.get_neighbors((40, -10), 10)
        assert len(neighbors_2) == 0

        neighbors_3 = self.space.get_neighbors((-30, -30), 10)
        assert len(neighbors_3) == 1

    def test_bounds(self):
        '''
        Test positions outside of boundary
        '''
        boundary_agents = []
        for i, pos in enumerate(OUTSIDE_POSITIONS):
            a = MockAgent(len(self.agents) + i, None)
            boundary_agents.append(a)
            self.space.place_agent(a, pos)

        for a, pos in zip(boundary_agents, OUTSIDE_POSITIONS):
            adj_pos = self.space.torus_adj(pos)
            assert a.pos == adj_pos

        a = self.agents[0]
        for pos in OUTSIDE_POSITIONS:
            assert self.space.out_of_bounds(pos)
            self.space.move_agent(a, pos)
Beispiel #7
0
class TestSpaceNonToroidal(unittest.TestCase):
    '''
    Testing a toroidal continuous space.
    '''

    def setUp(self):
        '''
        Create a test space and populate with Mock Agents.
        '''
        self.space = ContinuousSpace(70, 20, False, -30, -30)
        self.agents = []
        for i, pos in enumerate(TEST_AGENTS):
            a = MockAgent(i, None)
            self.agents.append(a)
            self.space.place_agent(a, pos)

    def test_agent_positions(self):
        '''
        Ensure that the agents are all placed properly.
        '''
        for i, pos in enumerate(TEST_AGENTS):
            a = self.agents[i]
            assert a.pos == pos

    def test_agent_matching(self):
        '''
        Ensure that the agents are all placed and indexed properly.
        '''
        for i, agent in self.space._index_to_agent.items():
            assert agent.pos == tuple(self.space._agent_points[i, :])
            assert i == self.space._agent_to_index[agent]

    def test_distance_calculations(self):
        '''
        Test toroidal distance calculations.
        '''

        pos_2 = (70, 20)
        pos_3 = (-30, -20)
        assert self.space.get_distance(pos_2, pos_3) == 107.70329614269008

    def test_heading(self):
        pos_1 = (-30, -30)
        pos_2 = (70, 20)
        self.assertEqual((100, 50), self.space.get_heading(pos_1, pos_2))

        pos_1 = (65, -25)
        pos_2 = (-25, -25)
        self.assertEqual((-90, 0), self.space.get_heading(pos_1, pos_2))

    def test_neighborhood_retrieval(self):
        '''
        Test neighborhood retrieval
        '''
        neighbors_1 = self.space.get_neighbors((-20, -20), 1)
        assert len(neighbors_1) == 2

        neighbors_2 = self.space.get_neighbors((40, -10), 10)
        assert len(neighbors_2) == 0

        neighbors_3 = self.space.get_neighbors((-30, -30), 10)
        assert len(neighbors_3) == 0

    def test_bounds(self):
        '''
        Test positions outside of boundary
        '''
        for i, pos in enumerate(OUTSIDE_POSITIONS):
            a = MockAgent(len(self.agents) + i, None)
            with self.assertRaises(Exception):
                self.space.place_agent(a, pos)

        a = self.agents[0]
        for pos in OUTSIDE_POSITIONS:
            assert self.space.out_of_bounds(pos)
            with self.assertRaises(Exception):
                self.space.move_agent(a, pos)