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
        arrival_rates = ArrivalRates(**input_dict)

        # THEN converting back and forth should in the end give the same result
        arrival_rates_dict = arrival_rates.to_json()
        arrival_rates_from_json = ArrivalRates.from_json(
            arrival_rates_dict=arrival_rates_dict)
        self.assertDictEqual(arrival_rates_dict,
                             arrival_rates_from_json.to_json())
    def test_add_different_lengths(self) -> None:
        """ Test adding two ArrivalRates with different number of rates """
        # GIVEN
        arrival_rates1 = ArrivalRates(id_to_arrival_rates={
            "1": [1000, 950],
            "2": [850, 700]
        })
        arrival_rates2 = ArrivalRates(id_to_arrival_rates={
            "1": [642, 230],
            "2": [600, 355, 800]
        })

        with self.assertRaises(ArithmeticError):
            # WHEN adding to rates with different ids
            arrival_rates1 + arrival_rates2
    def test_successful_validation(self) -> None:
        """ Test initializing ArrivalRates object with correct input """
        # GIVEN
        input_dict = TestInputValidation.get_default_inputs()

        # WHEN
        ArrivalRates(**input_dict)
    def test_no_list_for_rates(self) -> None:
        """ Test providing no list as value in id_to_arrival_rates"""
        # GIVEN
        input_dict = TestInputValidation.get_default_inputs()
        input_dict["id_to_arrival_rates"]["3"] = 1  # rates is not a list

        with self.assertRaises(ValueError):
            # WHEN initializing the arrival rates
            ArrivalRates(**input_dict)
Exemple #5
0
def evaluate_fixed_time_schedule(print_fixed_time_schedule: bool = False):
    """
    In this example we show how to evaluate a fixed-time schedule.

    Use case: comparing two fixed-time schedules (perhaps not optimized via this api) on expected performance.

    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].

    In this example, we load an intersection from disk (export of Swift Mobility Desktop). You can download this
    file (example_smd_export.json) from
    https://github.com/stijnfleuren/SwiftCloudApi/tree/master/swift_cloud_py/examples
    """
    logging.info(f"Running example '{os.path.basename(__file__)}'")
    # absolute path to .json file that has been exported from swift mobility desktop
    smd_export = os.path.join(
        os.path.join(os.path.abspath(__file__), os.pardir),
        "example_smd_export.json")

    # retrieve the json structure from the file
    with open(smd_export, "r") as f:
        json_dict = json.load(f)

    logging.info(f"Loading intersection and traffic situation from disk")
    intersection = Intersection.from_json(
        intersection_dict=json_dict["intersection"])
    arrival_rates = ArrivalRates.from_json(
        arrival_rates_dict=json_dict["arrival_rates"])
    logging.info(f"Loaded intersection and traffic situation from disk")
    logging.info(f"Minimizing delay")
    fixed_time_schedule, phase_diagram, objective_value, _ = SwiftMobilityCloudApi.get_optimized_fts(
        intersection=intersection,
        arrival_rates=arrival_rates,
        min_period_duration=30,
        max_period_duration=180,
        objective=ObjectiveEnum.min_delay,
        horizon=2)

    logging.info(f"Average experienced delay: {objective_value:.2f} seconds")

    if print_fixed_time_schedule:
        logging.info(fixed_time_schedule)
        logging.info(phase_diagram)

    # this should return the same estimated delay. With this functionality we could evaluate the expected performance
    #  of any fixed-time schedule.
    logging.info(f"Evaluate this schedule")
    kpis = SwiftMobilityCloudApi.evaluate_fts(
        intersection=intersection,
        fixed_time_schedule=fixed_time_schedule,
        arrival_rates=arrival_rates,
        horizon=2)
    logging.info(f"Output: {kpis}")
    def test_no_dict(self) -> None:
        """ Test providing no dictionary for id_to_arrival_rates"""
        # GIVEN
        input_dict = TestInputValidation.get_default_inputs()
        input_dict["id_to_arrival_rates"] = 1

        with self.assertRaises(ValueError):
            # WHEN initializing the arrival rates
            ArrivalRates(**input_dict)
