예제 #1
0
    def set_algorithm(self, algorithm: str):
        """
        Chooses the assignment algorithm. e.g. 'frank-wolfe', 'bfw', 'msa'

        'fw' is also accepted as an alternative to 'frank-wolfe'

        Args:
            algorithm (:obj:`list`): Algorithm to be used
        """

        # First we instantiate the arrays we will be using over and over

        algo_dict = {i: i for i in self.all_algorithms}
        algo_dict["fw"] = "frank-wolfe"
        algo = algo_dict.get(algorithm.lower())

        if algo is None:
            raise AttributeError(
                f"Assignment algorithm not available. Choose from: {','.join(self.all_algorithms)}"
            )

        if algo == "all-or-nothing":
            self.assignment = allOrNothing(self)
        elif algo in ["msa", "frank-wolfe", "cfw", "bfw"]:
            self.assignment = LinearApproximation(self, algo)
        else:
            raise Exception("Algorithm not listed in the case selection")

        self.__dict__["algorithm"] = algo

        self.__collect_data()
    def test_execute(self):
        # Loads and prepares the graph
        res1 = AssignmentResults()
        res1.prepare(self.g, self.matrix)
        assig1 = allOrNothing(self.matrix, self.g, res1)
        assig1.execute()

        res2 = AssignmentResults()
        res2.prepare(self.g, self.matrix2)
        assig2 = allOrNothing(self.matrix2, self.g, res2)
        assig2.execute()

        load1 = res1.get_load_results()
        load2 = res2.get_load_results()

        self.assertEqual(list(load1.matrix_tot * 2), list(load2.matrix_tot),
                         "Something wrong with the AoN")
    def test_skimming_on_assignment(self):

        res = AssignmentResults()

        res.prepare(self.g, self.matrix)

        self.g.set_skimming([])
        self.g.set_blocked_centroid_flows(True)
        assig = allOrNothing(self.matrix, self.g, res)
        assig.execute()

        if res.skims.distance.sum() > 0:
            self.fail(
                "skimming for nothing during assignment returned something different than zero"
            )

        res.prepare(self.g, self.matrix)

        assig = allOrNothing(self.matrix, self.g, res)
        assig.execute()
예제 #4
0
    def set_algorithm(self, algorithm: str):
        """
        Chooses the assignment algorithm. e.g. 'frank-wolfe', 'bfw', 'msa'
        """

        # First we instantiate the arrays we will be using over and over
        if algorithm not in self.all_algorithms:
            raise AttributeError(
                f"Assignment algorithm not available. Choose from: {','.join(self.all_algorithms)}"
            )

        if algorithm.lower() == "all-or-nothing":
            self.assignment = allOrNothing(self)
        elif algorithm.lower() in ["msa", "frank-wolfe", "cfw", "bfw"]:
            self.assignment = LinearApproximation(self, algorithm.lower())
        else:
            raise Exception('Algorithm not listed in the case selection')

        self.__collect_data()
