Exemple #1
0
    def _build_stops(self, riders: Dict[str, Rider], depots: Dict[str, Depot],
                     starts: List[int], ends: List[int]) -> List[Stop]:
        """Method to build Stops from locations of Riders and Depots"""

        stop_groups = defaultdict(list)
        for rider_id, rider in riders.items():
            geohash = rider.location.extract_geohash(
                precision=self._params.GEOHASH_PRECISION_GROUPING)
            stop_groups[geohash] += [rider_id]

        stops = [
            Stop(riders={rider_id: riders[rider_id]
                         for rider_id in rider_ids})
            for rider_ids in stop_groups.values()
        ]
        logging.info(
            f'Built {len(stops)} rider stops from {len(riders)} riders.')
        depot_stops = [
            Stop(depot_id=depot.depot_id, location=depot.location)
            for depot_ix, depot in enumerate(depots.values())
            if depot_ix in starts or depot_ix in ends
        ]
        logging.info(
            f'Built {len(depot_stops)} depot stops from {len(depots)} depots.')

        return depot_stops + stops
    def make_random_stop(self):
        new_stop = Stop()
        new_stop.name = "Stop 23"
        new_stop.latitude = 2.144
        new_stop.longitude = -1.222

        return new_stop
Exemple #3
0
    def test_linear_estimator_estimate(self):
        """Asserts linear estimations are correctly calculated"""

        stop_1 = Stop(
            depot_id='depot_1',
            location=Location(lat=4.720634, lng=-74.037228)
        )
        stop_2 = Stop(
            depot_id='depot_2',
            location=Location(lat=4.708958, lng=-74.035172)
        )
        estimator = LinearEstimator()
        estimations = estimator.estimate(stops=[stop_1, stop_2])
        self.assertEqual(
            len(estimations), 4,
            msg='Number of estimations incorrect.'
        )

        expected_estimation = round(
                haversine(
                    point1=stop_1.location.coordinates,
                    point2=stop_2.location.coordinates
                ) / DEFAULT_VELOCITY
        )
        for (origin, destination), est in estimations.items():
            if origin == destination:
                self.assertEqual(
                    est, 0.,
                    msg='Same origin and destination has non-zero estimation.'
                )
            else:
                self.assertEqual(
                    round(est), expected_estimation,
                    msg='Estimated linear time differs to distance / velocity.'
                )
Exemple #4
0
def update_services_stops():

    # Delete all data first
    delete_services_stops()

    # Get services as json data
    json_data = requests.get(API_SERVICES, headers=API_HEADER)
    service_dict = json.loads(json_data.text)

    # Array of service objects
    services = service_dict["services"]

    # Get stops as json data
    json_data = requests.get(API_STOPS, headers=API_HEADER)
    stop_dict = json.loads(json_data.text)

    # Array of stop objects
    stops = stop_dict["stops"]

    # Update the tables' last_updated field
    service_date = datetime.fromtimestamp(int(service_dict["last_updated"]))
    update_table_date("service", service_date)
    stop_date = datetime.fromtimestamp(int(stop_dict["last_updated"]))
    update_table_date("stop", stop_date)

    # Create a service instance of each service and store them in a new dictionary
    service_dict = {}
    for service in services:
        new_service = Service()
        new_service.name = service["name"]
        new_service.service_type = service["service_type"]
        new_service.description = service["description"]
        new_service.route = json.dumps(service["routes"][0]["points"]) if len(service["routes"]) > 0 else "none"
        service_dict[service["name"]] = new_service
        db_session.add(new_service)

    # Create a stop instance of each stop and add corresponding services to them
    for stop in stops:
        new_stop = Stop()
        new_stop.name = stop["name"]
        new_stop.latitude = stop["latitude"]
        new_stop.longitude = stop["longitude"]

        # Add services to stops
        # Must take the set because sometimes the services are listed multiple times for a particular stop.
        stop_services = set(stop["services"])
        for service_name in stop_services:
            new_stop.services.append(service_dict[service_name])

        db_session.add(new_stop)

    db_session.commit()
    db_session.flush()
Exemple #5
0
 def fetch_routes(self, stop):
     params = {
         "filter[stop]": stop,
         "filter[type]": 2,
         "include": "stop",
     }
     routes, included = self.fetch(path="routes", params=params)
     return [Route(r) for r in routes], Stop(included[0])
