1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//! Group-aware chromosome trait for multi-group crossover dispatch.
//!
//! The [`GroupAware`] trait exposes a `group_ranges()` method that returns
//! `(start, end)` index pairs for each independent permutation group in a
//! chromosome's DNA. This trait enables [`multi_group_pmx`] and
//! [`multi_group_ox`] crossover operators to apply PMX/OX within each group
//! independently, without crossing group boundaries.
//!
//! [`multi_group_pmx`]: crate::operations::crossover::multi_group_pmx
//! [`multi_group_ox`]: crate::operations::crossover::multi_group_ox
//!
//! # Design note
//!
//! This trait exists to enable generic dispatch in the crossover operator layer.
//! The `CrossoverOperator` trait is generic over `U: LinearChromosome`; to call
//! `group_ranges()` from a dispatch arm, the bound `U: LinearChromosome + GroupAware`
//! is added to the `multi_group_pmx` and `multi_group_ox` functions. Existing
//! chromosomes do NOT implement `GroupAware`, so they cannot accidentally invoke
//! the multi-group crossovers — `OperatorCompat` also guards against this at
//! `Ga::build()` time.
/// A chromosome that exposes its group boundaries for multi-group crossover.
///
/// Implement this trait on any chromosome type where the DNA is the concatenation
/// of independent permutations over disjoint groups. `group_ranges()` returns
/// the `(start, end)` index pairs (inclusive, 0-based) for each group.
///
/// For a chromosome with groups of sizes `[3, 3, 2]`:
///
/// ```text
/// group_ranges() → [(0, 2), (3, 5), (6, 7)]
/// ```
///
/// # Examples
///
/// ```rust,no_run
/// use genetic_algorithms::traits::GroupAware;
/// use genetic_algorithms::chromosomes::MultiUniqueChromosome;
///
/// let c = MultiUniqueChromosome::<i32>::new(vec![vec![0, 1, 2], vec![10, 20, 30]]);
/// let ranges = c.group_ranges();
/// assert_eq!(ranges, vec![(0, 2), (3, 5)]);
/// ```