@@ 1,8 1,8 @@
use std::{cmp::Ordering, marker::PhantomData};
-use nalgebra::{allocator::Allocator, DefaultAllocator, Dim, OVector, U1};
-use rand::{prelude::SliceRandom, Rng, RngCore};
+use nalgebra::{allocator::Allocator, Const, DefaultAllocator, Dim, OVector, U1, U2};
+use rand::{prelude::SliceRandom, seq::IteratorRandom, Rng, RngCore};
use eoa_lib::initializer::Initializer;
-use crate::tsp::{NodePermutation, TSPInstance};
+use crate::{graph::{Graph, minimal_spanning_tree_kruskal, GenericGraph}, tsp::{NodePermutation, TSPCity, TSPEdge, TSPInstance}};
pub struct TSPRandomInitializer<D>
where
@@ 169,10 169,133 @@ where
}
// 3. Initialize randomly with random p_choose_second (call initialize_single)
- for i in 0..count {
+ for _ in 0..count {
population.push(self.initialize_single(size, rng))
}
+ population
+ }
+}
+
+pub struct MinimumSpanningTreeInitializer<'a, D: Dim>
+where
+ DefaultAllocator: nalgebra::allocator::Allocator<D>,
+ DefaultAllocator: nalgebra::allocator::Allocator<D, D>
+{
+ instance: &'a TSPInstance<D>,
+ minimal_spanning_tree: GenericGraph<TSPCity, TSPEdge>,
+ _phantom: PhantomData<D>,
+}
+
+impl<'a, D: Dim> MinimumSpanningTreeInitializer<'a, D>
+where
+ DefaultAllocator: nalgebra::allocator::Allocator<D>,
+ DefaultAllocator: nalgebra::allocator::Allocator<D, D>,
+ DefaultAllocator: nalgebra::allocator::Allocator<D, U2>,
+{
+ pub fn new(instance: &'a TSPInstance<D>) -> Self {
+ let tsp_graph = instance.clone().to_graph();
+ let minimal_spanning_tree =
+ minimal_spanning_tree_kruskal(
+ &tsp_graph,
+ None,
+ |_| true
+ );
+
+ assert_eq!(minimal_spanning_tree.components_count(), 1);
+ let minimal_spanning_tree = tsp_graph
+ .filter_edges(|i, _|
+ minimal_spanning_tree.edges.contains(&i));
+
+ Self {
+ instance,
+ minimal_spanning_tree,
+ _phantom: PhantomData
+ }
+ }
+
+ fn initialize_from(
+ &self,
+ node: usize,
+ size: D,
+ rng: &mut dyn RngCore
+ ) -> NodePermutation<D> {
+ let mut used_nodes = vec![false; size.value()];
+ let mut individual =
+ OVector::zeros_generic(size, U1);
+
+ let mut current_node = node;
+ for i in 0..size.value()-1 {
+ individual[i] = current_node;
+ used_nodes[current_node] = true;
+
+ let usable_neighbors = self.minimal_spanning_tree
+ .neighbor_idxs(current_node)
+ .unwrap()
+ .filter(|&neighbor| !used_nodes[neighbor]);
+
+ let chosen = usable_neighbors.choose(rng);
+
+ current_node = if let Some(next_node) = chosen {
+ next_node
+ } else {
+ // Choose closest node
+ (0..size.value())
+ .filter(|&node| !used_nodes[node])
+ .min_by(|&next_node1, &next_node2|
+ self.instance.distances(current_node, next_node1)
+ .partial_cmp(&self.instance.distances(current_node, next_node2))
+ .unwrap_or(Ordering::Less))
+ // There has to be unused node since we haven't yet used size.value() nodes.
+ .unwrap()
+ }
+ }
+
+ // The last node
+ individual[size.value() - 1] = current_node;
+
+ NodePermutation { permutation: individual }
+ }
+}
+
+impl<'a, D: Dim> Initializer<D, NodePermutation<D>> for MinimumSpanningTreeInitializer<'a, D>
+where
+ DefaultAllocator: nalgebra::allocator::Allocator<D>,
+ DefaultAllocator: nalgebra::allocator::Allocator<D, D>,
+ DefaultAllocator: nalgebra::allocator::Allocator<D, U2>,
+{
+ fn initialize_single(&self, size: D, rng: &mut dyn RngCore) -> NodePermutation<D> {
+ let starting_node = rng.random_range(0..size.value());
+ self.initialize_from(starting_node, size, rng)
+ }
+
+ fn initialize(
+ &self,
+ size: D,
+ mut count: usize,
+ rng: &mut dyn RngCore
+ ) -> Vec<NodePermutation<D>> {
+ let mut population = Vec::with_capacity(count);
+
+ // 1. Initialize from every node
+ for i in 0..size.value() {
+ population.push(self.initialize_from(
+ i,
+ size,
+ rng
+ ));
+
+ count -= 1;
+
+ if count == 0 {
+ return population;
+ }
+ }
+
+ // 2. Initialize randomly with random p_choose_second (call initialize_single)
+ for _ in 0..count {
+ population.push(self.initialize_single(size, rng));
+ }
population
}