Exemple #6
0
    def test_to_dict(self):
        """Asserts the Stop is correctly parsed to a Dict"""

        depot_stop = Stop(depot_id='my_depot',
                          location=Location(lat=1.23, lng=4.56))
        depot_stop_dict = depot_stop.to_dict()
        self.assertEqual(
            depot_stop.depot_id,
            depot_stop_dict['depot_id'],
            msg='Depot stop has incorrect depot_id after parsing.')
        self.assertEqual(
            depot_stop.location.coordinates,
            depot_stop_dict['location'],
            msg='Depot stop has incorrect location after parsing.')
        self.assertIsNone(depot_stop_dict['riders'],
                          msg='Depot stop has non-null riders.')

        riders_stop = Stop(
            riders={
                'my_rider':
                Rider(location=Location(lat=1.23, lng=4.56),
                      rider_id='my_rider')
            })
        riders_stop_dict = riders_stop.to_dict()
        self.assertIsNone(riders_stop_dict['depot_id'],
                          msg='Riders stop has non-null depot_id.')
        self.assertEqual(
            depot_stop.location.coordinates,
            riders_stop_dict['location'],
            msg='Riders stop has incorrect location after parsing.')
        self.assertIsNotNone(riders_stop_dict['riders'],
                             msg='Riders stop has null riders.')
Exemple #7
0
    def test_post_init(self):
        """Assert the actions taken after the class is instantiated"""

        riders = parse_models(model_dicts=test_riders[0:2], cls=Rider)
        stop = Stop(riders=riders)

        self.assertEqual(stop.demand,
                         len(riders),
                         msg='Stop has demand that differs from riders.')
        self.assertEqual(
            stop.location.lat,
            mean([rider.location.lat for rider in riders.values()]),
            msg='Latitude incorrectly calculated for Stop.')
        self.assertEqual(
            stop.location.lng,
            mean([rider.location.lng for rider in riders.values()]),
            msg='Longitude incorrectly calculated for Stop.')
Exemple #8
0
async def nearby_stops(lat: float, lon: float, radius: float,
                       pool) -> List[Stop]:
    async with pool.acquire() as conn:
        query = f"""select q.lat, q.lon
                    from (select (st_distance(st_transform(st_setsrid(s.geopoint, 4326)::geometry, 3857),
                                              st_transform(ST_SetSRID(st_makepoint({lon}, {lat}), 4326)::geometry, 3857))) as d,
                                 s.lat,
                                 s.lon
                          from stop s
                         ) as q
                    where q.d < {radius};
                """

        rows = await conn.fetch(query)

        return [
            Stop(Coordinates(float(r['lat']), float(r['lon'])), arrivals=[])
            for r in rows
        ]
