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-typed, 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;
68pub mod collection_extract;
69pub mod collector;
70mod complemented_stream;
71mod cross_bi_stream;
72mod factory;
73pub mod filter;
74mod flattened_bi_stream;
75mod grouped_stream;
76mod if_exists_stream;
77pub mod join_target;
78pub mod joiner;
79pub mod key_extract;
80mod penta_stream;
81mod quad_stream;
82mod tri_stream;
83mod uni_stream;
84
85pub use balance_stream::{BalanceConstraintBuilder, BalanceConstraintStream};
86pub use bi_stream::{BiConstraintBuilder, BiConstraintStream};
87pub use collection_extract::{CollectionExtract, VecExtract};
88pub use complemented_stream::{ComplementedConstraintBuilder, ComplementedConstraintStream};
89pub use cross_bi_stream::{CrossBiConstraintBuilder, CrossBiConstraintStream};
90pub use factory::ConstraintFactory;
91pub use flattened_bi_stream::{FlattenedBiConstraintBuilder, FlattenedBiConstraintStream};
92pub use grouped_stream::{GroupedConstraintBuilder, GroupedConstraintStream};
93pub use if_exists_stream::{IfExistsBuilder, IfExistsStream};
94pub use join_target::JoinTarget;
95pub use key_extract::{EntityKeyAdapter, KeyExtract};
96pub use penta_stream::{PentaConstraintBuilder, PentaConstraintStream};
97pub use quad_stream::{QuadConstraintBuilder, QuadConstraintStream};
98pub use tri_stream::{TriConstraintBuilder, TriConstraintStream};
99pub use uni_stream::{UniConstraintBuilder, UniConstraintStream};