diff --git a/crates/solverforge-core/WIREFRAME.md b/crates/solverforge-core/WIREFRAME.md index e1093b54..f646e1f3 100644 --- a/crates/solverforge-core/WIREFRAME.md +++ b/crates/solverforge-core/WIREFRAME.md @@ -39,7 +39,7 @@ src/ ├── domain/ │ ├── mod.rs — Module declarations and re-exports for domain types │ ├── traits.rs — PlanningSolution, PlanningEntity, ProblemFact, PlanningId, ListVariableSolution -│ ├── entity_ref.rs — EntityRef, EntityExtractor trait, TypedEntityExtractor +│ ├── entity_ref.rs — EntityRef, EntityExtractor trait, EntityCollectionExtractor │ ├── variable.rs — VariableType, ShadowVariableKind, ValueRangeType, ChainedVariableInfo │ ├── value_range.rs — ValueRangeProvider trait, FieldValueRangeProvider, ComputedValueRangeProvider, StaticValueRange, IntegerRange │ ├── descriptor/ @@ -65,7 +65,7 @@ src/ │ │ └── tests.rs — Supply tests (inverse, anchor, list_state) │ └── tests/ │ ├── mod.rs — Test module declarations -│ ├── entity_ref_tests.rs — TypedEntityExtractor tests +│ ├── entity_ref_tests.rs — EntityCollectionExtractor tests │ ├── value_range_tests.rs — ValueRangeProvider tests │ └── variable_tests.rs — VariableType, ShadowVariableKind, ChainedVariableInfo tests ``` @@ -318,10 +318,10 @@ pub struct EntityRef { Derives: `Debug, Clone` -#### `TypedEntityExtractor` +#### `EntityCollectionExtractor` ```rust -pub struct TypedEntityExtractor { +pub struct EntityCollectionExtractor { type_name: &'static str, // private collection_field: &'static str, // private get_collection: fn(&S) -> &Vec, // private @@ -606,7 +606,7 @@ All three supply types (InverseSupply, AnchorSupply, ListStateSupply) follow str ### EntityExtractor as Intentional dyn Boundary -`EntityExtractor` is a `dyn` trait object — this is an **intentional type-erasure boundary**. Descriptors need to work with entities of unknown concrete type at runtime. The `TypedEntityExtractor` provides the concrete implementation that downcasts via `Any`. `Box` appears in `EntityDescriptor` and `ProblemFactDescriptor`. +`EntityExtractor` is a `dyn` trait object — this is an **intentional type-erasure boundary**. Descriptors need to work with entities of unknown concrete type at runtime. The `EntityCollectionExtractor` provides the concrete implementation that downcasts via `Any`. `Box` appears in `EntityDescriptor` and `ProblemFactDescriptor`. ### PhantomData Pattern diff --git a/crates/solverforge-core/src/domain/descriptor/tests/entity_descriptor.rs b/crates/solverforge-core/src/domain/descriptor/tests/entity_descriptor.rs index afb38c44..d42db70a 100644 --- a/crates/solverforge-core/src/domain/descriptor/tests/entity_descriptor.rs +++ b/crates/solverforge-core/src/domain/descriptor/tests/entity_descriptor.rs @@ -3,7 +3,7 @@ use std::any::TypeId; #[test] fn test_with_extractor() { - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "TestEntity", "entities", get_entities, diff --git a/crates/solverforge-core/src/domain/descriptor/tests/mod.rs b/crates/solverforge-core/src/domain/descriptor/tests/mod.rs index 12276332..4eebe290 100644 --- a/crates/solverforge-core/src/domain/descriptor/tests/mod.rs +++ b/crates/solverforge-core/src/domain/descriptor/tests/mod.rs @@ -5,7 +5,7 @@ mod solution_descriptor; mod variable_descriptor; use crate::domain::descriptor::*; -use crate::domain::TypedEntityExtractor; +use crate::domain::EntityCollectionExtractor; use std::any::Any; // Shared test helpers used across descriptor test modules. @@ -30,7 +30,7 @@ pub(super) fn get_entities_mut(s: &mut TestSolution) -> &mut Vec { } pub(super) fn create_test_entity_descriptor() -> EntityDescriptor { - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "TestEntity", "entities", get_entities, diff --git a/crates/solverforge-core/src/domain/entity_ref.rs b/crates/solverforge-core/src/domain/entity_ref.rs index 3c244b10..39cdb833 100644 --- a/crates/solverforge-core/src/domain/entity_ref.rs +++ b/crates/solverforge-core/src/domain/entity_ref.rs @@ -74,7 +74,7 @@ impl Clone for Box { /// # Type Parameters /// * `S` - The solution type /// * `E` - The entity type -pub struct TypedEntityExtractor { +pub struct EntityCollectionExtractor { // Name of the entity type. type_name: &'static str, // Name of the collection field in the solution. @@ -85,7 +85,7 @@ pub struct TypedEntityExtractor { get_collection_mut: fn(&mut S) -> &mut Vec, } -impl TypedEntityExtractor +impl EntityCollectionExtractor where S: 'static, E: 'static, @@ -105,7 +105,7 @@ where } } -impl EntityExtractor for TypedEntityExtractor +impl EntityExtractor for EntityCollectionExtractor where S: Send + Sync + 'static, E: Clone + Send + Sync + 'static, @@ -162,9 +162,9 @@ where } } -impl Debug for TypedEntityExtractor { +impl Debug for EntityCollectionExtractor { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("TypedEntityExtractor") + f.debug_struct("EntityCollectionExtractor") .field("type_name", &self.type_name) .field("collection_field", &self.collection_field) .finish() diff --git a/crates/solverforge-core/src/domain/mod.rs b/crates/solverforge-core/src/domain/mod.rs index 7c31b82f..bfaea93b 100644 --- a/crates/solverforge-core/src/domain/mod.rs +++ b/crates/solverforge-core/src/domain/mod.rs @@ -22,7 +22,7 @@ pub use descriptor::{ EntityDescriptor, ProblemFactDescriptor, SolutionDescriptor, UsizeEntityValueProvider, UsizeGetter, UsizeSetter, VariableDescriptor, }; -pub use entity_ref::{EntityExtractor, EntityRef, TypedEntityExtractor}; +pub use entity_ref::{EntityCollectionExtractor, EntityExtractor, EntityRef}; pub use listener::{ ListVariableListener, ListVariableNotification, VariableListener, VariableNotification, }; diff --git a/crates/solverforge-core/src/domain/tests/entity_ref_tests.rs b/crates/solverforge-core/src/domain/tests/entity_ref_tests.rs index 2da1cc57..741d70ed 100644 --- a/crates/solverforge-core/src/domain/tests/entity_ref_tests.rs +++ b/crates/solverforge-core/src/domain/tests/entity_ref_tests.rs @@ -1,6 +1,6 @@ use std::any::Any; -use crate::domain::{EntityExtractor, TypedEntityExtractor}; +use crate::domain::{EntityCollectionExtractor, EntityExtractor}; #[derive(Clone, Debug)] struct TestEntity { @@ -24,7 +24,7 @@ fn get_entities_mut(s: &mut TestSolution) -> &mut Vec { #[test] fn test_typed_entity_extractor_count() { let extractor = - TypedEntityExtractor::new("TestEntity", "entities", get_entities, get_entities_mut); + EntityCollectionExtractor::new("TestEntity", "entities", get_entities, get_entities_mut); let solution = TestSolution { entities: vec![ @@ -47,7 +47,7 @@ fn test_typed_entity_extractor_count() { #[test] fn test_typed_entity_extractor_get() { let extractor = - TypedEntityExtractor::new("TestEntity", "entities", get_entities, get_entities_mut); + EntityCollectionExtractor::new("TestEntity", "entities", get_entities, get_entities_mut); let solution = TestSolution { entities: vec![ @@ -76,7 +76,7 @@ fn test_typed_entity_extractor_get() { #[test] fn test_typed_entity_extractor_get_mut() { let extractor = - TypedEntityExtractor::new("TestEntity", "entities", get_entities, get_entities_mut); + EntityCollectionExtractor::new("TestEntity", "entities", get_entities, get_entities_mut); let mut solution = TestSolution { entities: vec![TestEntity { @@ -96,7 +96,7 @@ fn test_typed_entity_extractor_get_mut() { #[test] fn test_typed_entity_extractor_entity_refs() { let extractor = - TypedEntityExtractor::new("TestEntity", "entities", get_entities, get_entities_mut); + EntityCollectionExtractor::new("TestEntity", "entities", get_entities, get_entities_mut); let solution = TestSolution { entities: vec![ @@ -122,7 +122,7 @@ fn test_typed_entity_extractor_entity_refs() { #[test] fn test_extractor_wrong_solution_type() { let extractor = - TypedEntityExtractor::new("TestEntity", "entities", get_entities, get_entities_mut); + EntityCollectionExtractor::new("TestEntity", "entities", get_entities, get_entities_mut); let wrong_solution = "not a solution"; let count = extractor.count(&wrong_solution as &dyn Any); @@ -131,7 +131,7 @@ fn test_extractor_wrong_solution_type() { #[test] fn test_extractor_clone() { - let extractor: Box = Box::new(TypedEntityExtractor::new( + let extractor: Box = Box::new(EntityCollectionExtractor::new( "TestEntity", "entities", get_entities, @@ -153,7 +153,7 @@ fn test_extractor_clone() { #[test] fn test_clone_entity_boxed() { let extractor = - TypedEntityExtractor::new("TestEntity", "entities", get_entities, get_entities_mut); + EntityCollectionExtractor::new("TestEntity", "entities", get_entities, get_entities_mut); let solution = TestSolution { entities: vec![ @@ -192,7 +192,7 @@ fn test_clone_entity_boxed() { #[test] fn test_entity_type_id() { let extractor = - TypedEntityExtractor::new("TestEntity", "entities", get_entities, get_entities_mut); + EntityCollectionExtractor::new("TestEntity", "entities", get_entities, get_entities_mut); assert_eq!( extractor.entity_type_id(), diff --git a/crates/solverforge-macros/WIREFRAME.md b/crates/solverforge-macros/WIREFRAME.md index 16952a92..99936506 100644 --- a/crates/solverforge-macros/WIREFRAME.md +++ b/crates/solverforge-macros/WIREFRAME.md @@ -166,7 +166,7 @@ struct ShadowConfig { All generated code references types via `::solverforge::__internal::*` paths, meaning the generated code depends on the `solverforge` facade crate re-exporting core types under `__internal`. Key referenced types: - `PlanningEntity`, `PlanningSolution`, `PlanningId`, `ProblemFact` - `EntityDescriptor`, `SolutionDescriptor`, `ProblemFactDescriptor`, `VariableDescriptor` -- `TypedEntityExtractor` +- `EntityCollectionExtractor` - `ShadowVariableKind`, `ShadowVariableSupport`, `SolvableSolution` - `ScoreDirector`, `Director` diff --git a/crates/solverforge-macros/src/planning_solution.rs b/crates/solverforge-macros/src/planning_solution.rs index 1258ac86..3b7f359f 100644 --- a/crates/solverforge-macros/src/planning_solution.rs +++ b/crates/solverforge-macros/src/planning_solution.rs @@ -105,7 +105,7 @@ pub fn expand_derive(input: DeriveInput) -> Result { let element_type = extract_collection_inner_type(&f.ty)?; Some(quote! { .with_entity(#element_type::entity_descriptor(#field_name_str).with_extractor( - Box::new(::solverforge::__internal::TypedEntityExtractor::new( + Box::new(::solverforge::__internal::EntityCollectionExtractor::new( stringify!(#element_type), #field_name_str, |s: &#name| &s.#field_name, @@ -125,7 +125,7 @@ pub fn expand_derive(input: DeriveInput) -> Result { let element_type = extract_collection_inner_type(&f.ty)?; Some(quote! { .with_problem_fact(#element_type::problem_fact_descriptor(#field_name_str).with_extractor( - Box::new(::solverforge::__internal::TypedEntityExtractor::new( + Box::new(::solverforge::__internal::EntityCollectionExtractor::new( stringify!(#element_type), #field_name_str, |s: &#name| &s.#field_name, diff --git a/crates/solverforge-scoring/WIREFRAME.md b/crates/solverforge-scoring/WIREFRAME.md index 32c5b328..dbb3a410 100644 --- a/crates/solverforge-scoring/WIREFRAME.md +++ b/crates/solverforge-scoring/WIREFRAME.md @@ -485,4 +485,4 @@ All types use `PhantomData<(fn() -> S, fn() -> A, ...)>` to avoid inheriting bou ## Cross-Crate Dependencies -- **From `solverforge-core`:** `Score`, `PlanningSolution`, `ConstraintRef`, `ImpactType`, `SolutionDescriptor`, `EntityDescriptor`, `ProblemFactDescriptor`, `VariableDescriptor`, `TypedEntityExtractor` +- **From `solverforge-core`:** `Score`, `PlanningSolution`, `ConstraintRef`, `ImpactType`, `SolutionDescriptor`, `EntityDescriptor`, `ProblemFactDescriptor`, `VariableDescriptor`, `EntityCollectionExtractor` diff --git a/crates/solverforge-solver/WIREFRAME.md b/crates/solverforge-solver/WIREFRAME.md index d5661bf0..21d4d0f8 100644 --- a/crates/solverforge-solver/WIREFRAME.md +++ b/crates/solverforge-solver/WIREFRAME.md @@ -82,9 +82,9 @@ src/ │ └── selector/ │ ├── mod.rs — Re-exports │ ├── entity.rs — EntitySelector trait, FromSolutionEntitySelector, AllEntitiesSelector -│ ├── typed_value.rs — TypedValueSelector trait, StaticTypedValueSelector, FromSolutionTypedValueSelector -│ ├── typed_move_selector.rs — MoveSelector trait, ChangeMoveSelector, SwapMoveSelector, EitherChange/SwapMoveSelector, ListMove* wrappers -│ ├── typed_move_selector_tests.rs — Tests +│ ├── value_selector.rs — ValueSelector trait, StaticValueSelector, FromSolutionValueSelector +│ ├── move_selector.rs — MoveSelector trait, ChangeMoveSelector, SwapMoveSelector, EitherChange/SwapMoveSelector, ListMove* wrappers +│ ├── move_selector_tests.rs — Tests │ ├── list_change.rs — ListChangeMoveSelector │ ├── list_swap.rs — ListSwapMoveSelector, ListMoveListSwapSelector │ ├── list_reverse.rs — ListReverseMoveSelector, ListMoveListReverseSelector @@ -128,7 +128,7 @@ src/ │ ├── mimic.rs │ ├── nearby.rs │ ├── pillar.rs -│ └── typed_move_selector.rs +│ └── move_selector.rs │ ├── phase/ │ ├── mod.rs — Phase trait, tuple impls @@ -274,7 +274,7 @@ Requires: `Send + Debug`. | `size` | `fn>(&self, score_director: &D) -> usize` | | `is_never_ending` | `fn(&self) -> bool` | -### `MoveSelector>` — `typed_move_selector.rs` +### `MoveSelector>` — `move_selector.rs` | Method | Signature | |--------|-----------| @@ -282,7 +282,7 @@ Requires: `Send + Debug`. | `size` | `fn>(&self, score_director: &D) -> usize` | | `is_never_ending` | `fn(&self) -> bool` | -### `TypedValueSelector` — `typed_value.rs` +### `ValueSelector` — `value_selector.rs` | Method | Signature | |--------|-----------| @@ -462,8 +462,8 @@ All moves are generic over `S` (solution) and `V` (value). All use typed `fn` po | Selector | Note | |----------|------| -| `StaticTypedValueSelector` | Fixed value list | -| `FromSolutionTypedValueSelector` | Extracts values from solution via `fn(&S) -> Vec` | +| `StaticValueSelector` | Fixed value list | +| `FromSolutionValueSelector` | Extracts values from solution via `fn(&S) -> Vec` | | `RangeValueSelector` | Generates 0..count_fn(solution) | ### Move Selectors diff --git a/crates/solverforge-solver/src/builder/list_selector.rs b/crates/solverforge-solver/src/builder/list_selector.rs index da4e225f..7d7976d8 100644 --- a/crates/solverforge-solver/src/builder/list_selector.rs +++ b/crates/solverforge-solver/src/builder/list_selector.rs @@ -9,11 +9,11 @@ use solverforge_scoring::Director; use crate::heuristic::r#move::{ListMoveImpl, MoveArena}; use crate::heuristic::selector::decorator::VecUnionSelector; use crate::heuristic::selector::k_opt::KOptConfig; -use crate::heuristic::selector::nearby_list_change::CrossEntityDistanceMeter; -use crate::heuristic::selector::typed_move_selector::{ +use crate::heuristic::selector::move_selector::{ ListMoveKOptSelector, ListMoveListChangeSelector, ListMoveListRuinSelector, ListMoveNearbyKOptSelector, MoveSelector, }; +use crate::heuristic::selector::nearby_list_change::CrossEntityDistanceMeter; use super::context::IntraDistanceAdapter; use crate::heuristic::selector::{ diff --git a/crates/solverforge-solver/src/descriptor_standard.rs b/crates/solverforge-solver/src/descriptor_standard.rs index 33cc4b39..adc9c63d 100644 --- a/crates/solverforge-solver/src/descriptor_standard.rs +++ b/crates/solverforge-solver/src/descriptor_standard.rs @@ -12,7 +12,7 @@ use solverforge_scoring::Director; use crate::heuristic::r#move::Move; use crate::heuristic::selector::decorator::VecUnionSelector; -use crate::heuristic::selector::typed_move_selector::MoveSelector; +use crate::heuristic::selector::move_selector::MoveSelector; use crate::heuristic::selector::EntityReference; use crate::phase::construction::{ BestFitForager, ConstructionHeuristicPhase, EntityPlacer, FirstFitForager, Placement, diff --git a/crates/solverforge-solver/src/heuristic/mod.rs b/crates/solverforge-solver/src/heuristic/mod.rs index 58993969..8d88cc63 100644 --- a/crates/solverforge-solver/src/heuristic/mod.rs +++ b/crates/solverforge-solver/src/heuristic/mod.rs @@ -22,7 +22,7 @@ pub use selector::{ AllEntitiesSelector, ChangeMoveSelector, CrossEntityDistanceMeter, DefaultCrossEntityDistanceMeter, DefaultDistanceMeter, DefaultPillarSelector, EitherChangeMoveSelector, EitherSwapMoveSelector, EntityReference, EntitySelector, - FromSolutionEntitySelector, FromSolutionTypedValueSelector, KOptConfig, KOptMoveSelector, + FromSolutionEntitySelector, FromSolutionValueSelector, KOptConfig, KOptMoveSelector, ListChangeMoveSelector, ListMoveKOptSelector, ListMoveListChangeSelector, ListMoveListReverseSelector, ListMoveListRuinSelector, ListMoveListSwapSelector, ListMoveNearbyListChangeSelector, ListMoveNearbyListSwapSelector, @@ -30,8 +30,8 @@ pub use selector::{ ListReverseMoveSelector, ListRuinMoveSelector, ListSwapMoveSelector, MimicRecorder, MimicRecordingEntitySelector, MimicReplayingEntitySelector, MoveSelector, NearbyDistanceMeter, NearbyEntitySelector, NearbyKOptMoveSelector, NearbyListChangeMoveSelector, - NearbyListSwapMoveSelector, NearbySelectionConfig, PerEntityTypedValueSelector, Pillar, - PillarSelector, RuinMoveSelector, SelectionOrder, StaticTypedValueSelector, + NearbyListSwapMoveSelector, NearbySelectionConfig, PerEntityValueSelector, Pillar, + PillarSelector, RuinMoveSelector, SelectionOrder, StaticValueSelector, SubListChangeMoveSelector, SubListSwapMoveSelector, SubPillarConfig, SwapMoveSelector, - TypedValueSelector, + ValueSelector, }; diff --git a/crates/solverforge-solver/src/heuristic/move/k_opt_tests.rs b/crates/solverforge-solver/src/heuristic/move/k_opt_tests.rs index d2800848..fc61cda6 100644 --- a/crates/solverforge-solver/src/heuristic/move/k_opt_tests.rs +++ b/crates/solverforge-solver/src/heuristic/move/k_opt_tests.rs @@ -3,7 +3,7 @@ use super::*; use crate::heuristic::r#move::k_opt_reconnection::THREE_OPT_RECONNECTIONS; use solverforge_core::domain::{ - EntityDescriptor, PlanningSolution, SolutionDescriptor, TypedEntityExtractor, + EntityCollectionExtractor, EntityDescriptor, PlanningSolution, SolutionDescriptor, }; use solverforge_core::score::SoftScore; use solverforge_scoring::{RecordingDirector, ScoreDirector}; @@ -56,7 +56,7 @@ fn sublist_insert(s: &mut TspSolution, entity_idx: usize, pos: usize, items: Vec fn create_director(tours: Vec) -> ScoreDirector { let solution = TspSolution { tours, score: None }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Tour", "tours", get_tours, diff --git a/crates/solverforge-solver/src/heuristic/move/list_change_tests.rs b/crates/solverforge-solver/src/heuristic/move/list_change_tests.rs index 5311e46b..337b4398 100644 --- a/crates/solverforge-solver/src/heuristic/move/list_change_tests.rs +++ b/crates/solverforge-solver/src/heuristic/move/list_change_tests.rs @@ -2,7 +2,7 @@ use super::*; use solverforge_core::domain::{ - EntityDescriptor, PlanningSolution, SolutionDescriptor, TypedEntityExtractor, + EntityCollectionExtractor, EntityDescriptor, PlanningSolution, SolutionDescriptor, }; use solverforge_core::score::SoftScore; use solverforge_scoring::{RecordingDirector, ScoreDirector}; @@ -53,7 +53,7 @@ fn create_director(vehicles: Vec) -> ScoreDirector vehicles, score: None, }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Vehicle", "vehicles", get_vehicles, diff --git a/crates/solverforge-solver/src/heuristic/move/sublist_change_tests.rs b/crates/solverforge-solver/src/heuristic/move/sublist_change_tests.rs index 170ddbc5..3d32f6ea 100644 --- a/crates/solverforge-solver/src/heuristic/move/sublist_change_tests.rs +++ b/crates/solverforge-solver/src/heuristic/move/sublist_change_tests.rs @@ -2,7 +2,7 @@ use super::*; use solverforge_core::domain::{ - EntityDescriptor, PlanningSolution, SolutionDescriptor, TypedEntityExtractor, + EntityCollectionExtractor, EntityDescriptor, PlanningSolution, SolutionDescriptor, }; use solverforge_core::score::SoftScore; use solverforge_scoring::{RecordingDirector, ScoreDirector}; @@ -63,7 +63,7 @@ fn create_director(vehicles: Vec) -> ScoreDirector vehicles, score: None, }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Vehicle", "vehicles", get_vehicles, diff --git a/crates/solverforge-solver/src/heuristic/move/sublist_swap_tests.rs b/crates/solverforge-solver/src/heuristic/move/sublist_swap_tests.rs index 13c23ca0..4ed3b13c 100644 --- a/crates/solverforge-solver/src/heuristic/move/sublist_swap_tests.rs +++ b/crates/solverforge-solver/src/heuristic/move/sublist_swap_tests.rs @@ -2,7 +2,7 @@ use super::*; use solverforge_core::domain::{ - EntityDescriptor, PlanningSolution, SolutionDescriptor, TypedEntityExtractor, + EntityCollectionExtractor, EntityDescriptor, PlanningSolution, SolutionDescriptor, }; use solverforge_core::score::SoftScore; use solverforge_scoring::{RecordingDirector, ScoreDirector}; @@ -63,7 +63,7 @@ fn create_director(vehicles: Vec) -> ScoreDirector vehicles, score: None, }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Vehicle", "vehicles", get_vehicles, diff --git a/crates/solverforge-solver/src/heuristic/move/tests/k_opt.rs b/crates/solverforge-solver/src/heuristic/move/tests/k_opt.rs index 74016d14..393cf564 100644 --- a/crates/solverforge-solver/src/heuristic/move/tests/k_opt.rs +++ b/crates/solverforge-solver/src/heuristic/move/tests/k_opt.rs @@ -65,7 +65,7 @@ mod k_opt_tests { fn create_director(tours: Vec) -> ScoreDirector { let solution = TspSolution { tours, score: None }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Tour", "tours", get_tours, diff --git a/crates/solverforge-solver/src/heuristic/move/tests/list_change.rs b/crates/solverforge-solver/src/heuristic/move/tests/list_change.rs index 576a68a8..e97d91d0 100644 --- a/crates/solverforge-solver/src/heuristic/move/tests/list_change.rs +++ b/crates/solverforge-solver/src/heuristic/move/tests/list_change.rs @@ -47,7 +47,7 @@ fn create_director(vehicles: Vec) -> ScoreDirector vehicles, score: None, }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Vehicle", "vehicles", get_vehicles, diff --git a/crates/solverforge-solver/src/heuristic/move/tests/list_reverse.rs b/crates/solverforge-solver/src/heuristic/move/tests/list_reverse.rs index 3e1da6b6..6d6b47ba 100644 --- a/crates/solverforge-solver/src/heuristic/move/tests/list_reverse.rs +++ b/crates/solverforge-solver/src/heuristic/move/tests/list_reverse.rs @@ -41,7 +41,7 @@ fn list_reverse(s: &mut TspSolution, entity_idx: usize, start: usize, end: usize fn create_director(tours: Vec) -> ScoreDirector { let solution = TspSolution { tours, score: None }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Tour", "tours", get_tours, diff --git a/crates/solverforge-solver/src/heuristic/move/tests/list_ruin.rs b/crates/solverforge-solver/src/heuristic/move/tests/list_ruin.rs index 472b6aa9..24f3a124 100644 --- a/crates/solverforge-solver/src/heuristic/move/tests/list_ruin.rs +++ b/crates/solverforge-solver/src/heuristic/move/tests/list_ruin.rs @@ -54,7 +54,7 @@ fn create_director(stops: Vec) -> ScoreDirector { routes, score: None, }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Route", "routes", get_routes, diff --git a/crates/solverforge-solver/src/heuristic/move/tests/list_swap.rs b/crates/solverforge-solver/src/heuristic/move/tests/list_swap.rs index 883a7c51..2544920f 100644 --- a/crates/solverforge-solver/src/heuristic/move/tests/list_swap.rs +++ b/crates/solverforge-solver/src/heuristic/move/tests/list_swap.rs @@ -51,7 +51,7 @@ fn create_director(vehicles: Vec) -> ScoreDirector vehicles, score: None, }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Vehicle", "vehicles", get_vehicles, diff --git a/crates/solverforge-solver/src/heuristic/move/tests/mod.rs b/crates/solverforge-solver/src/heuristic/move/tests/mod.rs index 0350e048..8f828160 100644 --- a/crates/solverforge-solver/src/heuristic/move/tests/mod.rs +++ b/crates/solverforge-solver/src/heuristic/move/tests/mod.rs @@ -2,7 +2,7 @@ use super::*; use solverforge_core::domain::{ - EntityDescriptor, PlanningSolution, SolutionDescriptor, TypedEntityExtractor, + EntityCollectionExtractor, EntityDescriptor, PlanningSolution, SolutionDescriptor, }; use solverforge_core::score::SoftScore; use solverforge_scoring::{Director, RecordingDirector, ScoreDirector}; diff --git a/crates/solverforge-solver/src/heuristic/move/tests/pillar_change.rs b/crates/solverforge-solver/src/heuristic/move/tests/pillar_change.rs index e1c4fbd8..427e56c7 100644 --- a/crates/solverforge-solver/src/heuristic/move/tests/pillar_change.rs +++ b/crates/solverforge-solver/src/heuristic/move/tests/pillar_change.rs @@ -40,7 +40,7 @@ fn create_director(employees: Vec) -> ScoreDirector) -> ScoreDirector { employees, score: None, }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Employee", "employees", |s: &Solution| &s.employees, diff --git a/crates/solverforge-solver/src/heuristic/move/tests/ruin.rs b/crates/solverforge-solver/src/heuristic/move/tests/ruin.rs index 6df5346f..f007f447 100644 --- a/crates/solverforge-solver/src/heuristic/move/tests/ruin.rs +++ b/crates/solverforge-solver/src/heuristic/move/tests/ruin.rs @@ -45,7 +45,7 @@ fn create_director(assignments: &[Option]) -> ScoreDirector { .map(|&a| Task { assigned_to: a }) .collect(); let solution = Schedule { tasks, score: None }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Task", "tasks", get_tasks, diff --git a/crates/solverforge-solver/src/heuristic/move/tests/sublist_change.rs b/crates/solverforge-solver/src/heuristic/move/tests/sublist_change.rs index 3f1a5ec7..567058d3 100644 --- a/crates/solverforge-solver/src/heuristic/move/tests/sublist_change.rs +++ b/crates/solverforge-solver/src/heuristic/move/tests/sublist_change.rs @@ -57,7 +57,7 @@ fn create_director(vehicles: Vec) -> ScoreDirector vehicles, score: None, }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Vehicle", "vehicles", get_vehicles, diff --git a/crates/solverforge-solver/src/heuristic/move/tests/sublist_swap.rs b/crates/solverforge-solver/src/heuristic/move/tests/sublist_swap.rs index 603420c5..430abfba 100644 --- a/crates/solverforge-solver/src/heuristic/move/tests/sublist_swap.rs +++ b/crates/solverforge-solver/src/heuristic/move/tests/sublist_swap.rs @@ -57,7 +57,7 @@ fn create_director(vehicles: Vec) -> ScoreDirector vehicles, score: None, }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Vehicle", "vehicles", get_vehicles, diff --git a/crates/solverforge-solver/src/heuristic/move/tests/swap.rs b/crates/solverforge-solver/src/heuristic/move/tests/swap.rs index bc311f2a..d8157cb6 100644 --- a/crates/solverforge-solver/src/heuristic/move/tests/swap.rs +++ b/crates/solverforge-solver/src/heuristic/move/tests/swap.rs @@ -45,7 +45,7 @@ fn set_priority(s: &mut TaskSolution, idx: usize, v: Option) { fn create_director(tasks: Vec) -> ScoreDirector { let solution = TaskSolution { tasks, score: None }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Task", "tasks", get_tasks, diff --git a/crates/solverforge-solver/src/heuristic/selector/decorator/cartesian_product.rs b/crates/solverforge-solver/src/heuristic/selector/decorator/cartesian_product.rs index 663c784a..f76c38fe 100644 --- a/crates/solverforge-solver/src/heuristic/selector/decorator/cartesian_product.rs +++ b/crates/solverforge-solver/src/heuristic/selector/decorator/cartesian_product.rs @@ -140,7 +140,9 @@ mod tests { use super::*; use crate::heuristic::r#move::ChangeMove; use crate::heuristic::selector::ChangeMoveSelector; - use solverforge_core::domain::{EntityDescriptor, SolutionDescriptor, TypedEntityExtractor}; + use solverforge_core::domain::{ + EntityCollectionExtractor, EntityDescriptor, SolutionDescriptor, + }; use solverforge_core::score::SoftScore; use solverforge_scoring::ScoreDirector; use std::any::TypeId; @@ -192,7 +194,7 @@ mod tests { fn create_director(tasks: Vec) -> ScoreDirector { let solution = Sol { tasks, score: None }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Task", "tasks", get_tasks, diff --git a/crates/solverforge-solver/src/heuristic/selector/decorator/count_limit.rs b/crates/solverforge-solver/src/heuristic/selector/decorator/count_limit.rs index ba96e700..af5a0adb 100644 --- a/crates/solverforge-solver/src/heuristic/selector/decorator/count_limit.rs +++ b/crates/solverforge-solver/src/heuristic/selector/decorator/count_limit.rs @@ -10,7 +10,7 @@ use solverforge_core::domain::PlanningSolution; use solverforge_scoring::Director; use crate::heuristic::r#move::Move; -use crate::heuristic::selector::typed_move_selector::MoveSelector; +use crate::heuristic::selector::move_selector::MoveSelector; /// Limits the number of moves yielded from an inner selector. /// diff --git a/crates/solverforge-solver/src/heuristic/selector/decorator/filtering.rs b/crates/solverforge-solver/src/heuristic/selector/decorator/filtering.rs index 5ed7765e..0e12a0db 100644 --- a/crates/solverforge-solver/src/heuristic/selector/decorator/filtering.rs +++ b/crates/solverforge-solver/src/heuristic/selector/decorator/filtering.rs @@ -10,7 +10,7 @@ use solverforge_core::domain::PlanningSolution; use solverforge_scoring::Director; use crate::heuristic::r#move::Move; -use crate::heuristic::selector::typed_move_selector::MoveSelector; +use crate::heuristic::selector::move_selector::MoveSelector; /// Filters moves from an inner selector using a predicate function. /// diff --git a/crates/solverforge-solver/src/heuristic/selector/decorator/probability.rs b/crates/solverforge-solver/src/heuristic/selector/decorator/probability.rs index a497eb7f..bd951075 100644 --- a/crates/solverforge-solver/src/heuristic/selector/decorator/probability.rs +++ b/crates/solverforge-solver/src/heuristic/selector/decorator/probability.rs @@ -14,7 +14,7 @@ use solverforge_core::domain::PlanningSolution; use solverforge_scoring::Director; use crate::heuristic::r#move::Move; -use crate::heuristic::selector::typed_move_selector::MoveSelector; +use crate::heuristic::selector::move_selector::MoveSelector; /// Probabilistically filters moves from an inner selector. /// diff --git a/crates/solverforge-solver/src/heuristic/selector/decorator/shuffling.rs b/crates/solverforge-solver/src/heuristic/selector/decorator/shuffling.rs index 6086338b..af87ca6e 100644 --- a/crates/solverforge-solver/src/heuristic/selector/decorator/shuffling.rs +++ b/crates/solverforge-solver/src/heuristic/selector/decorator/shuffling.rs @@ -15,7 +15,7 @@ use solverforge_core::domain::PlanningSolution; use solverforge_scoring::Director; use crate::heuristic::r#move::Move; -use crate::heuristic::selector::typed_move_selector::MoveSelector; +use crate::heuristic::selector::move_selector::MoveSelector; /// Shuffles moves from an inner selector randomly. /// diff --git a/crates/solverforge-solver/src/heuristic/selector/decorator/sorting.rs b/crates/solverforge-solver/src/heuristic/selector/decorator/sorting.rs index 66f66506..b2e9ffd9 100644 --- a/crates/solverforge-solver/src/heuristic/selector/decorator/sorting.rs +++ b/crates/solverforge-solver/src/heuristic/selector/decorator/sorting.rs @@ -11,7 +11,7 @@ use solverforge_core::domain::PlanningSolution; use solverforge_scoring::Director; use crate::heuristic::r#move::Move; -use crate::heuristic::selector::typed_move_selector::MoveSelector; +use crate::heuristic::selector::move_selector::MoveSelector; /// Sorts moves from an inner selector using a comparator function. /// diff --git a/crates/solverforge-solver/src/heuristic/selector/decorator/union.rs b/crates/solverforge-solver/src/heuristic/selector/decorator/union.rs index 2bb7b5a7..a6f1dd72 100644 --- a/crates/solverforge-solver/src/heuristic/selector/decorator/union.rs +++ b/crates/solverforge-solver/src/heuristic/selector/decorator/union.rs @@ -10,7 +10,7 @@ use solverforge_core::domain::PlanningSolution; use solverforge_scoring::Director; use crate::heuristic::r#move::Move; -use crate::heuristic::selector::typed_move_selector::MoveSelector; +use crate::heuristic::selector::move_selector::MoveSelector; /// Combines moves from two selectors into a single stream. /// diff --git a/crates/solverforge-solver/src/heuristic/selector/decorator/vec_union.rs b/crates/solverforge-solver/src/heuristic/selector/decorator/vec_union.rs index 313c1365..6aa81cea 100644 --- a/crates/solverforge-solver/src/heuristic/selector/decorator/vec_union.rs +++ b/crates/solverforge-solver/src/heuristic/selector/decorator/vec_union.rs @@ -14,7 +14,7 @@ use solverforge_scoring::Director; use crate::heuristic::r#move::Move; use crate::heuristic::r#move::MoveArena; -use crate::heuristic::selector::typed_move_selector::MoveSelector; +use crate::heuristic::selector::move_selector::MoveSelector; /// Combines moves from an arbitrary number of leaf selectors into a single stream. /// diff --git a/crates/solverforge-solver/src/heuristic/selector/k_opt/nearby.rs b/crates/solverforge-solver/src/heuristic/selector/k_opt/nearby.rs index 2f178ca7..efe63f29 100644 --- a/crates/solverforge-solver/src/heuristic/selector/k_opt/nearby.rs +++ b/crates/solverforge-solver/src/heuristic/selector/k_opt/nearby.rs @@ -12,7 +12,7 @@ use crate::heuristic::r#move::k_opt_reconnection::{ use crate::heuristic::r#move::{CutPoint, KOptMove}; use super::super::entity::EntitySelector; -use super::super::typed_move_selector::MoveSelector; +use super::super::move_selector::MoveSelector; use super::config::KOptConfig; use super::distance_meter::ListPositionDistanceMeter; diff --git a/crates/solverforge-solver/src/heuristic/selector/k_opt/selector.rs b/crates/solverforge-solver/src/heuristic/selector/k_opt/selector.rs index b22fca09..d460219c 100644 --- a/crates/solverforge-solver/src/heuristic/selector/k_opt/selector.rs +++ b/crates/solverforge-solver/src/heuristic/selector/k_opt/selector.rs @@ -13,7 +13,7 @@ use crate::heuristic::r#move::k_opt_reconnection::{ use crate::heuristic::r#move::KOptMove; use super::super::entity::EntitySelector; -use super::super::typed_move_selector::MoveSelector; +use super::super::move_selector::MoveSelector; use super::config::KOptConfig; use super::iterators::count_cut_combinations; use super::iterators::CutCombinationIterator; diff --git a/crates/solverforge-solver/src/heuristic/selector/k_opt/tests.rs b/crates/solverforge-solver/src/heuristic/selector/k_opt/tests.rs index 0960bc14..40d1be78 100644 --- a/crates/solverforge-solver/src/heuristic/selector/k_opt/tests.rs +++ b/crates/solverforge-solver/src/heuristic/selector/k_opt/tests.rs @@ -3,9 +3,9 @@ use super::*; use crate::heuristic::r#move::Move; use crate::heuristic::selector::entity::FromSolutionEntitySelector; -use crate::heuristic::selector::typed_move_selector::MoveSelector; +use crate::heuristic::selector::move_selector::MoveSelector; use solverforge_core::domain::{ - EntityDescriptor, PlanningSolution, SolutionDescriptor, TypedEntityExtractor, + EntityCollectionExtractor, EntityDescriptor, PlanningSolution, SolutionDescriptor, }; use solverforge_core::score::SoftScore; use solverforge_scoring::ScoreDirector; @@ -57,7 +57,7 @@ fn sublist_insert(s: &mut TspSolution, entity_idx: usize, pos: usize, items: Vec fn create_director(tours: Vec) -> ScoreDirector { let solution = TspSolution { tours, score: None }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Tour", "tours", get_tours, diff --git a/crates/solverforge-solver/src/heuristic/selector/list_change.rs b/crates/solverforge-solver/src/heuristic/selector/list_change.rs index 85e66267..cd4fabdb 100644 --- a/crates/solverforge-solver/src/heuristic/selector/list_change.rs +++ b/crates/solverforge-solver/src/heuristic/selector/list_change.rs @@ -54,7 +54,7 @@ use solverforge_scoring::Director; use crate::heuristic::r#move::ListChangeMove; use super::entity::EntitySelector; -use super::typed_move_selector::MoveSelector; +use super::move_selector::MoveSelector; /// A move selector that generates list change moves. /// diff --git a/crates/solverforge-solver/src/heuristic/selector/list_reverse.rs b/crates/solverforge-solver/src/heuristic/selector/list_reverse.rs index 4bd40ddd..787bdabf 100644 --- a/crates/solverforge-solver/src/heuristic/selector/list_reverse.rs +++ b/crates/solverforge-solver/src/heuristic/selector/list_reverse.rs @@ -62,7 +62,7 @@ use solverforge_scoring::Director; use crate::heuristic::r#move::{ListMoveImpl, ListReverseMove}; use super::entity::EntitySelector; -use super::typed_move_selector::MoveSelector; +use super::move_selector::MoveSelector; /// A move selector that generates 2-opt segment reversal moves. /// diff --git a/crates/solverforge-solver/src/heuristic/selector/list_swap.rs b/crates/solverforge-solver/src/heuristic/selector/list_swap.rs index de15f743..d4e99987 100644 --- a/crates/solverforge-solver/src/heuristic/selector/list_swap.rs +++ b/crates/solverforge-solver/src/heuristic/selector/list_swap.rs @@ -63,7 +63,7 @@ use solverforge_scoring::Director; use crate::heuristic::r#move::{ListMoveImpl, ListSwapMove}; use super::entity::EntitySelector; -use super::typed_move_selector::MoveSelector; +use super::move_selector::MoveSelector; /// A move selector that generates list swap moves. /// diff --git a/crates/solverforge-solver/src/heuristic/selector/mod.rs b/crates/solverforge-solver/src/heuristic/selector/mod.rs index 2d06098b..b8f4f424 100644 --- a/crates/solverforge-solver/src/heuristic/selector/mod.rs +++ b/crates/solverforge-solver/src/heuristic/selector/mod.rs @@ -12,6 +12,7 @@ pub mod list_reverse; pub mod list_ruin; pub mod list_swap; pub mod mimic; +pub mod move_selector; pub mod nearby; pub mod nearby_list_change; pub mod nearby_list_swap; @@ -20,8 +21,7 @@ pub mod ruin; mod selection_order; pub mod sublist_change; pub mod sublist_swap; -pub mod typed_move_selector; -pub mod typed_value; +pub mod value_selector; #[cfg(test)] mod tests; @@ -38,6 +38,11 @@ pub use list_reverse::{ListMoveListReverseSelector, ListReverseMoveSelector}; pub use list_ruin::ListRuinMoveSelector; pub use list_swap::{ListMoveListSwapSelector, ListSwapMoveSelector}; pub use mimic::{MimicRecorder, MimicRecordingEntitySelector, MimicReplayingEntitySelector}; +pub use move_selector::{ + ChangeMoveSelector, EitherChangeMoveSelector, EitherSwapMoveSelector, ListMoveKOptSelector, + ListMoveListChangeSelector, ListMoveListRuinSelector, ListMoveNearbyKOptSelector, MoveSelector, + SwapMoveSelector, +}; pub use nearby::{NearbyDistanceMeter, NearbyEntitySelector, NearbySelectionConfig}; pub use nearby_list_change::{ CrossEntityDistanceMeter, DefaultCrossEntityDistanceMeter, ListMoveNearbyListChangeSelector, @@ -49,12 +54,7 @@ pub use ruin::RuinMoveSelector; pub use selection_order::SelectionOrder; pub use sublist_change::{ListMoveSubListChangeSelector, SubListChangeMoveSelector}; pub use sublist_swap::{ListMoveSubListSwapSelector, SubListSwapMoveSelector}; -pub use typed_move_selector::{ - ChangeMoveSelector, EitherChangeMoveSelector, EitherSwapMoveSelector, ListMoveKOptSelector, - ListMoveListChangeSelector, ListMoveListRuinSelector, ListMoveNearbyKOptSelector, MoveSelector, - SwapMoveSelector, -}; -pub use typed_value::{ - FromSolutionTypedValueSelector, PerEntityTypedValueSelector, StaticTypedValueSelector, - TypedValueSelector, +pub use value_selector::{ + FromSolutionValueSelector, PerEntityValueSelector, RangeValueSelector, StaticValueSelector, + ValueSelector, }; diff --git a/crates/solverforge-solver/src/heuristic/selector/typed_move_selector.rs b/crates/solverforge-solver/src/heuristic/selector/move_selector.rs similarity index 98% rename from crates/solverforge-solver/src/heuristic/selector/typed_move_selector.rs rename to crates/solverforge-solver/src/heuristic/selector/move_selector.rs index 58acd9c0..11d56720 100644 --- a/crates/solverforge-solver/src/heuristic/selector/typed_move_selector.rs +++ b/crates/solverforge-solver/src/heuristic/selector/move_selector.rs @@ -14,7 +14,7 @@ use crate::heuristic::r#move::MoveArena; use crate::heuristic::r#move::{ChangeMove, EitherMove, ListMoveImpl, Move, SwapMove}; use super::entity::{EntityReference, EntitySelector, FromSolutionEntitySelector}; -use super::typed_value::{StaticTypedValueSelector, TypedValueSelector}; +use super::value_selector::{StaticValueSelector, ValueSelector}; /// A typed move selector that yields moves of type `M` directly. /// @@ -98,7 +98,7 @@ impl ChangeMoveSelector { } impl - ChangeMoveSelector> + ChangeMoveSelector> { pub fn simple( getter: fn(&S, usize) -> Option, @@ -109,7 +109,7 @@ impl ) -> Self { Self { entity_selector: FromSolutionEntitySelector::new(descriptor_index), - value_selector: StaticTypedValueSelector::new(values), + value_selector: StaticValueSelector::new(values), getter, setter, descriptor_index, @@ -124,7 +124,7 @@ where S: PlanningSolution, V: Clone + PartialEq + Send + Sync + Debug + 'static, ES: EntitySelector, - VS: TypedValueSelector, + VS: ValueSelector, { fn iter_moves<'a, D: Director>( &'a self, @@ -324,7 +324,7 @@ impl Debug for EitherChangeMoveSelector - EitherChangeMoveSelector> + EitherChangeMoveSelector> { pub fn simple( getter: fn(&S, usize) -> Option, @@ -350,7 +350,7 @@ where S: PlanningSolution, V: Clone + PartialEq + Send + Sync + Debug + 'static, ES: EntitySelector, - VS: TypedValueSelector, + VS: ValueSelector, { fn iter_moves<'a, D: Director>( &'a self, @@ -591,5 +591,5 @@ sublist_swap.rs, list_reverse.rs) alongside the selectors they wrap. */ #[cfg(test)] -#[path = "typed_move_selector_tests.rs"] +#[path = "move_selector_tests.rs"] mod tests; diff --git a/crates/solverforge-solver/src/heuristic/selector/typed_move_selector_tests.rs b/crates/solverforge-solver/src/heuristic/selector/move_selector_tests.rs similarity index 97% rename from crates/solverforge-solver/src/heuristic/selector/typed_move_selector_tests.rs rename to crates/solverforge-solver/src/heuristic/selector/move_selector_tests.rs index 5a5f6a49..967c6545 100644 --- a/crates/solverforge-solver/src/heuristic/selector/typed_move_selector_tests.rs +++ b/crates/solverforge-solver/src/heuristic/selector/move_selector_tests.rs @@ -2,7 +2,7 @@ use super::*; use solverforge_core::domain::{ - EntityDescriptor, PlanningSolution, SolutionDescriptor, TypedEntityExtractor, + EntityCollectionExtractor, EntityDescriptor, PlanningSolution, SolutionDescriptor, }; use solverforge_core::score::SoftScore; use solverforge_scoring::{RecordingDirector, ScoreDirector}; @@ -53,7 +53,7 @@ fn set_priority(s: &mut TaskSolution, idx: usize, v: Option) { fn create_director(tasks: Vec) -> ScoreDirector { let solution = TaskSolution { tasks, score: None }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Task", "tasks", get_tasks, diff --git a/crates/solverforge-solver/src/heuristic/selector/nearby_list_change.rs b/crates/solverforge-solver/src/heuristic/selector/nearby_list_change.rs index db971735..71f56de2 100644 --- a/crates/solverforge-solver/src/heuristic/selector/nearby_list_change.rs +++ b/crates/solverforge-solver/src/heuristic/selector/nearby_list_change.rs @@ -99,7 +99,7 @@ use solverforge_scoring::Director; use crate::heuristic::r#move::{ListChangeMove, ListMoveImpl}; use super::entity::EntitySelector; -use super::typed_move_selector::MoveSelector; +use super::move_selector::MoveSelector; /// Measures distance between two list positions, potentially across different entities. /// diff --git a/crates/solverforge-solver/src/heuristic/selector/nearby_list_swap.rs b/crates/solverforge-solver/src/heuristic/selector/nearby_list_swap.rs index 118664f8..03448f6d 100644 --- a/crates/solverforge-solver/src/heuristic/selector/nearby_list_swap.rs +++ b/crates/solverforge-solver/src/heuristic/selector/nearby_list_swap.rs @@ -81,8 +81,8 @@ use solverforge_scoring::Director; use crate::heuristic::r#move::{ListMoveImpl, ListSwapMove}; use super::entity::EntitySelector; +use super::move_selector::MoveSelector; use super::nearby_list_change::CrossEntityDistanceMeter; -use super::typed_move_selector::MoveSelector; /// A distance-pruned list swap move selector. /// diff --git a/crates/solverforge-solver/src/heuristic/selector/pillar_tests.rs b/crates/solverforge-solver/src/heuristic/selector/pillar_tests.rs index 9605649e..0c7517c7 100644 --- a/crates/solverforge-solver/src/heuristic/selector/pillar_tests.rs +++ b/crates/solverforge-solver/src/heuristic/selector/pillar_tests.rs @@ -3,7 +3,7 @@ use super::*; use crate::heuristic::selector::entity::FromSolutionEntitySelector; use solverforge_core::domain::{ - EntityDescriptor, PlanningSolution, SolutionDescriptor, TypedEntityExtractor, + EntityCollectionExtractor, EntityDescriptor, PlanningSolution, SolutionDescriptor, }; use solverforge_core::score::SoftScore; use solverforge_scoring::ScoreDirector; @@ -47,7 +47,7 @@ fn create_test_director(employees: Vec) -> ScoreDirector) -> ScoreDirector { let solution = TspSolution { tours, score: None }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Tour", "tours", get_tours, diff --git a/crates/solverforge-solver/src/heuristic/selector/tests/list_change.rs b/crates/solverforge-solver/src/heuristic/selector/tests/list_change.rs index fb390ae2..b6792ba8 100644 --- a/crates/solverforge-solver/src/heuristic/selector/tests/list_change.rs +++ b/crates/solverforge-solver/src/heuristic/selector/tests/list_change.rs @@ -5,7 +5,7 @@ use crate::heuristic::selector::entity::FromSolutionEntitySelector; use crate::heuristic::selector::list_change::ListChangeMoveSelector; use crate::heuristic::selector::MoveSelector; use solverforge_core::domain::{ - EntityDescriptor, PlanningSolution, SolutionDescriptor, TypedEntityExtractor, + EntityCollectionExtractor, EntityDescriptor, PlanningSolution, SolutionDescriptor, }; use solverforge_core::score::SoftScore; use solverforge_scoring::ScoreDirector; @@ -56,7 +56,7 @@ fn create_director(vehicles: Vec) -> ScoreDirector { vehicles, score: None, }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Vehicle", "vehicles", get_vehicles, diff --git a/crates/solverforge-solver/src/heuristic/selector/tests/mimic.rs b/crates/solverforge-solver/src/heuristic/selector/tests/mimic.rs index 08af0cd0..2455e1b4 100644 --- a/crates/solverforge-solver/src/heuristic/selector/tests/mimic.rs +++ b/crates/solverforge-solver/src/heuristic/selector/tests/mimic.rs @@ -1,7 +1,7 @@ // Tests for mimic selectors. use solverforge_core::domain::{ - EntityDescriptor, PlanningSolution, SolutionDescriptor, TypedEntityExtractor, + EntityCollectionExtractor, EntityDescriptor, PlanningSolution, SolutionDescriptor, }; use solverforge_core::score::SoftScore; use solverforge_scoring::ScoreDirector; @@ -53,7 +53,7 @@ fn create_test_director(n: usize) -> ScoreDirector { score: None, }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Queen", "queens", get_queens, diff --git a/crates/solverforge-solver/src/heuristic/selector/tests/mod.rs b/crates/solverforge-solver/src/heuristic/selector/tests/mod.rs index 0671cd05..3f1d4285 100644 --- a/crates/solverforge-solver/src/heuristic/selector/tests/mod.rs +++ b/crates/solverforge-solver/src/heuristic/selector/tests/mod.rs @@ -9,6 +9,6 @@ mod k_opt; mod list_change; mod list_ruin; mod mimic; +mod move_selector; mod nearby; mod pillar; -mod typed_move_selector; diff --git a/crates/solverforge-solver/src/heuristic/selector/tests/typed_move_selector.rs b/crates/solverforge-solver/src/heuristic/selector/tests/move_selector.rs similarity index 96% rename from crates/solverforge-solver/src/heuristic/selector/tests/typed_move_selector.rs rename to crates/solverforge-solver/src/heuristic/selector/tests/move_selector.rs index e2ffd9f1..8a754666 100644 --- a/crates/solverforge-solver/src/heuristic/selector/tests/typed_move_selector.rs +++ b/crates/solverforge-solver/src/heuristic/selector/tests/move_selector.rs @@ -1,14 +1,14 @@ // Tests for typed move selectors. use solverforge_core::domain::{ - EntityDescriptor, PlanningSolution, SolutionDescriptor, TypedEntityExtractor, + EntityCollectionExtractor, EntityDescriptor, PlanningSolution, SolutionDescriptor, }; use solverforge_core::score::SoftScore; use solverforge_scoring::{Director, RecordingDirector, ScoreDirector}; use std::any::TypeId; use crate::heuristic::r#move::Move; -use crate::heuristic::selector::typed_move_selector::{ +use crate::heuristic::selector::move_selector::{ ChangeMoveSelector, MoveSelector, SwapMoveSelector, }; @@ -57,7 +57,7 @@ fn set_priority(s: &mut TaskSolution, idx: usize, v: Option) { fn create_director(tasks: Vec) -> ScoreDirector { let solution = TaskSolution { tasks, score: None }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Task", "tasks", get_tasks, diff --git a/crates/solverforge-solver/src/heuristic/selector/tests/nearby.rs b/crates/solverforge-solver/src/heuristic/selector/tests/nearby.rs index a4df7fd9..2ea3811f 100644 --- a/crates/solverforge-solver/src/heuristic/selector/tests/nearby.rs +++ b/crates/solverforge-solver/src/heuristic/selector/tests/nearby.rs @@ -7,7 +7,7 @@ use crate::heuristic::selector::nearby::{ }; use crate::heuristic::selector::{EntityReference, EntitySelector}; use solverforge_core::domain::{ - EntityDescriptor, PlanningSolution, SolutionDescriptor, TypedEntityExtractor, + EntityCollectionExtractor, EntityDescriptor, PlanningSolution, SolutionDescriptor, }; use solverforge_core::score::SoftScore; use solverforge_scoring::{Director, ScoreDirector}; @@ -116,7 +116,7 @@ fn create_test_director() -> ScoreDirector { score: None, }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Location", "locations", get_locations, diff --git a/crates/solverforge-solver/src/heuristic/selector/tests/pillar.rs b/crates/solverforge-solver/src/heuristic/selector/tests/pillar.rs index 63d49ada..f59caa45 100644 --- a/crates/solverforge-solver/src/heuristic/selector/tests/pillar.rs +++ b/crates/solverforge-solver/src/heuristic/selector/tests/pillar.rs @@ -5,7 +5,7 @@ use crate::heuristic::selector::entity::FromSolutionEntitySelector; use crate::heuristic::selector::pillar::{ DefaultPillarSelector, Pillar, PillarSelector, SubPillarConfig, }; -use solverforge_core::domain::{EntityDescriptor, SolutionDescriptor, TypedEntityExtractor}; +use solverforge_core::domain::{EntityCollectionExtractor, EntityDescriptor, SolutionDescriptor}; use solverforge_core::score::SoftScore; use solverforge_scoring::ScoreDirector; use std::any::TypeId; @@ -48,7 +48,7 @@ fn create_test_director(employees: Vec) -> ScoreDirector`, -typed value selectors yield `V` directly with no heap allocation. +these selectors yield `V` directly with no heap allocation. */ use std::fmt::Debug; @@ -10,7 +10,7 @@ use std::marker::PhantomData; use solverforge_core::domain::PlanningSolution; use solverforge_scoring::Director; -/// A typed value selector that yields values of type `V` directly. +/// A value selector that yields values of type `V` directly. /// /// Unlike `ValueSelector` which returns `Arc`, this trait /// returns `V` inline, eliminating heap allocation per value. @@ -18,8 +18,8 @@ use solverforge_scoring::Director; /// # Type Parameters /// * `S` - The planning solution type /// * `V` - The value type -pub trait TypedValueSelector: Send + Debug { - // Returns an iterator over typed values for the given entity. +pub trait ValueSelector: Send + Debug { + // Returns an iterator over values for the given entity. fn iter_typed<'a, D: Director>( &'a self, score_director: &'a D, @@ -40,13 +40,13 @@ pub trait TypedValueSelector: Send + Debug { } } -/// A typed value selector with a static list of values. -pub struct StaticTypedValueSelector { +/// A value selector with a static list of values. +pub struct StaticValueSelector { values: Vec, _phantom: PhantomData S>, } -impl Clone for StaticTypedValueSelector { +impl Clone for StaticValueSelector { fn clone(&self) -> Self { Self { values: self.values.clone(), @@ -55,15 +55,15 @@ impl Clone for StaticTypedValueSelector { } } -impl Debug for StaticTypedValueSelector { +impl Debug for StaticValueSelector { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("StaticTypedValueSelector") + f.debug_struct("StaticValueSelector") .field("values", &self.values) .finish() } } -impl StaticTypedValueSelector { +impl StaticValueSelector { pub fn new(values: Vec) -> Self { Self { values, @@ -76,7 +76,7 @@ impl StaticTypedValueSelector { } } -impl TypedValueSelector for StaticTypedValueSelector +impl ValueSelector for StaticValueSelector where S: PlanningSolution, V: Clone + Send + Debug + 'static, @@ -100,19 +100,19 @@ where } } -/// A typed value selector that extracts values from the solution using a function pointer. -pub struct FromSolutionTypedValueSelector { +/// A value selector that extracts values from the solution using a function pointer. +pub struct FromSolutionValueSelector { extractor: fn(&S) -> Vec, _phantom: PhantomData<(fn() -> S, fn() -> V)>, } -impl Debug for FromSolutionTypedValueSelector { +impl Debug for FromSolutionValueSelector { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("FromSolutionTypedValueSelector").finish() + f.debug_struct("FromSolutionValueSelector").finish() } } -impl FromSolutionTypedValueSelector { +impl FromSolutionValueSelector { pub fn new(extractor: fn(&S) -> Vec) -> Self { Self { extractor, @@ -121,18 +121,18 @@ impl FromSolutionTypedValueSelector { } } -pub struct PerEntityTypedValueSelector { +pub struct PerEntityValueSelector { extractor: fn(&S, usize) -> Vec, _phantom: PhantomData<(fn() -> S, fn() -> V)>, } -impl Debug for PerEntityTypedValueSelector { +impl Debug for PerEntityValueSelector { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("PerEntityTypedValueSelector").finish() + f.debug_struct("PerEntityValueSelector").finish() } } -impl PerEntityTypedValueSelector { +impl PerEntityValueSelector { pub fn new(extractor: fn(&S, usize) -> Vec) -> Self { Self { extractor, @@ -141,7 +141,7 @@ impl PerEntityTypedValueSelector { } } -impl TypedValueSelector for PerEntityTypedValueSelector +impl ValueSelector for PerEntityValueSelector where S: PlanningSolution, V: Clone + Send + Debug + 'static, @@ -165,7 +165,7 @@ where } } -impl TypedValueSelector for FromSolutionTypedValueSelector +impl ValueSelector for FromSolutionValueSelector where S: PlanningSolution, V: Clone + Send + Debug + 'static, @@ -190,7 +190,7 @@ where } } -/// A typed value selector that generates a range of usize values 0..count. +/// A value selector that generates a range of usize values 0..count. /// /// Uses a function pointer to get the count from the solution. pub struct RangeValueSelector { @@ -213,7 +213,7 @@ impl RangeValueSelector { } } -impl TypedValueSelector for RangeValueSelector +impl ValueSelector for RangeValueSelector where S: PlanningSolution, { @@ -240,7 +240,9 @@ where #[cfg(test)] mod tests { use super::*; - use solverforge_core::domain::{EntityDescriptor, SolutionDescriptor, TypedEntityExtractor}; + use solverforge_core::domain::{ + EntityCollectionExtractor, EntityDescriptor, SolutionDescriptor, + }; use solverforge_core::score::SoftScore; use solverforge_scoring::ScoreDirector; use std::any::TypeId; @@ -269,7 +271,7 @@ mod tests { fn create_director(tasks: Vec) -> ScoreDirector { let solution = TaskSolution { tasks, score: None }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Task", "tasks", |s: &TaskSolution| &s.tasks, @@ -283,12 +285,12 @@ mod tests { } #[test] - fn test_static_typed_value_selector() { + fn test_static_value_selector_selector() { let director = create_director(vec![Task { id: 0, priority: None, }]); - let selector = StaticTypedValueSelector::::new(vec![1, 2, 3, 4, 5]); + let selector = StaticValueSelector::::new(vec![1, 2, 3, 4, 5]); let values: Vec<_> = selector.iter_typed(&director, 0, 0).collect(); assert_eq!(values, vec![1, 2, 3, 4, 5]); @@ -296,7 +298,7 @@ mod tests { } #[test] - fn test_from_solution_typed_value_selector() { + fn test_from_solution_value_selector_selector() { let director = create_director(vec![ Task { id: 0, @@ -318,7 +320,7 @@ mod tests { s.tasks.iter().filter_map(|t| t.priority).collect() } - let selector = FromSolutionTypedValueSelector::new(extract_priorities); + let selector = FromSolutionValueSelector::new(extract_priorities); let values: Vec<_> = selector.iter_typed(&director, 0, 0).collect(); assert_eq!(values, vec![10, 20]); diff --git a/crates/solverforge-solver/src/lib.rs b/crates/solverforge-solver/src/lib.rs index d08be4ae..cc689b85 100644 --- a/crates/solverforge-solver/src/lib.rs +++ b/crates/solverforge-solver/src/lib.rs @@ -58,7 +58,7 @@ pub use heuristic::{ EntityReference, EntitySelector, FromSolutionEntitySelector, - FromSolutionTypedValueSelector, + FromSolutionValueSelector, KOptConfig, KOptMove, KOptMoveSelector, @@ -82,11 +82,11 @@ pub use heuristic::{ RuinMove, RuinMoveSelector, SelectionOrder, - StaticTypedValueSelector, + StaticValueSelector, SubPillarConfig, SwapMove, SwapMoveSelector, - TypedValueSelector, + ValueSelector, // Vec union selector VecUnionSelector, }; diff --git a/crates/solverforge-solver/src/manager/phase_factory/k_opt.rs b/crates/solverforge-solver/src/manager/phase_factory/k_opt.rs index 92ee0f51..e1192548 100644 --- a/crates/solverforge-solver/src/manager/phase_factory/k_opt.rs +++ b/crates/solverforge-solver/src/manager/phase_factory/k_opt.rs @@ -194,7 +194,7 @@ where fn solve(&mut self, solver_scope: &mut SolverScope) { use crate::heuristic::r#move::Move; use crate::heuristic::selector::entity::FromSolutionEntitySelector; - use crate::heuristic::selector::typed_move_selector::MoveSelector; + use crate::heuristic::selector::move_selector::MoveSelector; let mut phase_scope = PhaseScope::new(solver_scope, 0); diff --git a/crates/solverforge-solver/src/manager/phase_factory_tests.rs b/crates/solverforge-solver/src/manager/phase_factory_tests.rs index 982cb2b0..405edbd1 100644 --- a/crates/solverforge-solver/src/manager/phase_factory_tests.rs +++ b/crates/solverforge-solver/src/manager/phase_factory_tests.rs @@ -2,10 +2,10 @@ use super::*; use crate::heuristic::r#move::ChangeMove; -use crate::heuristic::selector::{FromSolutionEntitySelector, StaticTypedValueSelector}; +use crate::heuristic::selector::{FromSolutionEntitySelector, StaticValueSelector}; use crate::phase::construction::{EntityPlacer, ForagerType, QueuedEntityPlacer}; use crate::scope::SolverScope; -use solverforge_core::domain::{EntityDescriptor, SolutionDescriptor, TypedEntityExtractor}; +use solverforge_core::domain::{EntityDescriptor, SolutionDescriptor, EntityCollectionExtractor}; use solverforge_core::score::SoftScore; use solverforge_scoring::{Director, ScoreDirector}; use std::any::TypeId; @@ -72,7 +72,7 @@ fn create_test_director( ) -> ScoreDirector { let solution = TestSolution { tasks, score: None }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Task", "tasks", get_tasks, @@ -103,14 +103,14 @@ type TestPlacer = QueuedEntityPlacer< TestSolution, i64, FromSolutionEntitySelector, - StaticTypedValueSelector, + StaticValueSelector, >; fn create_placer_factory() -> impl Fn() -> TestPlacer + Send + Sync { || { QueuedEntityPlacer::new( FromSolutionEntitySelector::new(0), - StaticTypedValueSelector::new(vec![1i64, 2, 3, 4, 5]), + StaticValueSelector::new(vec![1i64, 2, 3, 4, 5]), get_task_priority, set_task_priority, 0, diff --git a/crates/solverforge-solver/src/manager/phase_factory_tests_localsearch.rs b/crates/solverforge-solver/src/manager/phase_factory_tests_localsearch.rs index 4b78f512..66415fbb 100644 --- a/crates/solverforge-solver/src/manager/phase_factory_tests_localsearch.rs +++ b/crates/solverforge-solver/src/manager/phase_factory_tests_localsearch.rs @@ -3,12 +3,12 @@ use super::*; use crate::heuristic::r#move::ChangeMove; use crate::heuristic::selector::{ - ChangeMoveSelector, FromSolutionEntitySelector, StaticTypedValueSelector, + ChangeMoveSelector, FromSolutionEntitySelector, StaticValueSelector, }; use crate::heuristic::MoveSelector; use crate::phase::construction::{EntityPlacer, QueuedEntityPlacer}; use crate::scope::SolverScope; -use solverforge_core::domain::{EntityDescriptor, SolutionDescriptor, TypedEntityExtractor}; +use solverforge_core::domain::{EntityDescriptor, SolutionDescriptor, EntityCollectionExtractor}; use solverforge_core::score::SoftScore; use solverforge_scoring::{Director, ScoreDirector}; use std::any::TypeId; @@ -74,7 +74,7 @@ fn create_test_director( ) -> ScoreDirector { let solution = TestSolution { tasks, score: None }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Task", "tasks", get_tasks, @@ -118,14 +118,14 @@ type TestPlacer = QueuedEntityPlacer< TestSolution, i64, FromSolutionEntitySelector, - StaticTypedValueSelector, + StaticValueSelector, >; fn create_placer_factory() -> impl Fn() -> TestPlacer + Send + Sync { || { QueuedEntityPlacer::new( FromSolutionEntitySelector::new(0), - StaticTypedValueSelector::new(vec![1i64, 2, 3, 4, 5]), + StaticValueSelector::new(vec![1i64, 2, 3, 4, 5]), get_task_priority, set_task_priority, 0, @@ -138,7 +138,7 @@ type TestMoveSelector = ChangeMoveSelector< TestSolution, i64, FromSolutionEntitySelector, - StaticTypedValueSelector, + StaticValueSelector, >; fn create_move_selector_factory() -> impl Fn() -> TestMoveSelector + Send + Sync { diff --git a/crates/solverforge-solver/src/phase/construction/forager_tests.rs b/crates/solverforge-solver/src/phase/construction/forager_tests.rs index 3f3c2c4b..781c4713 100644 --- a/crates/solverforge-solver/src/phase/construction/forager_tests.rs +++ b/crates/solverforge-solver/src/phase/construction/forager_tests.rs @@ -4,7 +4,7 @@ use super::*; use crate::heuristic::r#move::ChangeMove; use crate::heuristic::selector::EntityReference; use solverforge_core::domain::{ - EntityDescriptor, PlanningSolution, SolutionDescriptor, TypedEntityExtractor, + EntityCollectionExtractor, EntityDescriptor, PlanningSolution, SolutionDescriptor, }; use solverforge_core::score::SoftScore; use solverforge_scoring::ScoreDirector; @@ -57,7 +57,7 @@ fn create_test_director() -> ScoreDirector { score: None, }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Queen", "queens", get_queens, diff --git a/crates/solverforge-solver/src/phase/construction/phase.rs b/crates/solverforge-solver/src/phase/construction/phase.rs index 64e22abb..e85cbb73 100644 --- a/crates/solverforge-solver/src/phase/construction/phase.rs +++ b/crates/solverforge-solver/src/phase/construction/phase.rs @@ -171,7 +171,7 @@ where #[cfg(test)] mod tests { use super::*; - use crate::heuristic::selector::{FromSolutionEntitySelector, StaticTypedValueSelector}; + use crate::heuristic::selector::{FromSolutionEntitySelector, StaticValueSelector}; use crate::phase::construction::{BestFitForager, FirstFitForager, QueuedEntityPlacer}; use crate::test_utils::{ create_simple_nqueens_director, get_queen_row, set_queen_row, NQueensSolution, @@ -183,10 +183,10 @@ mod tests { NQueensSolution, i64, FromSolutionEntitySelector, - StaticTypedValueSelector, + StaticValueSelector, > { let es = FromSolutionEntitySelector::new(0); - let vs = StaticTypedValueSelector::new(values); + let vs = StaticValueSelector::new(values); QueuedEntityPlacer::new(es, vs, get_queen_row, set_queen_row, 0, "row") } diff --git a/crates/solverforge-solver/src/phase/construction/placer.rs b/crates/solverforge-solver/src/phase/construction/placer.rs index 403006b8..0fde37a4 100644 --- a/crates/solverforge-solver/src/phase/construction/placer.rs +++ b/crates/solverforge-solver/src/phase/construction/placer.rs @@ -11,7 +11,7 @@ use solverforge_core::domain::PlanningSolution; use solverforge_scoring::Director; use crate::heuristic::r#move::{ChangeMove, Move}; -use crate::heuristic::selector::{EntityReference, EntitySelector, TypedValueSelector}; +use crate::heuristic::selector::{EntityReference, EntitySelector, ValueSelector}; /// A placement represents an entity that needs a value assigned, /// along with the candidate moves to assign values. @@ -100,7 +100,7 @@ pub struct QueuedEntityPlacer where S: PlanningSolution, ES: EntitySelector, - VS: TypedValueSelector, + VS: ValueSelector, { // The entity selector. entity_selector: ES, @@ -121,7 +121,7 @@ impl QueuedEntityPlacer where S: PlanningSolution, ES: EntitySelector, - VS: TypedValueSelector, + VS: ValueSelector, { pub fn new( entity_selector: ES, @@ -147,7 +147,7 @@ impl Debug for QueuedEntityPlacer where S: PlanningSolution, ES: EntitySelector + Debug, - VS: TypedValueSelector + Debug, + VS: ValueSelector + Debug, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("QueuedEntityPlacer") @@ -163,7 +163,7 @@ where S: PlanningSolution, V: Clone + PartialEq + Send + Sync + Debug + 'static, ES: EntitySelector, - VS: TypedValueSelector, + VS: ValueSelector, { fn get_placements>( &self, @@ -226,7 +226,7 @@ where /// ``` /// use solverforge_solver::phase::construction::{SortedEntityPlacer, QueuedEntityPlacer, EntityPlacer}; /// use solverforge_solver::heuristic::r#move::ChangeMove; -/// use solverforge_solver::heuristic::selector::{FromSolutionEntitySelector, StaticTypedValueSelector}; +/// use solverforge_solver::heuristic::selector::{FromSolutionEntitySelector, StaticValueSelector}; /// use solverforge_core::domain::PlanningSolution; /// use solverforge_core::score::SoftScore; /// use solverforge_scoring::ScoreDirector; diff --git a/crates/solverforge-solver/src/phase/construction/placer_tests.rs b/crates/solverforge-solver/src/phase/construction/placer_tests.rs index 7c019c31..7f43b126 100644 --- a/crates/solverforge-solver/src/phase/construction/placer_tests.rs +++ b/crates/solverforge-solver/src/phase/construction/placer_tests.rs @@ -1,9 +1,9 @@ // Tests for entity placers. use super::*; -use crate::heuristic::selector::{FromSolutionEntitySelector, StaticTypedValueSelector}; +use crate::heuristic::selector::{FromSolutionEntitySelector, StaticValueSelector}; use solverforge_core::domain::{ - EntityDescriptor, PlanningSolution, SolutionDescriptor, TypedEntityExtractor, + EntityCollectionExtractor, EntityDescriptor, PlanningSolution, SolutionDescriptor, }; use solverforge_core::score::SoftScore; use solverforge_scoring::ScoreDirector; @@ -66,7 +66,7 @@ fn create_test_director(initialized: &[bool]) -> ScoreDirector, + crate::heuristic::selector::StaticValueSelector, > { ChangeMoveSelector::simple(get_queen_row, set_queen_row, 0, "row", values) } diff --git a/crates/solverforge-solver/src/phase/vnd/phase.rs b/crates/solverforge-solver/src/phase/vnd/phase.rs index ccefa56f..82d2556b 100644 --- a/crates/solverforge-solver/src/phase/vnd/phase.rs +++ b/crates/solverforge-solver/src/phase/vnd/phase.rs @@ -244,7 +244,7 @@ mod tests { NQueensSolution, i64, crate::heuristic::selector::FromSolutionEntitySelector, - crate::heuristic::selector::StaticTypedValueSelector, + crate::heuristic::selector::StaticValueSelector, > { ChangeMoveSelector::simple(get_queen_row, set_queen_row, 0, "row", values) } diff --git a/crates/solverforge-solver/src/realtime/problem_change.rs b/crates/solverforge-solver/src/realtime/problem_change.rs index 663ed109..73a669f2 100644 --- a/crates/solverforge-solver/src/realtime/problem_change.rs +++ b/crates/solverforge-solver/src/realtime/problem_change.rs @@ -172,7 +172,9 @@ where #[cfg(test)] mod tests { use super::*; - use solverforge_core::domain::{EntityDescriptor, SolutionDescriptor, TypedEntityExtractor}; + use solverforge_core::domain::{ + EntityCollectionExtractor, EntityDescriptor, SolutionDescriptor, + }; use solverforge_core::score::SoftScore; use solverforge_scoring::ScoreDirector; use std::any::TypeId; @@ -207,7 +209,7 @@ mod tests { fn create_director(tasks: Vec) -> ScoreDirector { let solution = TaskSchedule { tasks, score: None }; - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Task", "tasks", get_tasks, diff --git a/crates/solverforge-solver/src/unified_search.rs b/crates/solverforge-solver/src/unified_search.rs index 192b25a5..96839dc4 100644 --- a/crates/solverforge-solver/src/unified_search.rs +++ b/crates/solverforge-solver/src/unified_search.rs @@ -14,8 +14,8 @@ use crate::descriptor_standard::{ }; use crate::heuristic::r#move::{ListMoveImpl, Move, MoveArena}; use crate::heuristic::selector::decorator::VecUnionSelector; +use crate::heuristic::selector::move_selector::MoveSelector; use crate::heuristic::selector::nearby_list_change::CrossEntityDistanceMeter; -use crate::heuristic::selector::typed_move_selector::MoveSelector; use crate::phase::dynamic_vnd::DynamicVndPhase; use crate::phase::localsearch::{ AcceptedCountForager, LocalSearchPhase, SimulatedAnnealingAcceptor, diff --git a/crates/solverforge-test/src/entity.rs b/crates/solverforge-test/src/entity.rs index 72c1fac4..3711e7a5 100644 --- a/crates/solverforge-test/src/entity.rs +++ b/crates/solverforge-test/src/entity.rs @@ -17,7 +17,8 @@ let descriptor = create_test_descriptor(); */ use solverforge_core::domain::{ - EntityDescriptor, EntityExtractor, PlanningSolution, SolutionDescriptor, TypedEntityExtractor, + EntityCollectionExtractor, EntityDescriptor, EntityExtractor, PlanningSolution, + SolutionDescriptor, }; use solverforge_core::score::SoftScore; use std::any::TypeId; @@ -115,7 +116,7 @@ pub fn set_entity_value(s: &mut TestSolution, idx: usize, v: Option) { } pub fn create_test_entity_extractor() -> Box { - Box::new(TypedEntityExtractor::new( + Box::new(EntityCollectionExtractor::new( "TestEntity", "entities", get_test_entities, diff --git a/crates/solverforge-test/src/nqueens.rs b/crates/solverforge-test/src/nqueens.rs index db3114e6..62322965 100644 --- a/crates/solverforge-test/src/nqueens.rs +++ b/crates/solverforge-test/src/nqueens.rs @@ -17,7 +17,7 @@ assert_eq!(score, SoftScore::of(0)); // No conflicts */ use solverforge_core::domain::{ - EntityDescriptor, PlanningSolution, SolutionDescriptor, TypedEntityExtractor, + EntityCollectionExtractor, EntityDescriptor, PlanningSolution, SolutionDescriptor, }; use solverforge_core::score::SoftScore; use std::any::TypeId; @@ -178,7 +178,7 @@ pub fn calculate_conflicts(solution: &NQueensSolution) -> SoftScore { } pub fn create_nqueens_descriptor() -> SolutionDescriptor { - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Queen", "queens", get_queens, diff --git a/crates/solverforge-test/src/task.rs b/crates/solverforge-test/src/task.rs index 129f579c..63e6b8a6 100644 --- a/crates/solverforge-test/src/task.rs +++ b/crates/solverforge-test/src/task.rs @@ -18,7 +18,7 @@ assert_eq!(solution.tasks.len(), 3); */ use solverforge_core::domain::{ - EntityDescriptor, PlanningSolution, SolutionDescriptor, TypedEntityExtractor, + EntityCollectionExtractor, EntityDescriptor, PlanningSolution, SolutionDescriptor, }; use solverforge_core::score::SoftScore; use std::any::TypeId; @@ -94,7 +94,7 @@ pub fn set_priority(s: &mut TaskSolution, idx: usize, v: Option) { } pub fn create_task_descriptor() -> SolutionDescriptor { - let extractor = Box::new(TypedEntityExtractor::new( + let extractor = Box::new(EntityCollectionExtractor::new( "Task", "tasks", get_tasks, diff --git a/crates/solverforge/WIREFRAME.md b/crates/solverforge/WIREFRAME.md index 73248306..23c703bc 100644 --- a/crates/solverforge/WIREFRAME.md +++ b/crates/solverforge/WIREFRAME.md @@ -135,7 +135,7 @@ Used exclusively by macro-generated code. Not public API. **Domain types (from `solverforge-core::domain`):** - `PlanningEntity`, `PlanningSolution`, `PlanningId`, `ProblemFact` - `EntityDescriptor`, `SolutionDescriptor`, `ProblemFactDescriptor`, `VariableDescriptor` -- `TypedEntityExtractor` +- `EntityCollectionExtractor` - `ShadowVariableKind` **Scoring (from `solverforge-scoring`):** diff --git a/crates/solverforge/src/lib.rs b/crates/solverforge/src/lib.rs index 9bd105a6..fa1f2826 100644 --- a/crates/solverforge/src/lib.rs +++ b/crates/solverforge/src/lib.rs @@ -143,9 +143,9 @@ pub mod __internal { // Domain types pub use solverforge_core::domain::{ - EntityDescriptor, PlanningEntity, PlanningId, PlanningSolution, ProblemFact, - ProblemFactDescriptor, ShadowVariableKind, SolutionDescriptor, TypedEntityExtractor, - ValueRangeType, VariableDescriptor, + EntityCollectionExtractor, EntityDescriptor, PlanningEntity, PlanningId, PlanningSolution, + ProblemFact, ProblemFactDescriptor, ShadowVariableKind, SolutionDescriptor, ValueRangeType, + VariableDescriptor, }; // Scoring diff --git a/docs/typed-contract-audit.md b/docs/typed-contract-audit.md new file mode 100644 index 00000000..0a019814 --- /dev/null +++ b/docs/typed-contract-audit.md @@ -0,0 +1,69 @@ +# Typed Contract Audit and Unification Plan + +Date: 2026-03-31 + +## Goal + +Audit the former `Typed*` / `typed_*` public surface, explain the architectural boundary that remains intentional, and record the unified naming adopted in this refactor. + +## Scope audited + +- `crates/solverforge-core` +- `crates/solverforge-solver` +- `crates/solverforge-scoring` +- Macro-generated call sites in `crates/solverforge-macros` +- Public re-exports in `crates/solverforge` + +## What existed before this refactor + +### Core descriptor boundary + +- `TypedEntityExtractor` was the concrete implementation behind the dynamic `EntityExtractor` descriptor boundary. +- That adapter existed to bridge runtime descriptor storage (`Box`) with strongly typed solution field access. + +### Solver selector layer + +- `typed_value.rs` exposed: + - `TypedValueSelector` + - `StaticTypedValueSelector` + - `FromSolutionTypedValueSelector` +- `release/0.7.0` had also introduced `PerEntityTypedValueSelector`, which followed the same naming pattern and therefore belongs in the same cleanup. +- `typed_move_selector.rs` already exposed neutral trait names such as `MoveSelector`, so the drift there was primarily in module/file naming rather than the public trait names themselves. + +### Scoring references to "typed" + +- Remaining scoring references were descriptive prose rather than separate prefixed public contracts. + +## Architectural assessment + +- Prefix-free naming fits the current architecture better. In generic Rust APIs, the type information is already explicit in the signatures. +- The extractor adapter remains necessary. `EntityDescriptor` still depends on an object-safe erased boundary, so the refactor renames that adapter rather than removing it. +- The move-selector layer was already conceptually unified; the cleanup there is about removing naming drift in modules and re-exports. + +## Adopted unified naming + +- `TypedEntityExtractor` -> `EntityCollectionExtractor` +- `TypedValueSelector` -> `ValueSelector` +- `StaticTypedValueSelector` -> `StaticValueSelector` +- `FromSolutionTypedValueSelector` -> `FromSolutionValueSelector` +- `PerEntityTypedValueSelector` -> `PerEntityValueSelector` +- `typed_value.rs` -> `value_selector.rs` +- `typed_move_selector.rs` -> `move_selector.rs` + +## Migration notes + +- This remains a single breaking sweep with no compatibility shims, consistent with repository policy. +- Macro expansion paths and facade re-exports are updated in the same change as the core and solver renames. +- Relevant wireframes are updated in lockstep so the documented public surface matches the implemented API. +- The selector method name `iter_typed(...)` is intentionally left as-is in this refactor. The drafts agreed on removing the public `Typed*` prefixes first; a method-level rename can be handled separately if the project wants that additional API break. + +## Risk summary + +- Runtime risk is low because this is primarily a symbol and module rename. +- Integration risk is medium because downstream imports and type names change atomically. +- Mechanical scope is high because tests, macro-generated paths, re-exports, and wireframes all move together. + +## Conclusion + +- The repository now has one neutral selector/extractor naming model with the intentional erased descriptor boundary preserved. +- The synthesis branch combines the implementation intent from the code draft with the explanatory audit intent from the two documentation drafts, while also covering the additional `PerEntityTypedValueSelector` surface that existed on `release/0.7.0`.