Exemple #9
0
class TestsOptimizationModelBuilder(unittest.TestCase):
    """Tests for the Optimization Model Builder class"""

    # Base Problem
    riders = parse_models(model_dicts=test_riders[0:2], cls=Rider)
    vehicles = parse_models(model_dicts=test_vehicles, cls=Vehicle)
    depots = parse_models(model_dicts=test_depots, cls=Depot)
    stops = [
        Stop(depot_id=list(depots.values())[0].depot_id,
             location=list(depots.values())[0].location),
        Stop(riders=riders)
    ]
    estimations = {(0, 0): 0., (0, 1): 85., (1, 0): 78., (1, 1): 0.}
    params = get_params()
    problem = Problem(depots=depots,
                      estimations=estimations,
                      params=params,
                      riders=riders,
                      stops=stops,
                      vehicles=vehicles,
                      starts=[0, 1],
                      ends=[0, 1])

    def test_build_manager(self):
        """Asserts that a manager is built correctly from the Problem"""

        manager = RoutingIndexManager(
            len(self.problem.stops),  # Number of locations
            len(self.problem.vehicles),  # Number of vehicles
            self.problem.starts,  # Start list of Vehicles
            self.problem.ends  # End list of Vehicles
        )
        self.assertTrue(manager, msg='Opt. Manager could not be built.')
        self.assertEqual(manager.GetNumberOfVehicles(),
                         len(self.vehicles),
                         msg='Number of vehicles in manager is incorrect.')
        self.assertEqual(manager.GetNumberOfIndices(),
                         len(self.vehicles) * 2 + len(self.stops) -
                         len(self.problem.depots),
                         msg='Number of indices in manager is incorrect.')
        solver = RoutingModel(manager)
        self.assertTrue(solver, msg='Solver could not be instantiated.')

    def test_build_search_parameters(self):
        """Asserts the heuristic search parameters are correctly created"""

        search_parameters = OptimizationModelBuilder._build_search_parameters(
            self.problem)
        self.assertTrue(search_parameters,
                        msg='Search params could not be built.')
        self.assertEqual(search_parameters.time_limit,
                         Duration(seconds=self.params.SEARCH_TIME_LIMIT),
                         msg='Time limit is incorrect in the search params.')
        self.assertEqual(
            search_parameters.solution_limit,
            self.params.SEARCH_SOLUTIONS_LIMIT,
            msg='Solutions limit is incorrect in the search params.')
        self.assertEqual(
            search_parameters.first_solution_strategy,
            FIRST_SOLUTION_STRATEGY[self.params.FIRST_SOLUTION_STRATEGY],
            msg='First solution strategy is incorrect in the search params.')
        self.assertEqual(
            search_parameters.local_search_metaheuristic,
            LOCAL_SEARCH_METAHEURISTIC[self.params.SEARCH_METAHEURISTIC],
            msg='Search metaheuristic is incorrect in the search params.')

    def test_apply_constraints_capacity_constraint(self):
        """Asserts constraints are read correctly by the solver"""

        model_builder = OptimizationModelBuilder(
            constraints=[CapacityConstraint()])
        problem = self.problem
        manager = RoutingIndexManager(
            len(problem.stops),  # Number of locations
            len(problem.vehicles),  # Number of vehicles
            problem.starts,  # Start list of Vehicles
            problem.ends  # End list of Vehicles
        )
        solver = RoutingModel(manager)
        model_builder._apply_constraints(problem, manager, solver)
        self.assertTrue(solver, msg='Constraints added incorrectly.')
        self.assertTrue(solver.HasDimension('capacity_constraint'),
                        msg='Capacity constraint not added.')

    def test_set_objective_function(self):
        """Asserts the objective function is added to the solver"""

        model_builder = OptimizationModelBuilder(
            constraints=[CapacityConstraint()])
        problem = self.problem
        manager = RoutingIndexManager(
            len(problem.stops),  # Number of locations
            len(problem.vehicles),  # Number of vehicles
            problem.starts,  # Start list of Vehicles
            problem.ends  # End list of Vehicles
        )
        solver = RoutingModel(manager)
        model_builder._set_objective_function(problem, manager, solver)
        self.assertTrue(solver, msg='Objective function set incorrectly.')

    def test_build(self):
        """Assert the Opt. model is built correctly"""

        model_builder = OptimizationModelBuilder(
            constraints=[CapacityConstraint()])
        problem = self.problem
        model = model_builder.build(problem)
        self.assertTrue(model, msg='Opt. model built incorrectly.')
        self.assertEqual(model.manager.GetNumberOfVehicles(),
                         len(self.vehicles),
                         msg='Number of vehicles in manager is incorrect.')
        self.assertEqual(model.manager.GetNumberOfIndices(),
                         len(self.vehicles) * 2 + len(self.stops) -
                         len(problem.depots),
                         msg='Number of indices in manager is incorrect.')
        self.assertTrue(model.solver, msg='Solver could not be instantiated.')
        self.assertTrue(model.search_parameters,
                        msg='Search params could not be built.')
        self.assertEqual(model.search_parameters.time_limit,
                         Duration(seconds=self.params.SEARCH_TIME_LIMIT),
                         msg='Time limit is incorrect in the search params.')
        self.assertEqual(
            model.search_parameters.solution_limit,
            self.params.SEARCH_SOLUTIONS_LIMIT,
            msg='Solutions limit is incorrect in the search params.')
        self.assertEqual(
            model.search_parameters.first_solution_strategy,
            FIRST_SOLUTION_STRATEGY[self.params.FIRST_SOLUTION_STRATEGY],
            msg='First solution strategy is incorrect in the search params.')
        self.assertEqual(
            model.search_parameters.local_search_metaheuristic,
            LOCAL_SEARCH_METAHEURISTIC[self.params.SEARCH_METAHEURISTIC],
            msg='Search metaheuristic is incorrect in the search params.')
        self.assertTrue(model.solver.HasDimension('capacity_constraint'),
                        msg='Capacity constraint not added.')
Exemple #10
0
def stop_order(code, stop, num):
    Stop.stop_order(code, stop, num)
    pass