|
| 1 | +# solverforge-cvrp WIREFRAME |
| 2 | + |
| 3 | +Domain helpers for Capacitated Vehicle Routing Problems (CVRP). |
| 4 | + |
| 5 | +**Location:** `crates/solverforge-cvrp/` |
| 6 | + |
| 7 | +## Dependencies |
| 8 | + |
| 9 | +- `solverforge` (workspace) — Facade; re-exports `CrossEntityDistanceMeter` |
| 10 | + |
| 11 | +## File Map |
| 12 | + |
| 13 | +``` |
| 14 | +src/ |
| 15 | +└── lib.rs — All public types and free functions |
| 16 | +``` |
| 17 | + |
| 18 | +## Types |
| 19 | + |
| 20 | +### `ProblemData` |
| 21 | + |
| 22 | +Immutable problem data shared by all vehicles. Fields: |
| 23 | + |
| 24 | +| Field | Type | Description | |
| 25 | +|-------|------|-------------| |
| 26 | +| `capacity` | `i64` | Vehicle capacity | |
| 27 | +| `depot` | `usize` | Depot node index | |
| 28 | +| `demands` | `Vec<i32>` | Demand per node | |
| 29 | +| `distance_matrix` | `Vec<Vec<i64>>` | Distance matrix | |
| 30 | +| `time_windows` | `Vec<(i64, i64)>` | `(min_start, max_end)` per node | |
| 31 | +| `service_durations` | `Vec<i64>` | Service duration per node | |
| 32 | +| `travel_times` | `Vec<Vec<i64>>` | Travel time matrix | |
| 33 | +| `vehicle_departure_time` | `i64` | Departure time from depot | |
| 34 | + |
| 35 | +### `VrpSolution` (trait) |
| 36 | + |
| 37 | +Trait implemented by a planning solution that holds a fleet of vehicles. |
| 38 | + |
| 39 | +| Method | Signature | |
| 40 | +|--------|-----------| |
| 41 | +| `vehicle_data_ptr` | `fn(&self, entity_idx: usize) -> *const ProblemData` | |
| 42 | +| `vehicle_visits` | `fn(&self, entity_idx: usize) -> &[usize]` | |
| 43 | +| `vehicle_visits_mut` | `fn(&mut self, entity_idx: usize) -> &mut Vec<usize>` | |
| 44 | +| `vehicle_count` | `fn(&self) -> usize` | |
| 45 | + |
| 46 | +**Safety:** Implementors must ensure every `vehicle_data_ptr` points to a valid `ProblemData` for the entire duration of a solve call. |
| 47 | + |
| 48 | +### `MatrixDistanceMeter` |
| 49 | + |
| 50 | +Cross-entity distance meter backed by the solution's distance matrix. Implements `CrossEntityDistanceMeter<S: VrpSolution>`. `#[derive(Clone, Default)]`. |
| 51 | + |
| 52 | +### `MatrixIntraDistanceMeter` |
| 53 | + |
| 54 | +Intra-entity distance meter backed by the solution's distance matrix. Implements `CrossEntityDistanceMeter<S: VrpSolution>`. `#[derive(Clone, Default)]`. |
| 55 | + |
| 56 | +## Free Functions |
| 57 | + |
| 58 | +All functions are generic over `S: VrpSolution`. |
| 59 | + |
| 60 | +| Function | Signature | Description | |
| 61 | +|----------|-----------|-------------| |
| 62 | +| `distance` | `fn<S: VrpSolution>(plan: &S, i: usize, j: usize) -> i64` | Distance between two element indices via the first vehicle's data pointer | |
| 63 | +| `depot_for_entity` | `fn<S: VrpSolution>(plan: &S, _entity_idx: usize) -> usize` | Depot index (same for all vehicles) | |
| 64 | +| `depot_for_cw` | `fn<S: VrpSolution>(plan: &S) -> usize` | Depot index for Clarke-Wright (plan-level) | |
| 65 | +| `element_load` | `fn<S: VrpSolution>(plan: &S, elem: usize) -> i64` | Demand for a single customer element | |
| 66 | +| `capacity` | `fn<S: VrpSolution>(plan: &S) -> i64` | Vehicle capacity | |
| 67 | +| `assign_route` | `fn<S: VrpSolution>(plan: &mut S, entity_idx: usize, route: Vec<usize>)` | Assign a constructed route to a vehicle | |
| 68 | +| `get_route` | `fn<S: VrpSolution>(plan: &S, entity_idx: usize) -> Vec<usize>` | Current route for an entity | |
| 69 | +| `set_route` | `fn<S: VrpSolution>(plan: &mut S, entity_idx: usize, route: Vec<usize>)` | Replace current route for an entity | |
| 70 | +| `is_time_feasible` | `fn<S: VrpSolution>(plan: &S, route: &[usize]) -> bool` | True if route satisfies all time-window constraints | |
| 71 | +| `is_kopt_feasible` | `fn<S: VrpSolution>(plan: &S, _entity_idx: usize, route: &[usize]) -> bool` | K-opt feasibility gate; `entity_idx` ignored, delegates to `is_time_feasible` | |
| 72 | + |
| 73 | +### Usage as macro attribute fn pointers |
| 74 | + |
| 75 | +```rust |
| 76 | +#[shadow_variable_updates( |
| 77 | + merge_feasible_fn = "solverforge_cvrp_lib::is_time_feasible", |
| 78 | + cw_depot_fn = "solverforge_cvrp_lib::depot_for_cw", |
| 79 | + cw_distance_fn = "solverforge_cvrp_lib::distance", |
| 80 | + cw_element_load_fn= "solverforge_cvrp_lib::element_load", |
| 81 | + cw_capacity_fn = "solverforge_cvrp_lib::capacity", |
| 82 | + cw_assign_route_fn= "solverforge_cvrp_lib::assign_route", |
| 83 | + k_opt_get_route = "solverforge_cvrp_lib::get_route", |
| 84 | + k_opt_set_route = "solverforge_cvrp_lib::set_route", |
| 85 | + k_opt_depot_fn = "solverforge_cvrp_lib::depot_for_entity", |
| 86 | + k_opt_distance_fn = "solverforge_cvrp_lib::distance", |
| 87 | + k_opt_feasible_fn = "solverforge_cvrp_lib::is_kopt_feasible", |
| 88 | + // ... |
| 89 | +)] |
| 90 | +``` |
0 commit comments