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
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
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)
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")
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