cuGenOpt/benchmark/experiments/e2_vs_routing/routing.py
2026-03-20 00:33:45 +08:00

113 lines
4.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
E2: GenSolver vs 专用求解器 (OR-Tools Routing) — Routing 侧
目的:与 gpu.cu 对比,展示专用求解器的质量优势
实例TSP (全部 TSPLIB), VRP (A-n32-k5)
时间预算1s, 5s, 10s, 30s, 60s
用法python routing.py [tsp|vrp|all]
"""
import sys
import os
import time
from ortools.constraint_solver import routing_enums_pb2, pywrapcp
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "common"))
from instances import load_tsp, load_vrp, euc2d_dist_matrix, TSP_INSTANCES, VRP_INSTANCES
TSP_TIME_BUDGETS = [1, 5, 10, 30, 60]
VRP_TIME_BUDGETS = [1, 5, 10, 30]
def solve_tsp_routing(dist, n, time_limit_sec):
manager = pywrapcp.RoutingIndexManager(n, 1, 0)
routing = pywrapcp.RoutingModel(manager)
def dist_callback(from_idx, to_idx):
return dist[manager.IndexToNode(from_idx)][manager.IndexToNode(to_idx)]
transit_id = routing.RegisterTransitCallback(dist_callback)
routing.SetArcCostEvaluatorOfAllVehicles(transit_id)
params = pywrapcp.DefaultRoutingSearchParameters()
params.first_solution_strategy = routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC
params.local_search_metaheuristic = routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH
params.time_limit.seconds = time_limit_sec
t0 = time.perf_counter()
solution = routing.SolveWithParameters(params)
elapsed_ms = (time.perf_counter() - t0) * 1000.0
obj = solution.ObjectiveValue() if solution else float("inf")
return obj, elapsed_ms
def solve_cvrp_routing(dist, demands, n, n_vehicles, capacity, time_limit_sec):
manager = pywrapcp.RoutingIndexManager(n, n_vehicles, 0)
routing = pywrapcp.RoutingModel(manager)
def dist_callback(from_idx, to_idx):
return dist[manager.IndexToNode(from_idx)][manager.IndexToNode(to_idx)]
transit_id = routing.RegisterTransitCallback(dist_callback)
routing.SetArcCostEvaluatorOfAllVehicles(transit_id)
def demand_callback(idx):
return demands[manager.IndexToNode(idx)]
demand_id = routing.RegisterUnaryTransitCallback(demand_callback)
routing.AddDimensionWithVehicleCapacity(demand_id, 0, [capacity] * n_vehicles, True, "Cap")
params = pywrapcp.DefaultRoutingSearchParameters()
params.first_solution_strategy = routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC
params.local_search_metaheuristic = routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH
params.time_limit.seconds = time_limit_sec
t0 = time.perf_counter()
solution = routing.SolveWithParameters(params)
elapsed_ms = (time.perf_counter() - t0) * 1000.0
obj = solution.ObjectiveValue() if solution else float("inf")
return obj, elapsed_ms
def print_row(instance, config, obj, elapsed_ms, optimal):
if obj == float("inf"):
print(f"{instance},{config},0,inf,0.00,{elapsed_ms:.1f},inf,0,time")
else:
gap = (obj - optimal) / optimal * 100.0 if optimal > 0 else 0.0
print(f"{instance},{config},0,{obj:.2f},0.00,{elapsed_ms:.1f},{gap:.2f},0,time")
sys.stdout.flush()
def run_tsp():
for entry in TSP_INSTANCES:
inst = load_tsp(entry)
print(f" [e2-routing] TSP {inst['name']} (n={inst['n']})", file=sys.stderr)
dist = euc2d_dist_matrix(inst["coords"])
for t in TSP_TIME_BUDGETS:
obj, ms = solve_tsp_routing(dist, inst["n"], t)
print_row(inst["name"], f"routing_GLS_{t}s", obj, ms, inst["optimal"])
def run_vrp():
for entry in VRP_INSTANCES:
inst = load_vrp(entry)
print(f" [e2-routing] VRP {inst['name']} (n={inst['n']})", file=sys.stderr)
dist = euc2d_dist_matrix(inst["coords"])
for t in VRP_TIME_BUDGETS:
obj, ms = solve_cvrp_routing(
dist, inst["demands"], inst["n"],
inst["n_vehicles"], inst["capacity"], t)
print_row(inst["name"], f"routing_GLS_{t}s", obj, ms, inst["optimal"])
def main():
print("instance,config,seed,obj,penalty,time_ms,gap_pct,generations,stop_reason")
target = sys.argv[1] if len(sys.argv) > 1 else "all"
if target in ("all", "tsp"):
run_tsp()
if target in ("all", "vrp"):
run_vrp()
if __name__ == "__main__":
main()