pub struct ComplementedConstraintStream<S, A, B, K, EA, EB, KA, KB, C, D, Sc>where
Sc: Score,{ /* private fields */ }Expand description
Zero-erasure constraint stream with complemented groups.
ComplementedConstraintStream results from calling complement on a
GroupedConstraintStream. It ensures all keys from a complement source
are represented, using default values for missing keys.
The key function for A entities returns Option<K> to allow skipping
entities without valid keys (e.g., unassigned shifts).
§Type Parameters
S- Solution typeA- Original entity type (e.g., Shift)B- Complement entity type (e.g., Employee)K- Group key typeEA- Extractor for A entitiesEB- Extractor for B entities (complement source)KA- Key function for A (returnsOption<K>to allow filtering)KB- Key function for BC- Collector typeD- Default value functionSc- Score type
§Example
use solverforge_scoring::stream::ConstraintFactory;
use solverforge_scoring::stream::collector::count;
use solverforge_scoring::api::constraint_set::IncrementalConstraint;
use solverforge_core::score::SimpleScore;
#[derive(Clone, Hash, PartialEq, Eq)]
struct Employee { id: usize }
#[derive(Clone, Hash, PartialEq, Eq)]
struct Shift { employee_id: usize }
#[derive(Clone)]
struct Schedule {
employees: Vec<Employee>,
shifts: Vec<Shift>,
}
// Count shifts per employee, including employees with 0 shifts
let constraint = ConstraintFactory::<Schedule, SimpleScore>::new()
.for_each(|s: &Schedule| &s.shifts)
.group_by(|shift: &Shift| shift.employee_id, count())
.complement(
|s: &Schedule| s.employees.as_slice(),
|emp: &Employee| emp.id,
|_emp: &Employee| 0usize,
)
.penalize_with(|count: &usize| SimpleScore::of(*count as i64))
.as_constraint("Shift count");
let schedule = Schedule {
employees: vec![Employee { id: 0 }, Employee { id: 1 }, Employee { id: 2 }],
shifts: vec![
Shift { employee_id: 0 },
Shift { employee_id: 0 },
// Employee 1 has 0 shifts, Employee 2 has 0 shifts
],
};
// Employee 0: 2, Employee 1: 0, Employee 2: 0 → Total: -2
assert_eq!(constraint.evaluate(&schedule), SimpleScore::of(-2));Implementations§
Source§impl<S, A, B, K, EA, EB, KA, KB, C, D, Sc> ComplementedConstraintStream<S, A, B, K, EA, EB, KA, KB, C, D, Sc>where
S: Send + Sync + 'static,
A: Clone + Send + Sync + 'static,
B: Clone + Send + Sync + 'static,
K: Clone + Eq + Hash + Send + Sync + 'static,
EA: Fn(&S) -> &[A] + Send + Sync,
EB: Fn(&S) -> &[B] + Send + Sync,
KA: Fn(&A) -> Option<K> + Send + Sync,
KB: Fn(&B) -> K + Send + Sync,
C: UniCollector<A> + Send + Sync + 'static,
C::Accumulator: Send + Sync,
C::Result: Clone + Send + Sync,
D: Fn(&B) -> C::Result + Send + Sync,
Sc: Score + 'static,
impl<S, A, B, K, EA, EB, KA, KB, C, D, Sc> ComplementedConstraintStream<S, A, B, K, EA, EB, KA, KB, C, D, Sc>where
S: Send + Sync + 'static,
A: Clone + Send + Sync + 'static,
B: Clone + Send + Sync + 'static,
K: Clone + Eq + Hash + Send + Sync + 'static,
EA: Fn(&S) -> &[A] + Send + Sync,
EB: Fn(&S) -> &[B] + Send + Sync,
KA: Fn(&A) -> Option<K> + Send + Sync,
KB: Fn(&B) -> K + Send + Sync,
C: UniCollector<A> + Send + Sync + 'static,
C::Accumulator: Send + Sync,
C::Result: Clone + Send + Sync,
D: Fn(&B) -> C::Result + Send + Sync,
Sc: Score + 'static,
Sourcepub fn penalize_with<W>(
self,
weight_fn: W,
) -> ComplementedConstraintBuilder<S, A, B, K, EA, EB, KA, KB, C, D, W, Sc>
pub fn penalize_with<W>( self, weight_fn: W, ) -> ComplementedConstraintBuilder<S, A, B, K, EA, EB, KA, KB, C, D, W, Sc>
Penalizes each complemented group with a weight based on the result.
Sourcepub fn penalize_hard_with<W>(
self,
weight_fn: W,
) -> ComplementedConstraintBuilder<S, A, B, K, EA, EB, KA, KB, C, D, W, Sc>
pub fn penalize_hard_with<W>( self, weight_fn: W, ) -> ComplementedConstraintBuilder<S, A, B, K, EA, EB, KA, KB, C, D, W, Sc>
Penalizes each complemented group, explicitly marked as hard constraint.
Sourcepub fn reward_with<W>(
self,
weight_fn: W,
) -> ComplementedConstraintBuilder<S, A, B, K, EA, EB, KA, KB, C, D, W, Sc>
pub fn reward_with<W>( self, weight_fn: W, ) -> ComplementedConstraintBuilder<S, A, B, K, EA, EB, KA, KB, C, D, W, Sc>
Rewards each complemented group with a weight based on the result.
Sourcepub fn reward_hard_with<W>(
self,
weight_fn: W,
) -> ComplementedConstraintBuilder<S, A, B, K, EA, EB, KA, KB, C, D, W, Sc>
pub fn reward_hard_with<W>( self, weight_fn: W, ) -> ComplementedConstraintBuilder<S, A, B, K, EA, EB, KA, KB, C, D, W, Sc>
Rewards each complemented group, explicitly marked as hard constraint.
Trait Implementations§
Auto Trait Implementations§
impl<S, A, B, K, EA, EB, KA, KB, C, D, Sc> Freeze for ComplementedConstraintStream<S, A, B, K, EA, EB, KA, KB, C, D, Sc>
impl<S, A, B, K, EA, EB, KA, KB, C, D, Sc> RefUnwindSafe for ComplementedConstraintStream<S, A, B, K, EA, EB, KA, KB, C, D, Sc>where
EA: RefUnwindSafe,
EB: RefUnwindSafe,
KA: RefUnwindSafe,
KB: RefUnwindSafe,
C: RefUnwindSafe,
D: RefUnwindSafe,
S: RefUnwindSafe,
A: RefUnwindSafe,
B: RefUnwindSafe,
K: RefUnwindSafe,
Sc: RefUnwindSafe,
impl<S, A, B, K, EA, EB, KA, KB, C, D, Sc> Send for ComplementedConstraintStream<S, A, B, K, EA, EB, KA, KB, C, D, Sc>
impl<S, A, B, K, EA, EB, KA, KB, C, D, Sc> Sync for ComplementedConstraintStream<S, A, B, K, EA, EB, KA, KB, C, D, Sc>
impl<S, A, B, K, EA, EB, KA, KB, C, D, Sc> Unpin for ComplementedConstraintStream<S, A, B, K, EA, EB, KA, KB, C, D, Sc>
impl<S, A, B, K, EA, EB, KA, KB, C, D, Sc> UnwindSafe for ComplementedConstraintStream<S, A, B, K, EA, EB, KA, KB, C, D, Sc>where
EA: UnwindSafe,
EB: UnwindSafe,
KA: UnwindSafe,
KB: UnwindSafe,
C: UnwindSafe,
D: UnwindSafe,
S: UnwindSafe,
A: UnwindSafe,
B: UnwindSafe,
K: UnwindSafe,
Sc: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more