use std::fmt::Debug;
use std::marker::PhantomData;
use solverforge_core::domain::PlanningSolution;
use solverforge_scoring::Director;
use crate::heuristic::r#move::MoveArena;
use crate::heuristic::r#move::{ChangeMove, EitherMove, ListMoveImpl, Move, SwapMove};
use super::entity::{EntityReference, EntitySelector, FromSolutionEntitySelector};
use super::value_selector::{StaticValueSelector, ValueSelector};
pub trait MoveSelector<S: PlanningSolution, M: Move<S>>: Send + Debug {
fn iter_moves<'a, D: Director<S>>(
&'a self,
score_director: &'a D,
) -> impl Iterator<Item = M> + 'a;
fn size<D: Director<S>>(&self, score_director: &D) -> usize;
fn append_moves<D: Director<S>>(&self, score_director: &D, arena: &mut MoveArena<M>) {
arena.extend(self.iter_moves(score_director));
}
fn is_never_ending(&self) -> bool {
false
}
}
pub struct ChangeMoveSelector<S, V, ES, VS> {
entity_selector: ES,
value_selector: VS,
getter: fn(&S, usize) -> Option<V>,
setter: fn(&mut S, usize, Option<V>),
descriptor_index: usize,
variable_name: &'static str,
_phantom: PhantomData<(fn() -> S, fn() -> V)>,
}
impl<S, V: Debug, ES: Debug, VS: Debug> Debug for ChangeMoveSelector<S, V, ES, VS> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ChangeMoveSelector")
.field("entity_selector", &self.entity_selector)
.field("value_selector", &self.value_selector)
.field("descriptor_index", &self.descriptor_index)
.field("variable_name", &self.variable_name)
.finish()
}
}
impl<S: PlanningSolution, V: Clone, ES, VS> ChangeMoveSelector<S, V, ES, VS> {
pub fn new(
entity_selector: ES,
value_selector: VS,
getter: fn(&S, usize) -> Option<V>,
setter: fn(&mut S, usize, Option<V>),
descriptor_index: usize,
variable_name: &'static str,
) -> Self {
Self {
entity_selector,
value_selector,
getter,
setter,
descriptor_index,
variable_name,
_phantom: PhantomData,
}
}
}
impl<S: PlanningSolution, V: Clone + Send + Sync + Debug + 'static>
ChangeMoveSelector<S, V, FromSolutionEntitySelector, StaticValueSelector<S, V>>
{
pub fn simple(
getter: fn(&S, usize) -> Option<V>,
setter: fn(&mut S, usize, Option<V>),
descriptor_index: usize,
variable_name: &'static str,
values: Vec<V>,
) -> Self {
Self {
entity_selector: FromSolutionEntitySelector::new(descriptor_index),
value_selector: StaticValueSelector::new(values),
getter,
setter,
descriptor_index,
variable_name,
_phantom: PhantomData,
}
}
}
impl<S, V, ES, VS> MoveSelector<S, ChangeMove<S, V>> for ChangeMoveSelector<S, V, ES, VS>
where
S: PlanningSolution,
V: Clone + PartialEq + Send + Sync + Debug + 'static,
ES: EntitySelector<S>,
VS: ValueSelector<S, V>,
{
fn iter_moves<'a, D: Director<S>>(
&'a self,
score_director: &'a D,
) -> impl Iterator<Item = ChangeMove<S, V>> + 'a {
let descriptor_index = self.descriptor_index;
let variable_name = self.variable_name;
let getter = self.getter;
let setter = self.setter;
let value_selector = &self.value_selector;
self.entity_selector
.iter(score_director)
.flat_map(move |entity_ref| {
value_selector
.iter_typed(
score_director,
entity_ref.descriptor_index,
entity_ref.entity_index,
)
.map(move |value| {
ChangeMove::new(
entity_ref.entity_index,
Some(value),
getter,
setter,
variable_name,
descriptor_index,
)
})
})
}
fn size<D: Director<S>>(&self, score_director: &D) -> usize {
self.entity_selector
.iter(score_director)
.map(|entity_ref| {
self.value_selector.size(
score_director,
entity_ref.descriptor_index,
entity_ref.entity_index,
)
})
.sum()
}
}
pub struct SwapMoveSelector<S, V, LES, RES> {
left_entity_selector: LES,
right_entity_selector: RES,
getter: fn(&S, usize) -> Option<V>,
setter: fn(&mut S, usize, Option<V>),
descriptor_index: usize,
variable_name: &'static str,
_phantom: PhantomData<(fn() -> S, fn() -> V)>,
}
impl<S, V, LES: Debug, RES: Debug> Debug for SwapMoveSelector<S, V, LES, RES> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SwapMoveSelector")
.field("left_entity_selector", &self.left_entity_selector)
.field("right_entity_selector", &self.right_entity_selector)
.field("descriptor_index", &self.descriptor_index)
.field("variable_name", &self.variable_name)
.finish()
}
}
impl<S: PlanningSolution, V, LES, RES> SwapMoveSelector<S, V, LES, RES> {
pub fn new(
left_entity_selector: LES,
right_entity_selector: RES,
getter: fn(&S, usize) -> Option<V>,
setter: fn(&mut S, usize, Option<V>),
descriptor_index: usize,
variable_name: &'static str,
) -> Self {
Self {
left_entity_selector,
right_entity_selector,
getter,
setter,
descriptor_index,
variable_name,
_phantom: PhantomData,
}
}
}
impl<S: PlanningSolution, V>
SwapMoveSelector<S, V, FromSolutionEntitySelector, FromSolutionEntitySelector>
{
pub fn simple(
getter: fn(&S, usize) -> Option<V>,
setter: fn(&mut S, usize, Option<V>),
descriptor_index: usize,
variable_name: &'static str,
) -> Self {
Self {
left_entity_selector: FromSolutionEntitySelector::new(descriptor_index),
right_entity_selector: FromSolutionEntitySelector::new(descriptor_index),
getter,
setter,
descriptor_index,
variable_name,
_phantom: PhantomData,
}
}
}
impl<S, V, LES, RES> MoveSelector<S, SwapMove<S, V>> for SwapMoveSelector<S, V, LES, RES>
where
S: PlanningSolution,
V: Clone + PartialEq + Send + Sync + Debug + 'static,
LES: EntitySelector<S>,
RES: EntitySelector<S>,
{
fn iter_moves<'a, D: Director<S>>(
&'a self,
score_director: &'a D,
) -> impl Iterator<Item = SwapMove<S, V>> + 'a {
let descriptor_index = self.descriptor_index;
let variable_name = self.variable_name;
let getter = self.getter;
let setter = self.setter;
let left_entities: Vec<EntityReference> =
self.left_entity_selector.iter(score_director).collect();
let right_entities: Vec<EntityReference> =
self.right_entity_selector.iter(score_director).collect();
let mut moves =
Vec::with_capacity(left_entities.len() * left_entities.len().saturating_sub(1) / 2);
for (i, left) in left_entities.iter().enumerate() {
for right in &right_entities[i + 1..] {
if left.descriptor_index == right.descriptor_index
&& left.descriptor_index == descriptor_index
{
moves.push(SwapMove::new(
left.entity_index,
right.entity_index,
getter,
setter,
variable_name,
descriptor_index,
));
}
}
}
moves.into_iter()
}
fn size<D: Director<S>>(&self, score_director: &D) -> usize {
let left_count = self.left_entity_selector.size(score_director);
let right_count = self.right_entity_selector.size(score_director);
if left_count == right_count {
left_count * left_count.saturating_sub(1) / 2
} else {
left_count * right_count / 2
}
}
}
pub struct EitherChangeMoveSelector<S, V, ES, VS> {
inner: ChangeMoveSelector<S, V, ES, VS>,
}
impl<S, V: Debug, ES: Debug, VS: Debug> Debug for EitherChangeMoveSelector<S, V, ES, VS> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EitherChangeMoveSelector")
.field("inner", &self.inner)
.finish()
}
}
impl<S: PlanningSolution, V: Clone + Send + Sync + Debug + 'static>
EitherChangeMoveSelector<S, V, FromSolutionEntitySelector, StaticValueSelector<S, V>>
{
pub fn simple(
getter: fn(&S, usize) -> Option<V>,
setter: fn(&mut S, usize, Option<V>),
descriptor_index: usize,
variable_name: &'static str,
values: Vec<V>,
) -> Self {
Self {
inner: ChangeMoveSelector::simple(
getter,
setter,
descriptor_index,
variable_name,
values,
),
}
}
}
impl<S, V, ES, VS> MoveSelector<S, EitherMove<S, V>> for EitherChangeMoveSelector<S, V, ES, VS>
where
S: PlanningSolution,
V: Clone + PartialEq + Send + Sync + Debug + 'static,
ES: EntitySelector<S>,
VS: ValueSelector<S, V>,
{
fn iter_moves<'a, D: Director<S>>(
&'a self,
score_director: &'a D,
) -> impl Iterator<Item = EitherMove<S, V>> + 'a {
self.inner
.iter_moves(score_director)
.map(EitherMove::Change)
}
fn size<D: Director<S>>(&self, score_director: &D) -> usize {
self.inner.size(score_director)
}
}
pub struct EitherSwapMoveSelector<S, V, LES, RES> {
inner: SwapMoveSelector<S, V, LES, RES>,
}
impl<S, V: Debug, LES: Debug, RES: Debug> Debug for EitherSwapMoveSelector<S, V, LES, RES> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EitherSwapMoveSelector")
.field("inner", &self.inner)
.finish()
}
}
impl<S: PlanningSolution, V>
EitherSwapMoveSelector<S, V, FromSolutionEntitySelector, FromSolutionEntitySelector>
{
pub fn simple(
getter: fn(&S, usize) -> Option<V>,
setter: fn(&mut S, usize, Option<V>),
descriptor_index: usize,
variable_name: &'static str,
) -> Self {
Self {
inner: SwapMoveSelector::simple(getter, setter, descriptor_index, variable_name),
}
}
}
impl<S, V, LES, RES> MoveSelector<S, EitherMove<S, V>> for EitherSwapMoveSelector<S, V, LES, RES>
where
S: PlanningSolution,
V: Clone + PartialEq + Send + Sync + Debug + 'static,
LES: EntitySelector<S>,
RES: EntitySelector<S>,
{
fn iter_moves<'a, D: Director<S>>(
&'a self,
score_director: &'a D,
) -> impl Iterator<Item = EitherMove<S, V>> + 'a {
self.inner.iter_moves(score_director).map(EitherMove::Swap)
}
fn size<D: Director<S>>(&self, score_director: &D) -> usize {
self.inner.size(score_director)
}
}
use super::k_opt::{KOptMoveSelector, ListPositionDistanceMeter, NearbyKOptMoveSelector};
use super::list_change::ListChangeMoveSelector;
use super::list_ruin::ListRuinMoveSelector;
pub struct ListMoveListChangeSelector<S, V, ES> {
inner: ListChangeMoveSelector<S, V, ES>,
}
impl<S, V: Debug, ES: Debug> Debug for ListMoveListChangeSelector<S, V, ES> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ListMoveListChangeSelector")
.field("inner", &self.inner)
.finish()
}
}
impl<S, V, ES> ListMoveListChangeSelector<S, V, ES> {
pub fn new(inner: ListChangeMoveSelector<S, V, ES>) -> Self {
Self { inner }
}
}
impl<S, V, ES> MoveSelector<S, ListMoveImpl<S, V>> for ListMoveListChangeSelector<S, V, ES>
where
S: PlanningSolution,
V: Clone + PartialEq + Send + Sync + Debug + 'static,
ES: EntitySelector<S>,
{
fn iter_moves<'a, D: Director<S>>(
&'a self,
score_director: &'a D,
) -> impl Iterator<Item = ListMoveImpl<S, V>> + 'a {
self.inner
.iter_moves(score_director)
.map(ListMoveImpl::ListChange)
}
fn size<D: Director<S>>(&self, score_director: &D) -> usize {
self.inner.size(score_director)
}
}
pub struct ListMoveKOptSelector<S, V, ES> {
inner: KOptMoveSelector<S, V, ES>,
}
impl<S, V: Debug, ES: Debug> Debug for ListMoveKOptSelector<S, V, ES> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ListMoveKOptSelector")
.field("inner", &self.inner)
.finish()
}
}
impl<S, V, ES> ListMoveKOptSelector<S, V, ES> {
pub fn new(inner: KOptMoveSelector<S, V, ES>) -> Self {
Self { inner }
}
}
impl<S, V, ES> MoveSelector<S, ListMoveImpl<S, V>> for ListMoveKOptSelector<S, V, ES>
where
S: PlanningSolution,
V: Clone + PartialEq + Send + Sync + Debug + 'static,
ES: EntitySelector<S>,
{
fn iter_moves<'a, D: Director<S>>(
&'a self,
score_director: &'a D,
) -> impl Iterator<Item = ListMoveImpl<S, V>> + 'a {
self.inner
.iter_moves(score_director)
.map(ListMoveImpl::KOpt)
}
fn size<D: Director<S>>(&self, score_director: &D) -> usize {
self.inner.size(score_director)
}
}
pub struct ListMoveNearbyKOptSelector<S, V, D: ListPositionDistanceMeter<S>, ES> {
inner: NearbyKOptMoveSelector<S, V, D, ES>,
}
impl<S, V: Debug, D: ListPositionDistanceMeter<S>, ES: Debug> Debug
for ListMoveNearbyKOptSelector<S, V, D, ES>
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ListMoveNearbyKOptSelector")
.field("inner", &self.inner)
.finish()
}
}
impl<S, V, D: ListPositionDistanceMeter<S>, ES> ListMoveNearbyKOptSelector<S, V, D, ES> {
pub fn new(inner: NearbyKOptMoveSelector<S, V, D, ES>) -> Self {
Self { inner }
}
}
impl<S, V, D, ES> MoveSelector<S, ListMoveImpl<S, V>> for ListMoveNearbyKOptSelector<S, V, D, ES>
where
S: PlanningSolution,
V: Clone + PartialEq + Send + Sync + Debug + 'static,
D: ListPositionDistanceMeter<S> + 'static,
ES: EntitySelector<S>,
{
fn iter_moves<'a, Dir: Director<S>>(
&'a self,
score_director: &'a Dir,
) -> impl Iterator<Item = ListMoveImpl<S, V>> + 'a {
self.inner
.iter_moves(score_director)
.map(ListMoveImpl::KOpt)
}
fn size<Dir: Director<S>>(&self, score_director: &Dir) -> usize {
self.inner.size(score_director)
}
}
pub struct ListMoveListRuinSelector<S, V> {
inner: ListRuinMoveSelector<S, V>,
}
impl<S, V: Debug> Debug for ListMoveListRuinSelector<S, V> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ListMoveListRuinSelector")
.field("inner", &self.inner)
.finish()
}
}
impl<S, V> ListMoveListRuinSelector<S, V> {
pub fn new(inner: ListRuinMoveSelector<S, V>) -> Self {
Self { inner }
}
}
impl<S, V> MoveSelector<S, ListMoveImpl<S, V>> for ListMoveListRuinSelector<S, V>
where
S: PlanningSolution,
V: Clone + PartialEq + Send + Sync + Debug + 'static,
{
fn iter_moves<'a, D: Director<S>>(
&'a self,
score_director: &'a D,
) -> impl Iterator<Item = ListMoveImpl<S, V>> + 'a {
self.inner
.iter_moves(score_director)
.map(ListMoveImpl::ListRuin)
}
fn size<D: Director<S>>(&self, score_director: &D) -> usize {
self.inner.size(score_director)
}
}
#[cfg(test)]
#[path = "move_selector_tests.rs"]
mod tests;