def test_retrieving_single_greenyellow_interval(self):
        """ test retrieving a single greenyellow interval of a signal group """
        # GIVEN
        input_dict = TestFTSMethods.get_default_fts_inputs()
        sg1 = SignalGroup(
            id="sg1",
            traffic_lights=[TrafficLight(capacity=800, lost_time=1)],
            min_greenyellow=10,
            max_greenyellow=80,
            min_red=10,
            max_red=80)
        sg2 = SignalGroup(
            id="sg2",
            traffic_lights=[TrafficLight(capacity=800, lost_time=1)],
            min_greenyellow=10,
            max_greenyellow=80,
            min_red=10,
            max_red=80)

        # WHEN
        fts = FixedTimeSchedule(**input_dict)

        # THEN
        self.assertEqual(fts.get_greenyellow_interval(signalgroup=sg1, k=0),
                         input_dict["greenyellow_intervals"]["sg1"][0])
        self.assertEqual(fts.get_greenyellow_interval(signalgroup=sg1, k=1),
                         input_dict["greenyellow_intervals"]["sg1"][1])
        self.assertEqual(fts.get_greenyellow_interval(signalgroup=sg2, k=0),
                         input_dict["greenyellow_intervals"]["sg2"][0])
    def test_retrieving_single_interval_with_id(self):
        # GIVEN
        input_dict = TestFTSMethods.get_default_fts_inputs()
        sg1 = SignalGroup(
            id="sg1",
            traffic_lights=[TrafficLight(capacity=800, lost_time=1)],
            min_greenyellow=10,
            max_greenyellow=80,
            min_red=10,
            max_red=80)
        sg2 = SignalGroup(
            id="sg2",
            traffic_lights=[TrafficLight(capacity=800, lost_time=1)],
            min_greenyellow=10,
            max_greenyellow=80,
            min_red=10,
            max_red=80)

        # WHEN
        fts = FixedTimeSchedule(**input_dict)

        # THEN using id should give the same information
        self.assertEqual(fts.get_greenyellow_interval(signalgroup=sg1, k=0),
                         fts.get_greenyellow_interval(signalgroup=sg1.id, k=0))
        self.assertEqual(fts.get_greenyellow_interval(signalgroup=sg1, k=1),
                         fts.get_greenyellow_interval(signalgroup=sg1.id, k=1))
        self.assertEqual(fts.get_greenyellow_interval(signalgroup=sg2, k=0),
                         fts.get_greenyellow_interval(signalgroup=sg2.id, k=0))
예제 #3
0
    def test_getting_non_existing_signal_group(self):
        """ Test retrieving signal group by id when this id does not exist """
        # GIVEN
        signalgroup1 = SignalGroup(id="sg1", traffic_lights=[TrafficLight(capacity=1800, lost_time=1)],
                                   min_greenyellow=10, max_greenyellow=80, min_red=10, max_red=80)
        signalgroup2 = SignalGroup(id="sg2", traffic_lights=[TrafficLight(capacity=1800, lost_time=1)],
                                   min_greenyellow=10, max_greenyellow=80, min_red=10, max_red=80)
        intersection = Intersection(signalgroups=[signalgroup1, signalgroup2], conflicts=[], sync_starts=[],
                                    offsets=[], greenyellow_leads=[])

        with self.assertRaises(ValueError):
            # WHEN
            intersection.get_signalgroup(signalgroup_id="sg3")
예제 #4
0
    def test_getting_signal_group(self):
        """ Test retrieving signal group by id """
        # GIVEN
        signalgroup1 = SignalGroup(id="sg1", traffic_lights=[TrafficLight(capacity=1800, lost_time=1)],
                                   min_greenyellow=10, max_greenyellow=80, min_red=10, max_red=80)
        signalgroup2 = SignalGroup(id="sg2", traffic_lights=[TrafficLight(capacity=1800, lost_time=1)],
                                   min_greenyellow=10, max_greenyellow=80, min_red=10, max_red=80)

        intersection = Intersection(signalgroups=[signalgroup1, signalgroup2], conflicts=[], sync_starts=[],
                                    offsets=[], greenyellow_leads=[])

        # WHEN/THEN
        self.assertEqual(intersection.get_signalgroup(signalgroup_id="sg1"), signalgroup1)
        self.assertEqual(intersection.get_signalgroup(signalgroup_id="sg2"), signalgroup2)
    def test_json_back_and_forth(self) -> None:
        """ Test converting back and forth from and to json """
        # GIVEN
        input_dict = TestInputValidation.get_default_inputs()

        # WHEN
        traffic_light = TrafficLight(**input_dict)

        # THEN converting back and forth should in the end give the same result
        traffic_light_dict = traffic_light.to_json()
        traffic_light_from_json = TrafficLight.from_json(
            traffic_light_dict=traffic_light_dict)
        self.assertDictEqual(traffic_light_dict,
                             traffic_light_from_json.to_json())
    def test_retrieving_for_unkown_signalgroup(self):
        """ test retrieving greenyellow intervals of an unkown signal group """
        # GIVEN
        input_dict = TestFTSMethods.get_default_fts_inputs()
        # unkown signal group
        sg3 = SignalGroup(
            id="sg3",
            traffic_lights=[TrafficLight(capacity=800, lost_time=1)],
            min_greenyellow=10,
            max_greenyellow=80,
            min_red=10,
            max_red=80)

        fts = FixedTimeSchedule(**input_dict)

        with self.assertRaises(ValueError):
            # WHEN trying to access greenyellow intervals of an unkown signal group
            fts.get_greenyellow_intervals(sg3)

            # THEN an error should be raised

        # same but using id
        with self.assertRaises(ValueError):
            # WHEN trying to access greenyellow intervals of an unkown signal group
            fts.get_greenyellow_intervals(sg3.id)
