mirror of
https://github.com/tig-foundation/tig-monorepo.git
synced 2026-02-21 10:27:49 +08:00
Submitted vehicle_routing/cw_heuristic
This commit is contained in:
parent
bdc6ed6794
commit
ebccd1a090
23
tig-algorithms/src/vehicle_routing/cw_heuristic/README.md
Normal file
23
tig-algorithms/src/vehicle_routing/cw_heuristic/README.md
Normal file
@ -0,0 +1,23 @@
|
||||
# TIG Code Submission
|
||||
|
||||
## Submission Details
|
||||
|
||||
* **Challenge Name:** vehicle_routing
|
||||
* **Algorithm 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
|
||||
131
tig-algorithms/src/vehicle_routing/cw_heuristic/mod.rs
Normal file
131
tig-algorithms/src/vehicle_routing/cw_heuristic/mod.rs
Normal file
@ -0,0 +1,131 @@
|
||||
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.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
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn help() {
|
||||
println!("No help information available.");
|
||||
}
|
||||
@ -66,7 +66,8 @@
|
||||
|
||||
// c002_a034
|
||||
|
||||
// c002_a035
|
||||
pub mod cw_heuristic;
|
||||
pub use cw_heuristic as c002_a035;
|
||||
|
||||
// c002_a036
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user