예제 #5
0
    def execute(self):
        for c in self.traffic_classes:
            c.graph.set_graph(self.time_field)

        logger.info("{} Assignment STATS".format(self.algorithm))
        logger.info("Iteration, RelativeGap, stepsize")
        for self.iter in range(1, self.max_iter + 1):
            if pyqt:
                self.equilibration.emit(['rgap', self.rgap])
                self.equilibration.emit(['iterations', self.iter])
            flows = []
            aon_flows = []

            for c in self.traffic_classes:
                aon = allOrNothing(c.matrix, c.graph, c._aon_results)
                if pyqt:
                    aon.assignment.connect(self.signal_handler)
                aon.execute()
                c._aon_results.total_flows()
                aon_flows.append(c._aon_results.total_link_loads * c.pce)
            self.aon_total_flow = np.sum(aon_flows, axis=0)

            if self.iter == 1:
                for c in self.traffic_classes:
                    copy_two_dimensions(c.results.link_loads,
                                        c._aon_results.link_loads, self.cores)
                    c.results.total_flows()
                    copy_one_dimension(c.results.total_link_loads,
                                       c._aon_results.total_link_loads,
                                       self.cores)
                    if c.results.num_skims > 0:
                        copy_three_dimensions(c.results.skims.matrix_view,
                                              c._aon_results.skims.matrix_view,
                                              self.cores)
                    flows.append(c.results.total_link_loads * c.pce)
            else:
                self.__calculate_step_direction()
                self.calculate_stepsize()
                for c in self.traffic_classes:
                    stp_dir = self.step_direction[c.mode]
                    cls_res = c.results
                    linear_combination(cls_res.link_loads, stp_dir.link_loads,
                                       cls_res.link_loads, self.stepsize,
                                       self.cores)
                    if cls_res.num_skims > 0:
                        linear_combination_skims(cls_res.skims.matrix_view,
                                                 stp_dir.skims.matrix_view,
                                                 cls_res.skims.matrix_view,
                                                 self.stepsize, self.cores)
                    cls_res.total_flows()
                    flows.append(cls_res.total_link_loads * c.pce)

            self.fw_total_flow = np.sum(flows, axis=0)

            # Check convergence
            # This needs ot be done with the current costs, and not the future ones
            if self.iter > 1:
                if self.check_convergence():
                    if self.steps_below >= self.steps_below_needed_to_terminate:
                        break
                    else:
                        self.steps_below += 1

            self.vdf.apply_vdf(self.congested_time, self.fw_total_flow,
                               self.capacity, self.free_flow_tt,
                               *self.vdf_parameters)

            for c in self.traffic_classes:
                c.graph.cost = self.congested_time
                if self.time_field in c.graph.skim_fields:
                    idx = c.graph.skim_fields.index(self.time_field)
                    c.graph.skims[:, idx] = self.congested_time[:]
                c._aon_results.reset()
            logger.info("{},{},{}".format(self.iter, self.rgap, self.stepsize))

        if self.rgap > self.rgap_target:
            logger.error("Desired RGap of {} was NOT reached".format(
                self.rgap_target))
        logger.info(
            f"{self.algorithm} Assignment finished. {self.iter} iterations and {self.rgap} final gap"
        )
        if pyqt:
            self.equilibration.emit(['rgap', self.rgap])
            self.equilibration.emit(['iterations', self.iter])
            self.equilibration.emit(['finished_threaded_procedure'])