예제 #7
0
 def get_default_signalgroup(name: str, min_greenyellow: float = 10.0, max_greenyellow: float = 80.0,
                             min_red: float = 10.0, max_red: float = 80.0) -> SignalGroup:
     """ Get a default signalgroup object"""
     traffic_light = TrafficLight(capacity=0.5, lost_time=0.0)
     return SignalGroup(id=name, traffic_lights=[traffic_light],
                        min_greenyellow=min_greenyellow, max_greenyellow=max_greenyellow, min_red=min_red,
                        max_red=max_red, min_nr=1, max_nr=3)
    def test_successful_validation(self) -> None:
        """ Test initializing TrafficLight object with correct input """
        # GIVEN
        input_dict = TestInputValidation.get_default_inputs()

        # WHEN
        TrafficLight(**input_dict)
 def _add_signalgroup(self, name: str) -> None:
     traffic_light = TrafficLight(capacity=0.5, lost_time=0.0)
     self._signal_groups.append(
         SignalGroup(id=name,
                     traffic_lights=[traffic_light],
                     min_greenyellow=2,
                     max_greenyellow=20,
                     min_red=2,
                     max_red=50,
                     min_nr=1,
                     max_nr=3))
    def test_zero(self) -> None:
        """ Test providing zero values for capacity and max_saturation """

        for key in ["capacity", "max_saturation"]:
            with self.subTest(f"Wrong type in input '{key}'"):
                # GIVEN
                input_dict = TestInputValidation.get_default_inputs()
                input_dict[key] = 0.0  # argument should be positive
                with self.assertRaises(ValueError):
                    # WHEN initializing the traffic light
                    TrafficLight(**input_dict)
    def test_wrong_type(self) -> None:
        """ Test providing the wrong type """

        for key in TestInputValidation.get_default_inputs():
            with self.subTest(f"Wrong type in input '{key}'"):
                # GIVEN
                input_dict = TestInputValidation.get_default_inputs()
                input_dict[key] = 'string'  # all arguments are numbers
                with self.assertRaises(ValueError):
                    # WHEN initializing the traffic light
                    TrafficLight(**input_dict)
    def test_negativity(self) -> None:
        """ Test providing negative values for capacity, lost_time, weight and max_saturation"""

        for key in TestInputValidation.get_default_inputs():
            with self.subTest(f"Wrong type in input '{key}'"):
                # GIVEN
                input_dict = TestInputValidation.get_default_inputs()
                input_dict[
                    key] = -0.1  # all arguments are non-negative numbers
                with self.assertRaises(ValueError):
                    # WHEN initializing the traffic light
                    TrafficLight(**input_dict)
예제 #13
0
 def from_json(signalgroup_dict: Dict) -> SignalGroup:
     """Loading signal group from json (expected same json structure as generated with to_json)"""
     return SignalGroup(
         id=signalgroup_dict["id"],
         min_greenyellow=signalgroup_dict["min_greenyellow"],
         max_greenyellow=signalgroup_dict["max_greenyellow"],
         min_red=signalgroup_dict["min_red"],
         max_red=signalgroup_dict["max_red"],
         min_nr=signalgroup_dict["min_nr"],
         max_nr=signalgroup_dict["max_nr"],
         traffic_lights=[
             TrafficLight.from_json(traffic_light_dict)
             for traffic_light_dict in signalgroup_dict["traffic_lights"]
         ])