Exemple #7
0
def optimize_multiple_schedules():
    """
    Example showing how to:
    - retrieve intersection information and arrival rates from a json file exported from Swift Mobility Desktop.
    - use this information to optimize fixed-time schedules

    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].

    In this example, we load an intersection from disk (export of Swift Mobility Desktop). This functionality is tested
    with Swift Mobility Desktop 0.7.0.alpha.
    """
    logging.info(f"Running example '{os.path.basename(__file__)}'")
    # absolute path to .json file that has been exported from swift mobility desktop
    smd_export = os.path.join(
        os.path.join(os.path.abspath(__file__), os.pardir),
        "example_smd_export.json")

    # retrieve the json structure from the file
    with open(smd_export, "r") as f:
        json_dict = json.load(f)

    logging.info(f"Loading intersection and traffic situation from disk")
    intersection = Intersection.from_json(
        intersection_dict=json_dict["intersection"])

    arrival_rates = ArrivalRates.from_json(
        arrival_rates_dict=json_dict["arrival_rates"])
    logging.info(f"Loaded intersection and traffic situation from disk")

    logging.info(f"Minimizing average experienced delay")
    best_fixed_time_schedule, best_phase_diagram, objective_value, warm_start_info = \
        SwiftMobilityCloudApi.get_optimized_fts(
            intersection=intersection, arrival_rates=arrival_rates, min_period_duration=30, max_period_duration=180,
            objective=ObjectiveEnum.min_delay)

    logging.info(f"Average experienced delay: {objective_value:.2f} seconds")
    logging.info(best_fixed_time_schedule)
    logging.info(best_phase_diagram)

    logging.info(f"Finding second best schedule")
    second_best_fixed_time_schedule, second_best_phase_diagram, objective_value, warm_start_info = \
        SwiftMobilityCloudApi.get_optimized_fts(
            intersection=intersection, arrival_rates=arrival_rates, min_period_duration=30, max_period_duration=180,
            objective=ObjectiveEnum.min_delay, fixed_time_schedules_to_exclude=[best_fixed_time_schedule],
            warm_start_info=warm_start_info)

    logging.info(
        f"Average experienced delay of second best schedule: {objective_value:.2f} seconds"
    )
    logging.info(second_best_fixed_time_schedule)
    logging.info(second_best_phase_diagram)
 def __truediv__(self, time: float) -> ArrivalRates:
     """ divide the queue length by a time interval ('other' in hours) to get a rate in PCE/h"""
     if not isinstance(time, (int, float)):
         raise ArithmeticError(
             "can divide queue_lengths rates only by float")
     id_to_arrival_rates = {
         id_: [rate / time for rate in rates]
         for id_, rates in self.id_to_queue_lengths.items()
     }
     return ArrivalRates(id_to_arrival_rates=id_to_arrival_rates)
    def test_add(self) -> None:
        """ Test adding two ArrivalRates """
        # GIVEN
        arrival_rates1 = ArrivalRates(id_to_arrival_rates={
            "1": [1000, 950],
            "2": [850, 700]
        })
        arrival_rates2 = ArrivalRates(id_to_arrival_rates={
            "1": [642, 230],
            "2": [600, 355]
        })

        # WHEN
        arrival_rates1 += arrival_rates2

        # THEN
        self.assertListEqual(arrival_rates1.id_to_arrival_rates["1"],
                             [1000 + 642, 950 + 230])
        self.assertListEqual(arrival_rates1.id_to_arrival_rates["2"],
                             [850 + 600, 700 + 355])
    def test_no_string_values(self) -> None:
        """ Test providing no string as id in id_to_arrival_rates"""
        # GIVEN
        input_dict = TestInputValidation.get_default_inputs()
        input_dict["id_to_arrival_rates"][1] = [
            1, 2
        ]  # add value (1) which is not a string

        with self.assertRaises(ValueError):
            # WHEN initializing the arrival rates
            ArrivalRates(**input_dict)
    def test_multiply_wrong_type(self) -> None:
        """ Test multiplying ArrivalRates with non-numeric value """
        # GIVEN
        arrival_rates1 = ArrivalRates(id_to_arrival_rates={
            "1": [1000, 950],
            "2": [850, 700]
        })

        with self.assertRaises(ArithmeticError):
            # WHEN
            arrival_rates1 * "string"
    def test_rate_no_number(self) -> None:
        """ Test providing no numbers for the rates """
        # GIVEN
        input_dict = TestInputValidation.get_default_inputs()
        input_dict["id_to_arrival_rates"]["3"] = [
            1, "3"
        ]  # rates is not a list of numbers

        with self.assertRaises(ValueError):
            # WHEN initializing the arrival rates
            ArrivalRates(**input_dict)
    def test_multiply(self) -> None:
        """ Test multiplying ArrivalRates """
        # GIVEN
        arrival_rates1 = ArrivalRates(id_to_arrival_rates={
            "1": [1000, 950],
            "2": [850, 700]
        })

        # WHEN
        arrival_rates1 *= 1.3

        # THEN
        self.assertListEqual(arrival_rates1.id_to_arrival_rates["1"],
                             [1000 * 1.3, 950 * 1.3])
        self.assertListEqual(arrival_rates1.id_to_arrival_rates["2"],
                             [850 * 1.3, 700 * 1.3])