예제 #6
0
    def execute(self):
        for c in self.traffic_classes:
            c.graph.set_graph(self.time_field)

        logger.info(f"{self.algorithm} Assignment STATS")
        logger.info("Iteration, RelativeGap, stepsize")
        for self.iter in range(1, self.max_iter + 1):
            self.iteration_issue = []
            if pyqt:
                self.equilibration.emit(["rgap", self.rgap])
                self.equilibration.emit(["iterations", self.iter])

            aon_flows = []
            for c in self.traffic_classes:
                aon = allOrNothing(c.matrix, c.graph, c._aon_results)
                if pyqt:
                    aon.assignment.connect(self.signal_handler)
                aon.execute()
                aon_flows.append(c._aon_results.total_link_loads * c.pce)
            self.aon_total_flow = np.sum(aon_flows, axis=0)

            flows = []
            if self.iter == 1:
                for c in self.traffic_classes:
                    copy_two_dimensions(c.results.link_loads,
                                        c._aon_results.link_loads, self.cores)
                    copy_one_dimension(c.results.total_link_loads,
                                       c._aon_results.total_link_loads,
                                       self.cores)
                    if c.results.num_skims > 0:
                        copy_three_dimensions(c.results.skims.matrix_view,
                                              c._aon_results.skims.matrix_view,
                                              self.cores)
                    flows.append(c.results.total_link_loads * c.pce)
            else:
                self.__calculate_step_direction()
                self.calculate_stepsize()
                for c in self.traffic_classes:
                    stp_dir = self.step_direction[c.mode]
                    cls_res = c.results
                    linear_combination(cls_res.link_loads, stp_dir.link_loads,
                                       cls_res.link_loads, self.stepsize,
                                       self.cores)
                    if cls_res.num_skims > 0:
                        linear_combination_skims(
                            cls_res.skims.matrix_view,
                            stp_dir.skims.matrix_view,
                            cls_res.skims.matrix_view,
                            self.stepsize,
                            self.cores,
                        )
                    cls_res.total_flows()
                    flows.append(cls_res.total_link_loads * c.pce)

            self.fw_total_flow = np.sum(flows, axis=0)

            # Check convergence
            # This needs to be done with the current costs, and not the future ones
            converged = False
            if self.iter > 1:
                converged = self.check_convergence()

            self.convergence_report["iteration"].append(self.iter)
            self.convergence_report["rgap"].append(self.rgap)
            self.convergence_report["warnings"].append("; ".join(
                self.iteration_issue))
            self.convergence_report["alpha"].append(self.stepsize)

            if self.algorithm == "bfw":
                self.convergence_report["beta0"].append(self.betas[0])
                self.convergence_report["beta1"].append(self.betas[1])
                self.convergence_report["beta2"].append(self.betas[2])

            logger.info(f"{self.iter},{self.rgap},{self.stepsize}")
            if converged:
                if self.steps_below >= self.steps_below_needed_to_terminate:
                    break
                else:
                    self.steps_below += 1

            self.vdf.apply_vdf(
                self.congested_time,
                self.fw_total_flow,
                self.capacity,
                self.free_flow_tt,
                *self.vdf_parameters,
                self.cores,
            )

            for c in self.traffic_classes:
                aggregate_link_costs(self.congested_time, c.graph.compact_cost,
                                     c.results.crosswalk)
                if self.time_field in c.graph.skim_fields:
                    idx = c.graph.skim_fields.index(self.time_field)
                    c.graph.skims[:, idx] = self.congested_time[:]
                c._aon_results.reset()

        if self.rgap > self.rgap_target:
            logger.error(f"Desired RGap of {self.rgap_target} was NOT reached")
        logger.info(
            f"{self.algorithm} Assignment finished. {self.iter} iterations and {self.rgap} final gap"
        )
        if pyqt:
            self.equilibration.emit(["rgap", self.rgap])
            self.equilibration.emit(["iterations", self.iter])
            self.equilibration.emit(["finished_threaded_procedure"])
    def execute(self):
        # We build the fixed cost field
        for c in self.traffic_classes:
            if c.fixed_cost_field:
                # divide fixed cost by volume-dependent prefactor (vot) such that we don't have to do it for
                # each occurence in the objective funtion. TODO: Need to think about cost skims here, we do
                # not want this there I think
                c.fixed_cost[c.graph.graph.__supernet_id__] = (
                    c.graph.graph[c.fixed_cost_field].values[:] *
                    c.fc_multiplier / c.vot)
                c.fixed_cost[np.isnan(c.fixed_cost)] = 0

        # TODO: Review how to eliminate this. It looks unnecessary
        # Just need to create some arrays for cost
        for c in self.traffic_classes:
            c.graph.set_graph(self.time_field)

        logger.info(f"{self.algorithm} Assignment STATS")
        logger.info("Iteration, RelativeGap, stepsize")
        for self.iter in range(1, self.max_iter + 1):
            self.iteration_issue = []
            if pyqt:
                self.equilibration.emit(["rgap", self.rgap])
                self.equilibration.emit(["iterations", self.iter])

            aon_flows = []

            self.__maybe_create_path_file_directories()

            for c in self.traffic_classes:  # type: TrafficClass
                # cost = c.fixed_cost / c.vot + self.congested_time #  now only once
                cost = c.fixed_cost + self.congested_time
                aggregate_link_costs(cost, c.graph.compact_cost,
                                     c.results.crosswalk)

                aon = allOrNothing(c.matrix, c.graph, c._aon_results)
                if pyqt:
                    aon.assignment.connect(self.signal_handler)
                aon.execute()
                c._aon_results.link_loads *= c.pce
                c._aon_results.total_flows()
                aon_flows.append(c._aon_results.total_link_loads)

            self.aon_total_flow = np.sum(aon_flows, axis=0)

            flows = []
            if self.iter == 1:
                for c in self.traffic_classes:
                    copy_two_dimensions(c.results.link_loads,
                                        c._aon_results.link_loads, self.cores)
                    c.results.total_flows()
                    if c.results.num_skims > 0:
                        copy_three_dimensions(c.results.skims.matrix_view,
                                              c._aon_results.skims.matrix_view,
                                              self.cores)
                    flows.append(c.results.total_link_loads)

                if self.algorithm == "all-or-nothing":
                    break

            else:
                self.__calculate_step_direction()
                self.calculate_stepsize()
                for c in self.traffic_classes:
                    stp_dir = self.step_direction[c.__id__]
                    cls_res = c.results
                    linear_combination(cls_res.link_loads, stp_dir.link_loads,
                                       cls_res.link_loads, self.stepsize,
                                       self.cores)

                    if cls_res.num_skims > 0:
                        linear_combination_skims(
                            cls_res.skims.matrix_view,
                            stp_dir.skims.matrix_view,
                            cls_res.skims.matrix_view,
                            self.stepsize,
                            self.cores,
                        )
                    cls_res.total_flows()
                    flows.append(cls_res.total_link_loads)
            self.fw_total_flow = np.sum(flows, axis=0)

            # Check convergence
            # This needs to be done with the current costs, and not the future ones
            converged = self.check_convergence() if self.iter > 1 else False

            self.vdf.apply_vdf(
                self.congested_time,
                self.fw_total_flow,
                self.capacity,
                self.free_flow_tt,
                *self.vdf_parameters,
                self.cores,
            )

            self.convergence_report["iteration"].append(self.iter)
            self.convergence_report["rgap"].append(self.rgap)
            self.convergence_report["warnings"].append("; ".join(
                self.iteration_issue))
            self.convergence_report["alpha"].append(self.stepsize)

            if self.algorithm in ["cfw", "bfw"]:
                self.convergence_report["beta0"].append(self.betas[0])
                self.convergence_report["beta1"].append(self.betas[1])
                self.convergence_report["beta2"].append(self.betas[2])

            for c in self.traffic_classes:
                c._aon_results.reset()
                if self.time_field not in c.graph.skim_fields:
                    continue
                idx = c.graph.skim_fields.index(self.time_field)
                c.graph.skims[:, idx] = self.congested_time[:]

            logger.info(f"{self.iter},{self.rgap},{self.stepsize}")
            if converged:
                self.steps_below += 1
                if self.steps_below >= self.steps_below_needed_to_terminate:
                    break
            else:
                self.steps_below = 0

        for c in self.traffic_classes:
            c.results.link_loads /= c.pce
            c.results.total_flows()

        # TODO (Jan 18/4/21): Do we want to blob store path files (by iteration, class, origin, destination) in sqlite?
        # or do we just use one big hdf5 file?

        if (self.rgap > self.rgap_target) and (self.algorithm !=
                                               "all-or-nothing"):
            logger.error(f"Desired RGap of {self.rgap_target} was NOT reached")
        logger.info(
            f"{self.algorithm} Assignment finished. {self.iter} iterations and {self.rgap} final gap"
        )
        if pyqt:
            self.equilibration.emit(["rgap", self.rgap])
            self.equilibration.emit(["iterations", self.iter])
            self.equilibration.emit(["finished_threaded_procedure"])
