Submitted vehicle_routing/cw_heuristic

This commit is contained in:
FiveMovesAhead 2025-10-17 13:54:31 +01:00
parent a2fbd8c435
commit fd33126991
3 changed files with 152 additions and 1 deletions

View File

@ -0,0 +1,23 @@
# TIG Code Submission
## Submission Details
* **Challenge Name:** vehicle_routing
* **Submission Name:** cw_heuristic
* **Copyright:** 2024 Just
* **Identity of Submitter:** Just
* **Identity of Creator of Algorithmic Method:** null
* **Unique Algorithm Identifier (UAI):** null
## License
The files in this folder are under the following licenses:
* TIG Benchmarker Outbound License
* TIG Commercial License
* TIG Inbound Game License
* TIG Innovator Outbound Game License
* TIG Open Data License
* TIG THV Game License
Copies of the licenses can be obtained at:
https://github.com/tig-foundation/tig-monorepo/tree/main/docs/licenses

View File

@ -0,0 +1,127 @@
use anyhow::{anyhow, Result};
use serde_json::{Map, Value};
use tig_challenges::vehicle_routing::*;
pub fn solve_challenge(
challenge: &Challenge,
save_solution: &dyn Fn(&Solution) -> Result<()>,
hyperparameters: &Option<Map<String, Value>>,
) -> Result<()> {
Err(anyhow!("This algorithm is no longer compatible."))
}
// Old code that is no longer compatible
#[cfg(none)]
mod dead_code {
use tig_challenges::vehicle_routing::*;
pub fn solve_challenge(challenge: &Challenge) -> anyhow::Result<Option<Solution>> {
let mut solution = Solution {
sub_solutions: Vec::new(),
};
for sub_instance in &challenge.sub_instances {
match solve_sub_instance(sub_instance)? {
Some(sub_solution) => solution.sub_solutions.push(sub_solution),
None => return Ok(None),
}
}
Ok(Some(solution))
}
pub fn solve_sub_instance(challenge: &SubInstance) -> anyhow::Result<Option<SubSolution>> {
let d = &challenge.distance_matrix;
let c = challenge.max_capacity;
let n = challenge.difficulty.num_nodes;
let max_dist: f32 = challenge.distance_matrix[0].iter().sum::<i32>() as f32;
let p = challenge.baseline_total_distance as f32 / max_dist;
if p < 0.57 {
return Ok(None)
}
// Clarke-Wright heuristic for node pairs based on their distances to depot
// vs distance between each other
let mut scores: Vec<(i32, usize, usize)> = Vec::with_capacity((n-1)*(n-2)/2);
for i in 1..n {
for j in (i + 1)..n {
scores.push((d[i][0] + d[0][j] - d[i][j], i, j));
}
}
scores.sort_unstable_by(|a, b| b.0.cmp(&a.0));
// Create a route for every node
let mut routes: Vec<Option<Vec<usize>>> = (0..n).map(|i| Some(vec![i])).collect();
routes[0] = None;
let mut route_demands: Vec<i32> = challenge.demands.clone();
// Iterate through node pairs, starting from greatest score
for (s, i, j) in scores {
// Stop if score is negative
if s < 0 {
break;
}
// Skip if joining the nodes is not possible
if routes[i].is_none() || routes[j].is_none() {
continue;
}
let left_route = routes[i].as_ref().unwrap();
let right_route = routes[j].as_ref().unwrap();
let mut left_startnode = left_route[0];
let right_startnode = right_route[0];
let left_endnode = left_route[left_route.len() - 1];
let mut right_endnode = right_route[right_route.len() - 1];
let merged_demand = route_demands[left_startnode] + route_demands[right_startnode];
if left_startnode == right_startnode || merged_demand > c {
continue;
}
let mut left_route = routes[i].take().unwrap();
let mut right_route = routes[j].take().unwrap();
routes[left_startnode] = None;
routes[right_startnode] = None;
routes[left_endnode] = None;
routes[right_endnode] = None;
// reverse it
if left_startnode == i {
left_route.reverse();
left_startnode = left_endnode;
}
if right_endnode == j {
right_route.reverse();
right_endnode = right_startnode;
}
let mut new_route = left_route;
new_route.extend(right_route);
// Only the start and end nodes of routes are kept
routes[left_startnode] = Some(new_route.clone());
routes[right_endnode] = Some(new_route);
route_demands[left_startnode] = merged_demand;
route_demands[right_endnode] = merged_demand;
}
let routes = routes
.into_iter()
.enumerate()
.filter(|(i, x)| x.as_ref().is_some_and(|x| x[0] == *i))
.map(|(_, mut x)| {
let mut route = vec![0];
route.append(x.as_mut().unwrap());
route.push(0);
route
})
.collect();
Ok(Some(SubSolution {
routes
}))
}
}

View File

@ -66,7 +66,8 @@
// c002_a034
// c002_a035
pub mod cw_heuristic;
pub use cw_heuristic as c002_a035;
// c002_a036