예제 #14
0
 def get_default_inputs() -> Dict:
     """ Function to get default (valid) inputs for Intersection() """
     signalgroups = [SignalGroup(id=f"sg{i+1}", traffic_lights=[TrafficLight(capacity=1800, lost_time=1)],
                                 min_greenyellow=10, max_greenyellow=80, min_red=10, max_red=80) for i in range(6)]
     conflicts = [Conflict(id1="sg1", id2="sg2", setup12=1, setup21=2),
                  Conflict(id1="sg1", id2="sg6", setup12=1, setup21=2),
                  Conflict(id1="sg2", id2="sg6", setup12=1, setup21=2)]
     sync_starts = [SyncStart(from_id="sg1", to_id="sg3")]
     offsets = [Offset(from_id="sg1", to_id="sg4", seconds=10)]
     periodic_orders = [PeriodicOrder(order=["sg1", "sg2", "sg6"])]
     greenyellow_leads = [GreenyellowLead(from_id="sg1", to_id="sg5", min_seconds=1, max_seconds=10)]
     greenyellow_trails = [GreenyellowTrail(from_id="sg5", to_id="sg1", min_seconds=2, max_seconds=8)]
     return dict(signalgroups=signalgroups, conflicts=conflicts, sync_starts=sync_starts,
                 offsets=offsets, greenyellow_leads=greenyellow_leads, greenyellow_trails=greenyellow_trails,
                 periodic_orders=periodic_orders)
    def test_retrieving_unkown_interval(self):
        """ test retrieving greenyellow intervals of an unkown signal group """
        # GIVEN
        input_dict = TestFTSMethods.get_default_fts_inputs()
        # unkown signal group
        sg1 = SignalGroup(
            id="sg1",
            traffic_lights=[TrafficLight(capacity=800, lost_time=1)],
            min_greenyellow=10,
            max_greenyellow=80,
            min_red=10,
            max_red=80)

        fts = FixedTimeSchedule(**input_dict)

        with self.assertRaises(ValueError):
            # WHEN trying to access greenyellow intervals of an unkown signal group
            fts.get_greenyellow_interval(
                sg1, k=2)  # has only 2 intervals (with indices k=0 and k=1)
예제 #16
0
def fix_order_and_optimize():
    """
    This example shows how to ask for a fixed-time schedule that adheres to a specified fix order in which
    the signalgroups should receive their greenyellow interval.
    """
    logging.info(f"Running example '{os.path.basename(__file__)}'")
    # signal group consisting of two traffic light allowing 1 or 2 greenyellow intervals per repeating period.
    traffic_light1 = TrafficLight(capacity=1800, lost_time=2.2)
    traffic_light2 = TrafficLight(capacity=1810, lost_time=2.1)
    signalgroup1 = SignalGroup(id="2",
                               traffic_lights=[traffic_light1, traffic_light2],
                               min_greenyellow=10,
                               max_greenyellow=100,
                               min_red=10,
                               max_red=100,
                               min_nr=1,
                               max_nr=2)

    # signal group consisting of one traffic light allowing 1 greenyellow interval (default) per repeating period.
    traffic_light3 = TrafficLight(capacity=1650, lost_time=3.0)
    signalgroup2 = SignalGroup(id="5",
                               traffic_lights=[traffic_light3],
                               min_greenyellow=10,
                               max_greenyellow=100,
                               min_red=10,
                               max_red=100)

    # signal group consisting of one traffic light allowing 1 greenyellow interval (default) per repeating period.
    traffic_light4 = TrafficLight(capacity=1800, lost_time=2.1)
    signalgroup3 = SignalGroup(id="8",
                               traffic_lights=[traffic_light4],
                               min_greenyellow=10,
                               max_greenyellow=100,
                               min_red=10,
                               max_red=100)

    # conflicts & clearance times
    conflict12 = Conflict(id1=signalgroup1.id,
                          id2=signalgroup2.id,
                          setup12=1,
                          setup21=2)
    conflict13 = Conflict(id1=signalgroup1.id,
                          id2=signalgroup3.id,
                          setup12=2,
                          setup21=1)
    conflict23 = Conflict(id1=signalgroup2.id,
                          id2=signalgroup3.id,
                          setup12=2,
                          setup21=3)

    # initialize intersection object
    intersection = Intersection(
        signalgroups=[signalgroup1, signalgroup2, signalgroup3],
        conflicts=[conflict12, conflict13, conflict23])

    # set associated arrival rates
    arrival_rates = ArrivalRates(id_to_arrival_rates={
        "2": [800, 700],
        "5": [150],
        "8": [180]
    })
    logging.info(
        f"Not yet requesting any fixed order of greenyellow intervals")
    logging.info(f"Minimizing average experienced delay")
    # optimize fixed-time schedule
    fixed_time_schedule, phase_diagram, objective_value, _ = SwiftMobilityCloudApi.get_optimized_fts(
        intersection=intersection,
        arrival_rates=arrival_rates,
        objective=ObjectiveEnum.min_delay)

    logging.info(f"Average experienced delay {objective_value: .3f} seconds")
    logging.info(fixed_time_schedule)
    logging.info(phase_diagram)

    logging.info(f"Requesting order: 2 -> 8 -> 5 -> ")
    # initialize intersection object
    intersection = Intersection(
        signalgroups=[signalgroup1, signalgroup2, signalgroup3],
        conflicts=[conflict12, conflict13, conflict23],
        periodic_orders=[PeriodicOrder(order=["2", "8", "5"])])
    logging.info(f"Minimizing average experienced delay")
    # optimize fixed-time schedule
    fixed_time_schedule, phase_diagram, objective_value, _ = SwiftMobilityCloudApi.get_optimized_fts(
        intersection=intersection,
        arrival_rates=arrival_rates,
        objective=ObjectiveEnum.min_delay)

    logging.info(f"Average experienced delay {objective_value: .3f} seconds")
    logging.info(fixed_time_schedule)
    logging.info(phase_diagram)
