Пример #1
0
def spatialite_connection(conn):
    conn.enable_load_extension(True)
    par = Parameters()
    spatialite_path = par.parameters["system"]["spatialite_path"]
    if spatialite_path not in os.environ['PATH']:
        os.environ['PATH'] = spatialite_path + ';' + os.environ['PATH']
    try:
        conn.load_extension("mod_spatialite")
    except Exception as e:
        logger.warn(
            f"AequilibraE might not work as intended without spatialite. {e.args}"
        )
    return conn
Пример #2
0
    def calculate_stepsize(self):
        """Calculate optimal stepsize in descent direction"""
        if self.algorithm == "msa":
            self.stepsize = 1.0 / self.iter
            return

        def derivative_of_objective(stepsize):
            x = self.fw_total_flow + stepsize * (self.step_direction_flow - self.fw_total_flow)

            self.vdf.apply_vdf(self.congested_value, x, self.capacity, self.free_flow_tt, *self.vdf_parameters)
            return np.sum(self.congested_value * (self.step_direction_flow - self.fw_total_flow))

        try:
            min_res = root_scalar(derivative_of_objective, bracket=[0, 1])
            self.stepsize = min_res.root
            if not min_res.converged:
                logger.warn("Descent direction stepsize finder is not converged")
        except ValueError:
            # We can have iterations where the objective function is not *strictly* convex, but the scipy method cannot deal
            # with this. Stepsize is then either given by 1 or 0, depending on where the objective function is smaller.
            # However, using zero would mean the overall solution would not get updated, and therefore we assert the stepsize
            # in order to add a small fraction of the AoN. A heuristic value equal to the corresponding MSA step size
            # seems to work well in practice.
            if derivative_of_objective(0.0) < derivative_of_objective(1.0):
                if self.algorithm == "frank-wolfe":
                    heuristic_stepsize_at_zero = 1.0 / self.iter
                    logger.warn("# Alert: Adding {} to stepsize to make it non-zero".format(heuristic_stepsize_at_zero))
                    self.stepsize = heuristic_stepsize_at_zero
                else:
                    # for cf/bfw: don't add a bad step, just reset the stepdirection calculation to start with fw again
                    # TODO: test which works better, msa stepsize or not adding anything
                    self.stepsize = 0.0
                    # need to reset conjugate / bi-conjugate direction search
                    self.do_fw_step = True
            else:
                # Do we want to keep some of the old solution, or just throw away everything?
                self.stepsize = 1.0

        assert 0 <= self.stepsize <= 1.0
Пример #3
0
from aequilibrae.paths.traffic_class import TrafficClass
from aequilibrae.paths.results import AssignmentResults
from aequilibrae.paths.all_or_nothing import allOrNothing
from aequilibrae.paths.AoN import linear_combination, linear_combination_skims
from aequilibrae.paths.AoN import triple_linear_combination, triple_linear_combination_skims
from aequilibrae.paths.AoN import copy_one_dimension, copy_two_dimensions, copy_three_dimensions
from aequilibrae import logger
import scipy
if int(scipy.__version__.split('.')[1]) >= 3:
    from scipy.optimize import root_scalar
    recent_scipy = True
else:
    from scipy.optimize import root as root_scalar
    recent_scipy = False
    logger.warn(
        f"Using older version of Scipy. For better performance, use Scipy >= 1.4"
    )

if False:
    from aequilibrae.paths.traffic_assignment import TrafficAssignment

spec = iutil.find_spec("PyQt5")
pyqt = spec is not None
if pyqt:
    from PyQt5.QtCore import pyqtSignal as SIGNAL


class LinearApproximation(WorkerThread):
    if pyqt:
        equilibration = SIGNAL(object)
        assignment = SIGNAL(object)
Пример #4
0
    def create_from_osm(
            self,
            west: float = None,
            south: float = None,
            east: float = None,
            north: float = None,
            place_name: str = None,
            modes=["car", "transit", "bicycle", "walk"],
            spatial_index=False,
    ) -> None:

        if self._check_if_exists():
            raise FileExistsError("You can only import an OSM network into a brand new model file")

        self.create_empty_tables()

        curr = self.conn.cursor()
        curr.execute("""ALTER TABLE links ADD COLUMN osm_id integer""")
        curr.execute("""ALTER TABLE nodes ADD COLUMN osm_id integer""")
        self.conn.commit()

        if isinstance(modes, (tuple, list)):
            modes = list(modes)
        elif isinstance(modes, str):
            modes = [modes]
        else:
            raise ValueError("'modes' needs to be string or list/tuple of string")

        if place_name is None:
            if min(east, west) < -180 or max(east, west) > 180 or min(north, south) < -90 or max(north, south) > 90:
                raise ValueError("Coordinates out of bounds")
            bbox = [west, south, east, north]
        else:
            bbox, report = placegetter(place_name)
            west, south, east, north = bbox
            if bbox is None:
                msg = f'We could not find a reference for place name "{place_name}"'
                warn(msg)
                logger.warn(msg)
                return
            for i in report:
                if "PLACE FOUND" in i:
                    logger.info(i)

        # Need to compute the size of the bounding box to not exceed it too much
        height = haversine((east + west) / 2, south, (east + west) / 2, north)
        width = haversine(east, (north + south) / 2, west, (north + south) / 2)
        area = height * width

        if area < max_query_area_size:
            polygons = [bbox]
        else:
            polygons = []
            parts = math.ceil(area / max_query_area_size)
            horizontal = math.ceil(math.sqrt(parts))
            vertical = math.ceil(parts / horizontal)
            dx = east - west
            dy = north - south
            for i in range(horizontal):
                xmin = max(-180, west + i * dx)
                xmax = min(180, west + (i + 1) * dx)
                for j in range(vertical):
                    ymin = max(-90, south + j * dy)
                    ymax = min(90, south + (j + 1) * dy)
                    box = [xmin, ymin, xmax, ymax]
                    polygons.append(box)

        logger.info("Downloading data")
        self.downloader = OSMDownloader(polygons, modes)
        self.downloader.doWork()

        logger.info("Building Network")
        self.builder = OSMBuilder(self.downloader.json, self.conn)
        self.builder.doWork()

        if spatial_index:
            logger.info("Adding spatial indices")
            self.add_spatial_index()

        self.add_triggers()
        logger.info("Network built successfully")
Пример #5
0
import sys
import threading
from multiprocessing.dummy import Pool as ThreadPool
from .multi_threaded_skimming import MultiThreadedNetworkSkimming
from ..utils import WorkerThread
import importlib.util as iutil
from aequilibrae import logger

try:
    from aequilibrae.paths.AoN import skimming_single_origin
except ImportError as ie:
    logger.warn(f'Could not import procedures from the binary. {ie.args}')

spec = iutil.find_spec("PyQt5")
pyqt = spec is not None
if pyqt:
    from PyQt5.QtCore import pyqtSignal

sys.dont_write_bytecode = True


class NetworkSkimming(WorkerThread):
    if pyqt:
        skimming = pyqtSignal(object)

    def __init__(self, graph, results, origins=None):
        WorkerThread.__init__(self, None)

        self.origins = origins
        self.graph = graph
        self.results = results