Skip to main content

solverforge_scoring/stream/
mod.rs

1// Fluent constraint stream API for zero-erasure constraint programming.
2//
3// This module provides an ergonomic builder pattern for defining constraints
4// that compile to fully-typed, monomorphized constraint implementations.
5//
6// # Overview
7//
8// The stream API transforms verbose constraint definitions into concise,
9// fluent declarations while preserving full type information through the
10// entire evaluation pipeline.
11//
12// # Example
13//
14// ```
15// use solverforge_scoring::stream::ConstraintFactory;
16// use solverforge_scoring::api::constraint_set::{ConstraintSet, IncrementalConstraint};
17// use solverforge_core::score::SoftScore;
18//
19// #[derive(Clone)]
20// struct Schedule {
21//     shifts: Vec<Shift>,
22// }
23//
24// #[derive(Clone, Debug)]
25// struct Shift {
26//     employee_idx: Option<usize>,
27//     required_skill: String,
28// }
29//
30// // Define constraints using the fluent API
31// let unassigned = ConstraintFactory::<Schedule, SoftScore>::new()
32//     .for_each(|s: &Schedule| &s.shifts)
33//     .filter(|shift: &Shift| shift.employee_idx.is_none())
34//     .penalize(SoftScore::of(1))
35//     .named("Unassigned shift");
36//
37// // Use the constraint
38// let schedule = Schedule {
39//     shifts: vec![
40//         Shift { employee_idx: Some(0), required_skill: "A".into() },
41//         Shift { employee_idx: None, required_skill: "B".into() },
42//     ],
43// };
44//
45// assert_eq!(unassigned.evaluate(&schedule), SoftScore::of(-1));
46// ```
47//
48// # Architecture
49//
50// The stream builders produce existing constraint types at definition time:
51//
52// ```text
53// ConstraintFactory::new()
54//     .for_each(extractor)     -> UniConstraintStream<S, A, Sc>
55//     .filter(predicate)            -> UniConstraintStream (accumulates filters)
56//     .penalize(weight)             -> UniConstraintBuilder<S, A, Sc>
57//     .named(name)                  -> IncrementalUniConstraint<S, A, Sc>
58// ```
59//
60// The final `IncrementalUniConstraint` is fully monomorphized with no
61// virtual dispatch in the hot path.
62
63#[macro_use]
64mod arity_stream_macros;
65mod balance_stream;
66mod bi_stream;
67pub mod collector;
68mod complemented_stream;
69mod cross_bi_stream;
70mod factory;
71pub mod filter;
72mod flattened_bi_stream;
73mod grouped_stream;
74mod if_exists_stream;
75pub mod join_target;
76pub mod joiner;
77pub mod key_extract;
78mod penta_stream;
79mod quad_stream;
80mod tri_stream;
81mod uni_stream;
82
83pub use balance_stream::{BalanceConstraintBuilder, BalanceConstraintStream};
84pub use bi_stream::{BiConstraintBuilder, BiConstraintStream};
85pub use complemented_stream::{ComplementedConstraintBuilder, ComplementedConstraintStream};
86pub use cross_bi_stream::{CrossBiConstraintBuilder, CrossBiConstraintStream};
87pub use factory::ConstraintFactory;
88pub use flattened_bi_stream::{FlattenedBiConstraintBuilder, FlattenedBiConstraintStream};
89pub use grouped_stream::{GroupedConstraintBuilder, GroupedConstraintStream};
90pub use if_exists_stream::{IfExistsBuilder, IfExistsStream};
91pub use join_target::JoinTarget;
92pub use key_extract::{EntityKeyAdapter, KeyExtract};
93pub use penta_stream::{PentaConstraintBuilder, PentaConstraintStream};
94pub use quad_stream::{QuadConstraintBuilder, QuadConstraintStream};
95pub use tri_stream::{TriConstraintBuilder, TriConstraintStream};
96pub use uni_stream::{UniConstraintBuilder, UniConstraintStream};