def minimizing_period_duration(print_fixed_time_schedule: bool = False):
    """
    In this example (given a traffic scenario) we search for the fixed-time schedule with the smallest period duration
    for which none of the traffic lights are oversatured.

    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].

    In this example, we load an intersection from disk (export of Swift Mobility Desktop). This functionality is tested
    with Swift Mobility Desktop 0.7.0.alpha.
    """
    logging.info(f"Running example '{os.path.basename(__file__)}'")
    # absolute path to .json file that has been exported from swift mobility desktop
    smd_export = os.path.join(
        os.path.join(os.path.abspath(__file__), os.pardir),
        "example_smd_export.json")

    # retrieve the json structure from the file
    with open(smd_export, "r") as f:
        json_dict = json.load(f)

    logging.info(f"Loading intersection and traffic situation from disk")
    intersection = Intersection.from_json(
        intersection_dict=json_dict["intersection"])
    arrival_rates = ArrivalRates.from_json(
        arrival_rates_dict=json_dict["arrival_rates"])
    logging.info(f"Loaded intersection and traffic situation from disk")

    logging.info(f"Minimizing period duration")
    fixed_time_schedule, phase_diagram, objective_value, _ = SwiftMobilityCloudApi.get_optimized_fts(
        intersection=intersection,
        arrival_rates=arrival_rates,
        min_period_duration=30,
        max_period_duration=180,
        objective=ObjectiveEnum.min_period)

    logging.info(f"Minimized period duration: {objective_value:.2f} seconds")

    if print_fixed_time_schedule:
        logging.info(fixed_time_schedule)
        logging.info(phase_diagram)
