use std::fmt::Debug;
use solverforge_core::domain::PlanningSolution;
use solverforge_scoring::Director;
use crate::heuristic::r#move::{ListMoveImpl, MoveArena};
use crate::heuristic::selector::move_selector::{
ListMoveKOptSelector, ListMoveListChangeSelector, ListMoveListRuinSelector,
ListMoveNearbyKOptSelector, MoveSelector,
};
use crate::heuristic::selector::nearby_list_change::CrossEntityDistanceMeter;
use crate::heuristic::selector::{
FromSolutionEntitySelector, ListMoveListReverseSelector, ListMoveListSwapSelector,
ListMoveNearbyListChangeSelector, ListMoveNearbyListSwapSelector,
ListMoveSubListChangeSelector, ListMoveSubListSwapSelector,
};
use super::super::context::IntraDistanceAdapter;
pub enum ListLeafSelector<S, V, DM, IDM>
where
S: PlanningSolution,
V: Clone + PartialEq + Send + Sync + Debug + 'static,
DM: CrossEntityDistanceMeter<S>,
IDM: CrossEntityDistanceMeter<S>,
{
NearbyListChange(ListMoveNearbyListChangeSelector<S, V, DM, FromSolutionEntitySelector>),
NearbyListSwap(ListMoveNearbyListSwapSelector<S, V, DM, FromSolutionEntitySelector>),
ListReverse(ListMoveListReverseSelector<S, V, FromSolutionEntitySelector>),
SubListChange(ListMoveSubListChangeSelector<S, V, FromSolutionEntitySelector>),
KOpt(ListMoveKOptSelector<S, V, FromSolutionEntitySelector>),
NearbyKOpt(
ListMoveNearbyKOptSelector<S, V, IntraDistanceAdapter<IDM>, FromSolutionEntitySelector>,
),
ListRuin(ListMoveListRuinSelector<S, V>),
ListChange(ListMoveListChangeSelector<S, V, FromSolutionEntitySelector>),
ListSwap(ListMoveListSwapSelector<S, V, FromSolutionEntitySelector>),
SubListSwap(ListMoveSubListSwapSelector<S, V, FromSolutionEntitySelector>),
}
impl<S, V, DM, IDM> Debug for ListLeafSelector<S, V, DM, IDM>
where
S: PlanningSolution,
V: Clone + PartialEq + Send + Sync + Debug + 'static,
DM: CrossEntityDistanceMeter<S>,
IDM: CrossEntityDistanceMeter<S>,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::NearbyListChange(s) => write!(f, "ListLeafSelector::NearbyListChange({s:?})"),
Self::NearbyListSwap(s) => write!(f, "ListLeafSelector::NearbyListSwap({s:?})"),
Self::ListReverse(s) => write!(f, "ListLeafSelector::ListReverse({s:?})"),
Self::SubListChange(s) => write!(f, "ListLeafSelector::SubListChange({s:?})"),
Self::KOpt(s) => write!(f, "ListLeafSelector::KOpt({s:?})"),
Self::NearbyKOpt(s) => write!(f, "ListLeafSelector::NearbyKOpt({s:?})"),
Self::ListRuin(s) => write!(f, "ListLeafSelector::ListRuin({s:?})"),
Self::ListChange(s) => write!(f, "ListLeafSelector::ListChange({s:?})"),
Self::ListSwap(s) => write!(f, "ListLeafSelector::ListSwap({s:?})"),
Self::SubListSwap(s) => write!(f, "ListLeafSelector::SubListSwap({s:?})"),
}
}
}
impl<S, V, DM, IDM> MoveSelector<S, ListMoveImpl<S, V>> for ListLeafSelector<S, V, DM, IDM>
where
S: PlanningSolution,
V: Clone + PartialEq + Send + Sync + Debug + 'static,
DM: CrossEntityDistanceMeter<S>,
IDM: CrossEntityDistanceMeter<S> + 'static,
{
fn iter_moves<'a, D: Director<S>>(
&'a self,
score_director: &'a D,
) -> impl Iterator<Item = ListMoveImpl<S, V>> + 'a {
enum ListLeafIter<A, B, C, DIter, E, F, G, H, I, J> {
NearbyListChange(A),
NearbyListSwap(B),
ListReverse(C),
SubListChange(DIter),
KOpt(E),
NearbyKOpt(F),
ListRuin(G),
ListChange(H),
ListSwap(I),
SubListSwap(J),
}
impl<T, A, B, C, DIter, E, F, G, H, I, J> Iterator
for ListLeafIter<A, B, C, DIter, E, F, G, H, I, J>
where
A: Iterator<Item = T>,
B: Iterator<Item = T>,
C: Iterator<Item = T>,
DIter: Iterator<Item = T>,
E: Iterator<Item = T>,
F: Iterator<Item = T>,
G: Iterator<Item = T>,
H: Iterator<Item = T>,
I: Iterator<Item = T>,
J: Iterator<Item = T>,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
match self {
Self::NearbyListChange(iter) => iter.next(),
Self::NearbyListSwap(iter) => iter.next(),
Self::ListReverse(iter) => iter.next(),
Self::SubListChange(iter) => iter.next(),
Self::KOpt(iter) => iter.next(),
Self::NearbyKOpt(iter) => iter.next(),
Self::ListRuin(iter) => iter.next(),
Self::ListChange(iter) => iter.next(),
Self::ListSwap(iter) => iter.next(),
Self::SubListSwap(iter) => iter.next(),
}
}
}
match self {
Self::NearbyListChange(s) => {
ListLeafIter::NearbyListChange(s.iter_moves(score_director))
}
Self::NearbyListSwap(s) => ListLeafIter::NearbyListSwap(s.iter_moves(score_director)),
Self::ListReverse(s) => ListLeafIter::ListReverse(s.iter_moves(score_director)),
Self::SubListChange(s) => ListLeafIter::SubListChange(s.iter_moves(score_director)),
Self::KOpt(s) => ListLeafIter::KOpt(s.iter_moves(score_director)),
Self::NearbyKOpt(s) => ListLeafIter::NearbyKOpt(s.iter_moves(score_director)),
Self::ListRuin(s) => ListLeafIter::ListRuin(s.iter_moves(score_director)),
Self::ListChange(s) => ListLeafIter::ListChange(s.iter_moves(score_director)),
Self::ListSwap(s) => ListLeafIter::ListSwap(s.iter_moves(score_director)),
Self::SubListSwap(s) => ListLeafIter::SubListSwap(s.iter_moves(score_director)),
}
}
fn size<D: Director<S>>(&self, score_director: &D) -> usize {
match self {
Self::NearbyListChange(s) => s.size(score_director),
Self::NearbyListSwap(s) => s.size(score_director),
Self::ListReverse(s) => s.size(score_director),
Self::SubListChange(s) => s.size(score_director),
Self::KOpt(s) => s.size(score_director),
Self::NearbyKOpt(s) => s.size(score_director),
Self::ListRuin(s) => s.size(score_director),
Self::ListChange(s) => s.size(score_director),
Self::ListSwap(s) => s.size(score_director),
Self::SubListSwap(s) => s.size(score_director),
}
}
fn append_moves<D: Director<S>>(
&self,
score_director: &D,
arena: &mut MoveArena<ListMoveImpl<S, V>>,
) {
match self {
Self::NearbyListChange(s) => arena.extend(s.iter_moves(score_director)),
Self::NearbyListSwap(s) => arena.extend(s.iter_moves(score_director)),
Self::ListReverse(s) => arena.extend(s.iter_moves(score_director)),
Self::SubListChange(s) => arena.extend(s.iter_moves(score_director)),
Self::KOpt(s) => arena.extend(s.iter_moves(score_director)),
Self::NearbyKOpt(s) => arena.extend(s.iter_moves(score_director)),
Self::ListRuin(s) => arena.extend(s.iter_moves(score_director)),
Self::ListChange(s) => arena.extend(s.iter_moves(score_director)),
Self::ListSwap(s) => arena.extend(s.iter_moves(score_director)),
Self::SubListSwap(s) => arena.extend(s.iter_moves(score_director)),
}
}
}