예제 #17
0
def create_intersection_and_optimize():
    """
    Example showing how to:
    - create traffic lights, signal groups and intersections, ...
    - optimize a fixed-time schedule for this intersection

    NOTE:
    To run the example below you need credentials to invoke the swift mobility cloud api.
    To this end, you need to specify the following environment variables:
    - smc_api_key: the access key of your swift mobility cloud api account
    - smc_api_secret: the secret access key of your swift mobility cloud api account
    If you do not have such an account yet, please contact [email protected].
    """
    logging.info(f"Running example '{os.path.basename(__file__)}'")
    # signal group consisting of two traffic light allowing 1 or 2 greenyellow intervals per repeating period.
    traffic_light1 = TrafficLight(capacity=1800, lost_time=2.2)
    traffic_light2 = TrafficLight(capacity=1810, lost_time=2.1)
    signalgroup1 = SignalGroup(id="2",
                               traffic_lights=[traffic_light1, traffic_light2],
                               min_greenyellow=10,
                               max_greenyellow=100,
                               min_red=10,
                               max_red=100,
                               min_nr=1,
                               max_nr=2)

    # signal group consisting of one traffic light allowing 1 greenyellow interval (default) per repeating period.
    traffic_light3 = TrafficLight(capacity=1650, lost_time=3.0)
    signalgroup2 = SignalGroup(id="5",
                               traffic_lights=[traffic_light3],
                               min_greenyellow=10,
                               max_greenyellow=100,
                               min_red=10,
                               max_red=100)

    # signal group consisting of one traffic light allowing 1 greenyellow interval (default) per repeating period.
    traffic_light4 = TrafficLight(capacity=1800, lost_time=2.1)
    signalgroup3 = SignalGroup(id="8",
                               traffic_lights=[traffic_light4],
                               min_greenyellow=10,
                               max_greenyellow=100,
                               min_red=10,
                               max_red=100)

    # conflicts & clearance times
    conflict12 = Conflict(id1=signalgroup1.id,
                          id2=signalgroup2.id,
                          setup12=1,
                          setup21=2)
    conflict13 = Conflict(id1=signalgroup1.id,
                          id2=signalgroup3.id,
                          setup12=1,
                          setup21=2)
    conflict23 = Conflict(id1=signalgroup2.id,
                          id2=signalgroup3.id,
                          setup12=2,
                          setup21=3)

    # initialize intersection object
    intersection = Intersection(
        signalgroups=[signalgroup1, signalgroup2, signalgroup3],
        conflicts=[conflict12, conflict13, conflict23])

    # set associated arrival rates
    arrival_rates = ArrivalRates(id_to_arrival_rates={
        "2": [800, 700],
        "5": [150],
        "8": [180]
    })

    logging.info(f"Minimizing average experienced delay")
    # optimize fixed-time schedule
    fixed_time_schedule, phase_diagram, objective_value, _ = SwiftMobilityCloudApi.get_optimized_fts(
        intersection=intersection,
        arrival_rates=arrival_rates,
        objective=ObjectiveEnum.min_delay)

    logging.info(f"Average experienced delay {objective_value: .3f} seconds")
    logging.info(fixed_time_schedule)
    logging.info(phase_diagram)

    # the following code indicates how to compute a phase diagram from a fixed-time schedule (note that now it makes
    #  no sense to do so as it was already computed above)
    logging.info(
        "Computing phase diagram from fixed-time schedule. Should be the same as before"
    )
    phase_diagram = SwiftMobilityCloudApi.get_phase_diagram(
        intersection=intersection, fixed_time_schedule=fixed_time_schedule)
    logging.info(phase_diagram)