Skip to content

Commit

Permalink
Merge remote-tracking branch 'public/test/vehicle_routing/clarke_wrig…
Browse files Browse the repository at this point in the history
…ht' into test/temp
  • Loading branch information
FiveMovesAhead committed Apr 24, 2024
2 parents 5686528 + e9ad558 commit 9fdabe2
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 1 deletion.
87 changes: 87 additions & 0 deletions tig-algorithms/src/vehicle_routing/clarke_wright.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use tig_challenges::vehicle_routing::*;

pub fn solve_challenge(challenge: &Challenge) -> anyhow::Result<Option<Solution>> {
let d = &challenge.distance_matrix;
let c = challenge.max_capacity;
let n = challenge.difficulty.num_nodes;

// 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::new();
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_by(|a, b| b.0.cmp(&a.0)); // Sort in descending order by score

// 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;
}

Ok(Some(Solution {
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(),
}))
}
2 changes: 1 addition & 1 deletion tig-algorithms/src/vehicle_routing/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// c002_a001 placeholder
pub mod clarke_wright;
// c002_a002 placeholder
// c002_a003 placeholder
// c002_a004 placeholder
Expand Down
Binary file not shown.

0 comments on commit 9fdabe2

Please sign in to comment.