Ejemplo n.º 1
0
def main():
    # read inputs
    argParser = initOptions()
    options = argParser.parse_args()

    r_all = {}
    rv_dict = {}
    memory_problems = [0]

    # start traci
    if options.sumocfg:
        run_traci = [
            options.sumo, "-c", options.sumocfg,
            '--tripinfo-output.write-unfinished'
        ]
    else:
        run_traci = [
            options.sumo, '--net-file',
            '%s' % options.network, '-r',
            '%s,%s' % (options.reservations, options.taxis), '-l', 'log.txt',
            '--device.taxi.dispatch-algorithm', 'traci', '--tripinfo-output',
            '%s' % options.output, '--tripinfo-output.write-unfinished'
        ]
        if options.gui_settings:
            run_traci.extend(['-g', '%s' % options.gui_settings])

    traci.start(run_traci)

    # execute the TraCI control loop
    step = traci.simulation.getTime() + 10
    v_type = None
    rerouting = True
    while rerouting:
        traci.simulationStep(step)

        # get vType for route calculation
        if not v_type:
            fleet = traci.vehicle.getTaxiFleet(-1)
            v_type = traci.vehicle.getTypeID(fleet[0])

        # get new reservations
        r_id_new = []
        for x in traci.person.getTaxiReservations(1):

            # search direct travel time
            direct = int(
                traci.simulation.findRoute(x.fromEdge,
                                           x.toEdge,
                                           v_type,
                                           x.depart,
                                           routingMode=0).travelTime)

            # add new reservation attributes
            setattr(x, 'direct', direct)  # direct travel time
            setattr(x, 'vehicle', False)  # id of assigned vehicle
            setattr(x, 'delay',
                    0)  # difference between assigned pick up time and real one
            setattr(
                x, 'tw_pickup',
                [x.depart, x.depart + options.max_wait])  # pickup time window
            # drop off time window
            if x.direct * options.drf < options.drf_min:
                setattr(x, 'tw_dropoff', [
                    x.tw_pickup[0] + direct,
                    x.tw_pickup[1] + direct + options.drf_min
                ])
            else:
                setattr(x, 'tw_dropoff', [
                    x.tw_pickup[0] + direct,
                    x.tw_pickup[1] + direct * options.drf
                ])

            # add id to new reservations
            r_id_new.append(x.id)
            # add reservation to list
            r_all[x.id] = x

        # unassigned reservations
        r_id_unassigned = [x.id for x_id, x in r_all.items() if not x.vehicle]

        # if reservations pending
        if r_id_unassigned:
            if options.debug:
                print('\nRun dispatcher')
                if r_id_new:
                    print('New reservations: ', r_id_new)
                print('Unassigned reservations: ',
                      list(set(r_id_unassigned) - set(r_id_new)))

            # get fleet
            fleet = traci.vehicle.getTaxiFleet(-1)
            if set(fleet) != set(fleet) & set(
                    traci.vehicle.getIDList()):  # TODO manage teleports
                print("\nVehicle %s is being teleported, skip to next step" %
                      (set(fleet) - set(traci.vehicle.getIDList())))
                step += options.sim_step
                continue  # if a vehicle is being teleported skip to next step

            # remove reservations already served
            r_id_current = [x.id for x in traci.person.getTaxiReservations(0)]
            r_id_served = list(set(r_all.keys()) - set(r_id_current))
            [r_all.pop(key) for key in r_id_served]
            [
                rv_dict.pop(key) for key in list(rv_dict)
                if set(r_id_served) & set(rv_dict[key][2])
            ]

            # reservations already picked up
            r_id_picked = [x.id for x in traci.person.getTaxiReservations(8)]

            # search request-vehicles pairs
            if options.debug:
                print('Calculate RV-Graph')
            get_rv(options, r_id_new, r_id_picked, r_id_served, r_all, fleet,
                   v_type, rv_dict, step)

            # search trips (rtv graph)
            # TODO define/import algorithm before to avoid checking each time
            # Maybe a list with the function as element and get the element (0, 1, 2)

            if options.debug:
                print('Calculate RTV-Graph')
            if options.rtv_algorithm == '0':
                rtv_dict, r_id_rtv, memory_problems = rtvAlgorithm.exhaustive_search(
                    options, r_id_unassigned, r_id_picked, r_all, fleet,
                    v_type, rv_dict, step, memory_problems)
            elif options.rtv_algorithm == '1':
                rtv_dict, r_id_rtv = rtvAlgorithm.simple(
                    options, r_id_unassigned, r_id_picked, r_id_served, r_all,
                    fleet, v_type, rv_dict, step)
            elif options.rtv_algorithm == '2':
                rtv_dict, r_id_rtv = rtvAlgorithm.simple_rerouting(
                    options, r_id_unassigned, r_id_picked, r_id_served, r_all,
                    fleet, v_type, rv_dict, step)
            # rtv_dict, r_id_rtv = get_rtv(options, r_id_unassigned, r_id_picked, r_id_served, r_all, fleet, v_type, rv_dict, step)

            if len(rtv_dict) == 0:
                step += options.sim_step
                continue  # if no routes found

            elif len(rtv_dict.keys()) == 1:
                # if one vehicle darp, assign route
                best_routes = list(rtv_dict.keys())

            else:
                # if multiple vehicle darp, solve ILP with pulp
                vehicle_constraints = {}
                request_constraints = {}
                costs = {}
                trips = list(rtv_dict.keys()
                             )  # list of all trips for ILP solution parse

                # add bonus_cost to trip cost (makes trips with more served requests cheaper than splitting the requests to more
                # vehicles with smaller trips if both strategies would yield a similar cost)
                for idx, trip_id in enumerate(trips):
                    # rtv_dict[route] = [travel_time, v_bin, r_bin, value]
                    bonus_cost = (
                        sum(rtv_dict[trip_id][2]) + 1
                    ) * options.cost_per_trip  # TODO specific cost for vehicle can be consider here
                    costs.update({idx: rtv_dict[trip_id][0] + bonus_cost
                                  })  # generate dict with cost
                    vehicle_constraints.update({
                        idx: rtv_dict[trip_id][1]
                    })  # generate dict with vehicle used in the trip
                    request_constraints.update({
                        idx: rtv_dict[trip_id][2]
                    })  # generate dict with served requests in the trip

                if options.debug:
                    print('Solve ILP')
                ilp_result = ilp_solve(options, len(fleet), len(r_id_rtv),
                                       costs, vehicle_constraints,
                                       request_constraints)

                # parse ILP result
                best_routes = [
                    trips[int(route_index)] for route_index in ilp_result
                ]

            # assign routes to vehicles
            for route_id in best_routes:
                stops = route_id.replace('y', '')
                stops = stops.replace('z', '')
                stops = stops.split("_")
                # first check if route different or better (when no optimal solution) than already assigned
                current_route = []
                try:  # get current route
                    for taxi_stop in traci.vehicle.getStops(stops[0]):
                        sub_stops = taxi_stop.actType.split(
                            ",")  # if more than 1 reservation in stop
                        for sub_stop in sub_stops:
                            current_route.append(sub_stop.split(" ")[2][1:-1])
                except:
                    current_route = ['None']
                if current_route == stops[1:]:
                    # route is the same
                    continue
                elif set(current_route) == set(
                        stops[1:]) and len(current_route) == len(stops[1:]):
                    # if route serve same request, check if new is faster
                    tt_current_route = 0
                    edges = [
                        taxi_stops.lane.split("_")[0]
                        for taxi_stops in traci.vehicle.getStops(stops[0])
                    ]  # TODO check next_act update
                    edges.insert(
                        0,
                        traci.vehicle.getLaneID(
                            stops[0]).split("_")[0])  # add current edge
                    for idx, edge in enumerate(edges[:-1]):
                        tt_current_route += int(
                            traci.simulation.findRoute(
                                edge,
                                edges[idx + 1],
                                v_type,
                                step,
                                routingMode=0).travelTime
                        ) + 60  # TODO default stop time ticket #6714
                    tt_new_route = rtv_dict[route_id][0]
                    if tt_new_route >= tt_current_route:
                        continue  # current route better than new found
                if options.debug:
                    print('Dispatch: ', route_id)
                traci.vehicle.dispatchTaxi(stops[0], stops[1:])
                # assign vehicle to requests
                # TODO to avoid major changes in the pick-up time when assigning new passengers,
                # tw_pickup should be updated, whit some constant X seconds, e.g. 10 Minutes
                for x_id in set(stops[1:]):
                    x = r_all[x_id]
                    x.vehicle = stops[0]

        if step > options.end_time or (
                not traci.simulation.getMinExpectedNumber() > 0
                and not traci.person.getIDList()):  #TODO ticket #8385
            rerouting = False

        step += options.sim_step

    if options.rtv_algorithm == 0:  # if exhaustive search
        if sum(memory_problems) == 0:
            print('Optimal solution found')
        else:
            print(
                'The maximum specified time for the calculation with the exact method was exceeded. Solution could not be optimal'
            )
    print('DRT simulation ended')
    traci.close()
