Skip to main content

solverforge_scoring/stream/
mod.rs

1/* Fluent constraint stream API for zero-erasure constraint programming.
2
3This module provides an ergonomic builder pattern for defining constraints
4that compile to fully monomorphized, monomorphized constraint implementations.
5
6# Overview
7
8The stream API transforms verbose constraint definitions into concise,
9fluent declarations while preserving full type information through the
10entire evaluation pipeline.
11
12# Example
13
14```
15use solverforge_scoring::stream::ConstraintFactory;
16use solverforge_scoring::api::constraint_set::{ConstraintSet, IncrementalConstraint};
17use solverforge_core::score::SoftScore;
18
19#[derive(Clone)]
20struct Schedule {
21shifts: Vec<Shift>,
22}
23
24#[derive(Clone, Debug)]
25struct Shift {
26employee_idx: Option<usize>,
27required_skill: String,
28}
29
30// Define constraints using the fluent API
31let 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
38let schedule = Schedule {
39shifts: vec![
40Shift { employee_idx: Some(0), required_skill: "A".into() },
41Shift { employee_idx: None, required_skill: "B".into() },
42],
43};
44
45assert_eq!(unassigned.evaluate(&schedule), SoftScore::of(-1));
46```
47
48# Architecture
49
50The stream builders produce existing constraint types at definition time:
51
52```text
53ConstraintFactory::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
60The final `IncrementalUniConstraint` is fully monomorphized with no
61virtual dispatch in the hot path.
62*/
63
64#[macro_use]
65mod arity_stream_macros;
66mod balance_stream;
67mod bi_stream;
68mod chain_stream;
69pub mod collection_extract;
70pub mod collector;
71mod complemented_stream;
72mod cross_bi_stream;
73mod cross_penta_stream;
74pub(crate) mod cross_quad_stream;
75mod cross_tri_stream;
76mod existence_stream;
77mod existence_target;
78mod factory;
79pub mod filter;
80mod flattened_bi_stream;
81mod grouped_stream;
82pub mod join_target;
83pub mod joiner;
84pub mod key_extract;
85mod penta_stream;
86mod projected_stream;
87mod quad_stream;
88pub mod relational;
89mod tri_stream;
90mod unassigned;
91mod uni_stream;
92mod weighting_support;
93
94#[cfg(test)]
95mod tests;
96
97pub mod cross {
98    pub use super::cross_bi_stream::{
99        Bi, Builder, ComplementedGrouped, ComplementedGroupedBuilder, Grouped, GroupedBuilder,
100    };
101    pub use super::cross_penta_stream::{Penta, PentaBuilder};
102    pub use super::cross_quad_stream::{Quad, QuadBuilder};
103    pub use super::cross_tri_stream::Tri;
104}
105
106pub mod projected {
107    pub use super::projected_stream::{
108        Bi, BiBuilder, Builder, ComplementedGrouped, ComplementedGroupedBuilder, DirectedBi,
109        DirectedBiBuilder, Grouped, GroupedBuilder, JoinedSource, ProjectedJoinTarget, Projection,
110        ProjectionSink, RowCoordinate, RowOwner, Source, Stream,
111    };
112}
113
114pub use balance_stream::{BalanceConstraintBuilder, BalanceConstraintStream};
115pub use bi_stream::{BiConstraintBuilder, BiConstraintStream};
116pub use collection_extract::{
117    source, ChangeSource, CollectionExtract, FlattenExtract, SourceExtract, VecExtract,
118};
119pub use complemented_stream::{ComplementedConstraintBuilder, ComplementedConstraintStream};
120pub use existence_stream::{ExistenceMode, ExistsConstraintBuilder, ExistsConstraintStream};
121pub use existence_target::{ExistenceTarget, FlattenedCollectionTarget};
122pub use factory::ConstraintFactory;
123pub use flattened_bi_stream::{FlattenedBiConstraintBuilder, FlattenedBiConstraintStream};
124pub use grouped_stream::{GroupedConstraintBuilder, GroupedConstraintStream};
125pub use join_target::JoinTarget;
126pub use key_extract::{EntityKeyAdapter, KeyExtract};
127pub use penta_stream::{PentaConstraintBuilder, PentaConstraintStream};
128pub use projected_stream::{Projection, ProjectionSink};
129pub use quad_stream::{QuadConstraintBuilder, QuadConstraintStream};
130pub use tri_stream::{TriConstraintBuilder, TriConstraintStream};
131#[doc(hidden)]
132pub use unassigned::UnassignedEntity;
133pub use uni_stream::{UniConstraintBuilder, UniConstraintStream};
134#[doc(hidden)]
135pub use weighting_support::ConstraintWeight;
136pub use weighting_support::{fixed_weight, hard_weight, FixedWeight, HardWeight};