def load_from_smd_and_run():
    """
    Example showing how to:
    - retrieve intersection information and arrival rates from a json file exported from Swift Mobility Desktop.
    - use this information to optimize fixed-time schedules
    
    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].
    
    In this example, we load an intersection from disk (export of Swift Mobility Desktop). This functionality is tested
    with Swift Mobility Desktop 0.7.0.alpha.
    """
    logging.info(f"Running example '{os.path.basename(__file__)}'")
    # absolute path to .json file that has been exported from swift mobility desktop
    smd_export = os.path.join(os.path.join(os.path.abspath(__file__), os.pardir), "example_smd_export.json")

    # retrieve the json structure from the file
    with open(smd_export, "r") as f:
        json_dict = json.load(f)

    logging.info(f"Loading intersection and traffic situation from disk")
    intersection = Intersection.from_json(intersection_dict=json_dict["intersection"])

    arrival_rates = ArrivalRates.from_json(arrival_rates_dict=json_dict["arrival_rates"])
    logging.info(f"Loaded intersection and traffic situation from disk")

    logging.info(f"Minimizing average experienced delay")
    fixed_time_schedule, phase_diagram, objective_value, _ = SwiftMobilityCloudApi.get_optimized_fts(
        intersection=intersection, arrival_rates=arrival_rates, min_period_duration=30, max_period_duration=180,
        objective=ObjectiveEnum.min_delay)

    logging.info(f"Average experienced delay: {objective_value:.2f} 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)
def minimizing_delay(print_fixed_time_schedule: bool = False):
    """
    In this example (given a traffic scenario) we search for the fixed-time schedule that minimizes the average
    delay that road uses (arriving during an horizon of 2 hours) are expected to experience at the intersection.

    Use case:
    This enables real-time optimization of traffic light control allowing truly dynamic and smart traffic
    light control that automatically adapts to the traffic situation. For example, by periodically computing the
    optimal fixed-time schedule, and automatically converting it to a vehicle-actuated controller (e.g., using
    the green times as maximum green times and allowing green times to be terminated prematurely).

    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].

    In this example, we load an intersection from disk (export of Swift Mobility Desktop). This functionality is tested
    with Swift Mobility Desktop 0.7.0.alpha.
    """
    logging.info(f"Running example '{os.path.basename(__file__)}'")
    # absolute path to .json file that has been exported from swift mobility desktop
    smd_export = os.path.join(
        os.path.join(os.path.abspath(__file__), os.pardir),
        "example_smd_export.json")

    # retrieve the json structure from the file
    with open(smd_export, "r") as f:
        json_dict = json.load(f)

    logging.info(f"Loading intersection and traffic situation from disk")
    intersection = Intersection.from_json(
        intersection_dict=json_dict["intersection"])
    arrival_rates = ArrivalRates.from_json(
        arrival_rates_dict=json_dict["arrival_rates"])
    logging.info(f"Loaded intersection and traffic situation from disk")

    logging.info(f"Minimizing delay")
    fixed_time_schedule, phase_diagram, objective_value, _ = SwiftMobilityCloudApi.get_optimized_fts(
        intersection=intersection,
        arrival_rates=arrival_rates,
        min_period_duration=30,
        max_period_duration=180,
        objective=ObjectiveEnum.min_delay,
        horizon=2)

    logging.info(f"Average experienced delay: {objective_value:.2f} seconds")

    if print_fixed_time_schedule:
        logging.info(fixed_time_schedule)
        logging.info(phase_diagram)

    # intersection becomes oversaturated
    scaling_factor = 1.3
    logging.info(
        f"Increasing original amount of traffic with {(scaling_factor - 1) * 100:.2f}%"
    )
    arrival_rates *= scaling_factor
    initial_queue = 25
    logging.info(
        f"Adding initial queue of {initial_queue: d} PCE/cyclists/pedestrians to each queue"
    )
    id_to_queue_lengths = dict()
    for signalgroup in intersection.signalgroups:
        id_to_queue_lengths[signalgroup.id] = [
            initial_queue for _ in signalgroup.traffic_lights
        ]
    initial_queue_lengths = QueueLengths(
        id_to_queue_lengths=id_to_queue_lengths)

    logging.info(f"Minimizing delay")
    fixed_time_schedule, phase_diagram, objective_value, _ = SwiftMobilityCloudApi.get_optimized_fts(
        intersection=intersection,
        arrival_rates=arrival_rates,
        min_period_duration=30,
        max_period_duration=180,
        objective=ObjectiveEnum.min_delay,
        horizon=2,
        initial_queue_lengths=initial_queue_lengths)

    logging.info(f"Average experienced delay: {objective_value:.2f} seconds")

    if print_fixed_time_schedule:
        logging.info(fixed_time_schedule)
        logging.info(phase_diagram)
def tune_fixed_time_schedule(print_fixed_time_schedule: bool = False):
    """
    In this example we show how to tune a fixed-time schedule.

    Use case: Traffic situations change throughout the day. This function allows you to quickly adapt the green times
    of an existing fixed-time schedule to a new traffic situations. This can be used, for example, to adapt the
    maximum greenyellow times of a smart traffic light controller to the current traffic situation in real-time.

    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].

    In this example, we load an intersection from disk (export of Swift Mobility Desktop). This functionality is tested
    with Swift Mobility Desktop 0.7.0.alpha.
    """
    logging.info(f"Running example '{os.path.basename(__file__)}'")
    # absolute path to .json file that has been exported from swift mobility desktop
    smd_export = os.path.join(
        os.path.join(os.path.abspath(__file__), os.pardir),
        "example_smd_export.json")

    # retrieve the json structure from the file
    with open(smd_export, "r") as f:
        json_dict = json.load(f)

    logging.info(f"Loading intersection and traffic situation from disk")
    intersection = Intersection.from_json(
        intersection_dict=json_dict["intersection"])
    arrival_rates = ArrivalRates.from_json(
        arrival_rates_dict=json_dict["arrival_rates"])
    logging.info(f"Loaded intersection and traffic situation from disk")

    logging.info(f"Minimizing delay")
    fixed_time_schedule, phase_diagram, objective_value, _ = SwiftMobilityCloudApi.get_optimized_fts(
        intersection=intersection,
        arrival_rates=arrival_rates,
        min_period_duration=30,
        max_period_duration=180,
        objective=ObjectiveEnum.min_delay,
        horizon=2)

    logging.info(f"Average experienced delay: {objective_value:.2f} seconds")

    if print_fixed_time_schedule:
        logging.info(fixed_time_schedule)
        logging.info(phase_diagram)

    # the more the traffic situation changes, the more effect tuning the fixed-time schedule has. In this example,
    # we only scale the amount of traffic.
    for scaling_factor in [0.95, 0.9, 0.7, 0.4]:
        logging.info(
            f"Evaluating schedule for situation with {(1-scaling_factor)*100 :.1f}% less traffic"
        )

        arrival_rates_scaled = arrival_rates * scaling_factor

        kpis = SwiftMobilityCloudApi.evaluate_fts(
            intersection=intersection,
            fixed_time_schedule=fixed_time_schedule,
            arrival_rates=arrival_rates_scaled,
            horizon=2)

        logging.info(
            f"Average experienced delay without tuning: {kpis.delay:.2f} seconds"
        )

        logging.info(
            f"Tuning schedule for situation with {(1-scaling_factor)*100 :.1f}% less traffic"
        )

        tuned_fixed_time_schedule, objective_value = SwiftMobilityCloudApi.get_tuned_fts(
            intersection=intersection,
            fixed_time_schedule=fixed_time_schedule,
            arrival_rates=arrival_rates_scaled,
            min_period_duration=30,
            max_period_duration=180,
            objective=ObjectiveEnum.min_delay,
            horizon=2)

        logging.info(
            f"Average experienced delay after tuning: {objective_value:.2f} seconds"
        )

        if print_fixed_time_schedule:
            logging.info(fixed_time_schedule)
            logging.info(phase_diagram)
 def get_arrival_rates(signalgroups: List[SignalGroup]):
     id_to_arrival_rates = {
         signalgroup.id: 100
         for signalgroup in signalgroups
     }
     return ArrivalRates(id_to_arrival_rates=id_to_arrival_rates)
Exemple #19
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)
Exemple #20
0
def maximize_intersection_capacity(print_fixed_time_schedule: bool = False):
    """
    In this example (given a traffic scenario) we search for the fixed-time schedule that maximizes the largest
    increase in traffic (scaling factor) that the intersection is able handle without becoming unstable/oversaturated.

    This is very useful information as it gives an indication as to how close the intersection is to being
    oversaturated.
     - An objective value of f < 1 indicates that the intersection is oversaturated for all (!) possible
       fixed-time schedules. For example, if f=0.8 then it is impossible to prevent oversaturation (with any
       traffic light controller!) unless the amount of traffic at the intersection decreases by at least 20%
       (=(1-0.8)*100)).
     - An objective value of > 1 indicates that it is possible to prevent oversaturation at this intersection.
       For example, if f=1.2, then the amount of traffic arriving at the intersection may still increase by 20% without
       the intersection becoming oversaturated (under optimal traffic light control!)

    Usecase 1: Monitoring
    We can in real-time monitor the traffic situation and quantify the amount of traffic arriving at the intersection.
    This information can again be used for traffic management (e.g., redirect traffic to relieve highly congested parts
    of the network).

    Usecase 2: Smart traffic-light control
    Low-traffic and high-traffic situations require a different control strategy. We can periodically evaluate the
    traffic situation in an automated manner (e.g., every 30 minutes). Based on the result (the value of f) we can
    (automatically!) select the control strategy that best matches the current traffic situation;
    this would be truly smart traffic-light control!

    Usecase 3: Quantitative support to decide which traffic-light control to update.
    Suppose traffic flow is not as smooth as desired at an intersection (e.g., queue lengths are large) while we can
    quantify the intersection to have sufficient capacity (e.g., f < 0.8). It, might be sensible to reevaluate the
    currently used traffic-light controller (and potentially update this controller). In this way, we can decide
    which traffic-light controllers need to be updated and focus effort on these controllers.

    On the other hand, if the capacity of the intersection is expected to be insufficient as well (e.g., f > 1.0), then
    this might motivate infrastructural changes (see next usecase).

    Usecase 4: Support for strategic decision making on infrastructural changes to the road network.
    Traffic situations may change overtime (e.g., due to urban development). Therefore, it is very important to
    periodically evaluate if any infrastructural changes (or policy changes by the government) are needed.

    This is a very difficult decision to be made with high impact; quantitative support is really useful when making
    these decisions. It is now possible, to evaluate the maximum traffic increase that the intersection/infrastructure
    is able to handle under optimal traffic light control. This could be used to answer questions like: is the
    capacity of our infrastructure (intersection) expected to still be sufficient in 3 years?

    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].

    In this example, we load an intersection from disk (export of Swift Mobility Desktop). This functionality is tested
    with Swift Mobility Desktop 0.7.0.alpha.
    """
    logging.info(f"Running example '{os.path.basename(__file__)}'")
    # absolute path to .json file that has been exported from swift mobility desktop
    smd_export = os.path.join(
        os.path.join(os.path.abspath(__file__), os.pardir),
        "example_smd_export.json")

    # retrieve the json structure from the file
    with open(smd_export, "r") as f:
        json_dict = json.load(f)

    logging.info(f"Loading intersection and traffic situation from disk")
    intersection = Intersection.from_json(
        intersection_dict=json_dict["intersection"])
    arrival_rates = ArrivalRates.from_json(
        arrival_rates_dict=json_dict["arrival_rates"])
    logging.info(f"Loaded intersection and traffic situation from disk")

    logging.info(f"Maximizing capacity of the intersection")
    fixed_time_schedule, phase_diagram, objective_value, _ = SwiftMobilityCloudApi.get_optimized_fts(
        intersection=intersection,
        arrival_rates=arrival_rates,
        min_period_duration=30,
        max_period_duration=180,
        objective=ObjectiveEnum.max_capacity)

    logging.info(
        f"Maximum sustainable increase in traffic {(objective_value - 1) * 100:.2f}%"
    )

    if print_fixed_time_schedule:
        logging.info(fixed_time_schedule)
        logging.info(phase_diagram)

    scaling_factor = 1.2
    logging.info(
        f"Increasing original amount of traffic with {(scaling_factor - 1) * 100:.2f}%"
    )
    arrival_rates *= scaling_factor
    logging.info(
        f"Expected maximum sustainable increase: {(objective_value/scaling_factor - 1) * 100:.2f}%"
    )

    logging.info(
        f"Maximizing capacity of the intersection with scaled traffic")
    fixed_time_schedule, phase_diagram, objective_value, _ = SwiftMobilityCloudApi.get_optimized_fts(
        intersection=intersection,
        arrival_rates=arrival_rates,
        min_period_duration=30,
        max_period_duration=180,
        objective=ObjectiveEnum.max_capacity)

    # objective_value < 1 implies that the intersection is oversaturated for any traffic light controller.
    logging.info(
        f"Computed maximum sustainable increase in traffic: {(objective_value - 1) * 100:.2f}%"
    )

    if print_fixed_time_schedule:
        logging.info(fixed_time_schedule)
        logging.info(phase_diagram)
Exemple #21
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)