예제 #8
0
    def execute(self):

        for c in self.traffic_classes:
            c.graph.set_graph(self.time_field)

        logger.info("{} Assignment STATS".format(self.algorithm))
        logger.info("Iteration, RelativeGap, stepsize")
        for self.iter in range(1, self.max_iter + 1):
            flows = []
            aon_flows = []

            for c in self.traffic_classes:
                aon = allOrNothing(c.matrix, c.graph, c._aon_results)
                aon.execute()
                c._aon_results.total_flows()
                aon_flows.append(c._aon_results.total_link_loads * c.pce)
            self.aon_total_flow = np.sum(aon_flows, axis=0)

            if self.iter == 1:
                for c in self.traffic_classes:
                    copy_two_dimensions(c.results.link_loads, c._aon_results.link_loads, self.cores)
                    c.results.total_flows()
                    copy_one_dimension(c.results.total_link_loads, c._aon_results.total_link_loads, self.cores)
                    if c.results.num_skims > 0:
                        copy_three_dimensions(c.results.skims.matrix_view, c._aon_results.skims.matrix_view, self.cores)
                    flows.append(c.results.total_link_loads * c.pce)
            else:
                self.__calculate_step_direction()
                self.calculate_stepsize()
                for c in self.traffic_classes:
                    stp_dir = self.step_direction[c.mode]
                    cls_res = c.results
                    linear_combination(cls_res.link_loads, stp_dir.link_loads, cls_res.link_loads, self.stepsize,
                                       self.cores)
                    # TODO: We need to compute the step direction for skims as well.
                    #       It is probably a matter of transforming the step_direction values from numpy arrays to
                    #       full AssignmentResults() ones, and cleaning the stuff we don't need
                    if cls_res.num_skims > 0:
                        linear_combination_skims(cls_res.skims.matrix_view,
                                                 stp_dir.skims.matrix_view,
                                                 cls_res.skims.matrix_view,
                                                 self.stepsize,
                                                 self.cores)
                    cls_res.total_flows()
                    flows.append(cls_res.total_link_loads * c.pce)

            self.fw_total_flow = np.sum(flows, axis=0)

            # Check convergence
            # This needs ot be done with the current costs, and not the future ones
            if self.iter > 1:
                if self.check_convergence():
                    if self.steps_below >= self.steps_below_needed_to_terminate:
                        break
                    else:
                        self.steps_below += 1

            self.vdf.apply_vdf(
                self.congested_time, self.fw_total_flow, self.capacity, self.free_flow_tt, *self.vdf_parameters
            )

            for c in self.traffic_classes:
                c.graph.cost = self.congested_time
                c._aon_results.reset()
            logger.info("{},{},{}".format(self.iter, self.rgap, self.stepsize))

        if self.rgap > self.rgap_target:
            logger.error("Desired RGap of {} was NOT reached".format(self.rgap_target))
        logger.info(
            "{} Assignment finished. {} iterations and {} final gap".format(self.algorithm, self.iter, self.rgap)
        )