Ejemplo n.º 2
0
def main():
    # read inputs
    ap = initOptions()
    options = ap.parse_args()

    res_all = {}
    rv_dict = {}
    exact_sol = [0]

    if options.sumo == 'sumo':
        SUMO = checkBinary('sumo')
    else:
        SUMO = checkBinary('sumo-gui')

    # start traci
    if options.sumocfg:
        run_traci = [
            SUMO, "-c", options.sumocfg, '--tripinfo-output.write-unfinished'
        ]
    else:
        run_traci = [
            SUMO, '--net-file',
            '%s' % options.network, '-r',
            '%s,%s' % (options.reservations, options.taxis), '-l', 'log.txt',
            '--device.taxi.dispatch-algorithm', 'traci', '--tripinfo-output',
            '%s' % options.output, '--tripinfo-output.write-unfinished'
        ]
        if options.gui_settings:
            run_traci.extend(['-g', '%s' % options.gui_settings])

    traci.start(run_traci)

    # execute the TraCI control loop
    step = traci.simulation.getTime() + 10
    veh_type = None
    rerouting = True
    while rerouting:
        traci.simulationStep(step)

        # get vType for route calculation
        if not veh_type:
            fleet = traci.vehicle.getTaxiFleet(-1)
            veh_type = traci.vehicle.getTypeID(fleet[0])

        # get new reservations
        res_id_new = []
        for res in traci.person.getTaxiReservations(1):

            # search direct travel time
            direct = int(
                findRoute(res.fromEdge,
                          res.toEdge,
                          veh_type,
                          res.depart,
                          routingMode=0).travelTime)

            # add new reservation attributes
            setattr(res, 'direct', direct)  # direct travel time
            setattr(res, 'vehicle', False)  # id of assigned vehicle
            setattr(res, 'delay', 0)  # real pick up time - assigned time
            # pickup time window
            setattr(res, 'tw_pickup',
                    [res.depart, res.depart + options.max_wait])
            # drop off time window
            if res.direct * options.drf < options.drf_min:
                setattr(res, 'tw_dropoff', [
                    res.tw_pickup[0] + direct,
                    res.tw_pickup[1] + direct + options.drf_min
                ])
            else:
                setattr(res, 'tw_dropoff', [
                    res.tw_pickup[0] + direct,
                    res.tw_pickup[1] + direct * options.drf
                ])

            # add reservation id to new reservations
            res_id_new.append(res.id)
            # add reservation object to list
            res_all[res.id] = res

        # unassigned reservations
        res_id_unassigned = [
            res.id for res_id, res in res_all.items() if not res.vehicle
        ]

        # if reservations pending
        if res_id_unassigned:
            if options.debug:
                print('\nRun dispatcher')
                if res_id_new:
                    print('New reservations: ', res_id_new)
                print('Unassigned reservations: ',
                      list(set(res_id_unassigned) - set(res_id_new)))

            # get fleet
            fleet = traci.vehicle.getTaxiFleet(-1)
            if set(fleet) != set(fleet) & set(
                    traci.vehicle.getIDList()):  # TODO manage teleports # noqa
                print("\nVehicle %s is being teleported, skip to next step" %
                      (set(fleet) - set(traci.vehicle.getIDList())))
                step += options.sim_step
                continue  # if a vehicle is being teleported skip to next step

            # remove reservations already served
            res_id_current = [
                res.id for res in traci.person.getTaxiReservations(0)
            ]  # noqa
            res_id_served = list(set(res_all.keys()) - set(res_id_current))
            [res_all.pop(key) for key in res_id_served]
            [
                rv_dict.pop(key) for key in list(rv_dict)
                if set(res_id_served) & set(rv_dict[key][2])
            ]

            # reservations already picked up
            res_id_picked = [
                res.id for res in traci.person.getTaxiReservations(8)
            ]  # noqa

            # search reservation-vehicles pairs
            if options.debug:
                print('Calculate RV-Graph')
            get_rv(options, res_id_new, res_id_picked, res_id_served, res_all,
                   fleet, veh_type, rv_dict, step)

            # search trips (rtv graph)
            if options.debug:
                print('Calculate RTV-Graph')
            if options.rtv_algorithm == '0':
                rtv_dict, rtv_res, exact_sol = rtvAlgorithm.exhaustive_search(
                    options, res_id_unassigned, res_id_picked, res_all, fleet,
                    veh_type, rv_dict, step, exact_sol)
            elif options.rtv_algorithm == '1':
                rtv_dict, rtv_res = rtvAlgorithm.simple(
                    options, res_id_unassigned, res_id_picked, res_id_served,
                    res_all, fleet, veh_type, rv_dict, step)
            elif options.rtv_algorithm == '2':
                rtv_dict, rtv_res = rtvAlgorithm.simple_rerouting(
                    options, res_id_unassigned, res_id_picked, res_id_served,
                    res_all, fleet, veh_type, rv_dict, step)

            if len(rtv_dict) == 0:
                step += options.sim_step
                continue  # if no routes found

            elif len(rtv_dict.keys()) == 1:
                # if one vehicle darp, assign route
                best_routes = list(rtv_dict.keys())

            else:
                # if multiple vehicle darp, solve ILP with pulp
                veh_constraints = {}
                res_constraints = {}
                costs = {}
                trips = list(rtv_dict.keys())  # trips for parsing ILP solution

                # add bonus_cost to trip cost (makes trips with more served
                # reservations cheaper than splitting the reservations to more
                # vehicles with smaller trips if both strategies would yield
                # a similar cost)
                for idx, trip_id in enumerate(trips):
                    # rtv_dict[route] = [travel_time, veh_bin, res_bin, value]
                    # TODO specific cost for vehicle can be consider here
                    bonus_cost = (sum(rtv_dict[trip_id][2]) + 1) * \
                                  options.cost_per_trip
                    # generate dict with costs
                    costs.update({idx: rtv_dict[trip_id][0] + bonus_cost})
                    # generate dict with vehicle used in the trip
                    veh_constraints.update({idx: rtv_dict[trip_id][1]})
                    # generate dict with served reservations in the trip
                    res_constraints.update({idx: rtv_dict[trip_id][2]})

                if options.debug:
                    print('Solve ILP')
                ilp_result = ilp_solve(options, len(fleet), len(rtv_res),
                                       costs, veh_constraints, res_constraints)

                # parse ILP result
                best_routes = [
                    trips[int(route_index)] for route_index in ilp_result
                ]  # noqa

            # assign routes to vehicles
            for route_id in best_routes:
                stops = route_id.replace('y', '')
                stops = stops.replace('z', '')
                stops = stops.split("_")
                veh_id = stops[0]
                # first check if new route is better than the current one
                current_route = []
                if len(traci.vehicle.getStops(veh_id)) > 1:
                    for taxi_stop in traci.vehicle.getStops(veh_id):
                        # get reservations served at each stop
                        sub_stops = taxi_stop.actType.split(",")
                        # if more than 1 reservation in stop
                        for sub_stop in sub_stops:
                            current_route.append(sub_stop.split(" ")[2][1:-1])
                if current_route == stops[1:]:
                    # route is the same
                    continue
                elif (set(current_route) == set(stops[1:])
                      and len(current_route) == len(stops[1:])):
                    # if route serve same reservations and have the same stops
                    # get travel time of current route
                    tt_current_route = 0
                    edges = [
                        taxi_stop.lane.split("_")[0]
                        for taxi_stop in traci.vehicle.getStops(veh_id)
                    ]
                    # add current edge to list
                    edges.insert(
                        0,
                        traci.vehicle.getLaneID(veh_id).split("_")[0])  # noqa
                    # calculate travel time
                    for idx, edge in enumerate(edges[:-1]):
                        # TODO default stop time ticket #6714
                        tt_current_route += int(
                            findRoute(edge,
                                      edges[idx + 1],
                                      veh_type,
                                      step,
                                      routingMode=0).travelTime) + 60
                    # get travel time of the new route
                    tt_new_route = rtv_dict[route_id][0]
                    if tt_new_route >= tt_current_route:
                        continue  # current route better than new found
                if options.debug:
                    print('Dispatch: ', route_id)
                traci.vehicle.dispatchTaxi(veh_id, stops[1:])
                # assign vehicle to reservations
                # TODO to avoid major changes in the pick-up time when assigning new passengers,  # noqa
                # tw_pickup should be updated, whit some constant X seconds, e.g. 10 Minutes  # noqa
                for res_id in set(stops[1:]):
                    res = res_all[res_id]
                    res.vehicle = veh_id

        # TODO ticket #8385
        if step > options.end_time or (traci.simulation.getMinExpectedNumber()
                                       <= 0 and not traci.person.getIDList()):
            rerouting = False

        step += options.sim_step

    if options.rtv_algorithm == 0:  # if exhaustive search
        if sum(exact_sol) == 0:
            print('Optimal solution found.')
        else:
            print(
                'The maximal specified calculation time has been exceeded. Solution could be not optimal.'
            )  # noqa
    print('DRT simulation ended')
    traci.close()