11use solverforge:: prelude:: * ;
2+ use solverforge:: prelude:: ConstraintSet as CSet ;
23use solverforge:: IncrementalConstraint ;
34
45struct Plan {
@@ -16,6 +17,13 @@ fn fixed_one() -> impl IncrementalConstraint<Plan, SoftScore> {
1617 . named ( "fixed one" )
1718}
1819
20+ fn fixed_named ( name : String ) -> impl ConstraintSet < Plan , SoftScore > {
21+ ConstraintFactory :: < Plan , SoftScore > :: new ( )
22+ . for_each ( shifts as fn ( & Plan ) -> & [ usize ] )
23+ . penalize ( SoftScore :: ONE )
24+ . named ( name. as_str ( ) )
25+ }
26+
1927fn fixed_constraints ( ) -> impl ConstraintSet < Plan , SoftScore > {
2028 let fixed_two = ConstraintFactory :: < Plan , SoftScore > :: new ( )
2129 . for_each ( shifts as fn ( & Plan ) -> & [ usize ] )
@@ -29,6 +37,82 @@ fn fixed_constraints() -> impl ConstraintSet<Plan, SoftScore> {
2937 ( fixed_two, fixed_three)
3038}
3139
40+ #[ solverforge_constraints]
41+ fn moved_name_constraints ( ) -> impl ConstraintSet < Plan , SoftScore > {
42+ let by_employee = ConstraintFactory :: < Plan , SoftScore > :: new ( )
43+ . for_each ( shifts as fn ( & Plan ) -> & [ usize ] )
44+ . group_by ( |employee_id : & usize | * employee_id, count ( ) ) ;
45+ let name = String :: from ( "moved fixed" ) ;
46+
47+ (
48+ by_employee
49+ . penalize ( |_employee_id : & usize , count : & usize | SoftScore :: of ( * count as i64 ) )
50+ . named ( name. as_str ( ) ) ,
51+ fixed_named ( name) ,
52+ by_employee
53+ . penalize ( |_employee_id : & usize , count : & usize | {
54+ SoftScore :: of ( ( * count * * count) as i64 )
55+ } )
56+ . named ( "after move" ) ,
57+ )
58+ }
59+
60+ #[ solverforge_constraints]
61+ fn empty_tuple_constraints ( ) -> impl ConstraintSet < Plan , SoftScore > {
62+ let by_employee = ConstraintFactory :: < Plan , SoftScore > :: new ( )
63+ . for_each ( shifts as fn ( & Plan ) -> & [ usize ] )
64+ . group_by ( |employee_id : & usize | * employee_id, count ( ) ) ;
65+
66+ (
67+ by_employee
68+ . penalize ( |_employee_id : & usize , count : & usize | SoftScore :: of ( * count as i64 ) )
69+ . named ( "empty linear" ) ,
70+ ( ) ,
71+ by_employee
72+ . penalize ( |_employee_id : & usize , count : & usize | {
73+ SoftScore :: of ( ( * count * * count) as i64 )
74+ } )
75+ . named ( "empty squared" ) ,
76+ )
77+ }
78+
79+ #[ solverforge_constraints]
80+ fn alias_terminal_constraints ( ) -> impl CSet < Plan , SoftScore > {
81+ let by_employee = ConstraintFactory :: < Plan , SoftScore > :: new ( )
82+ . for_each ( shifts as fn ( & Plan ) -> & [ usize ] )
83+ . group_by ( |employee_id : & usize | * employee_id, count ( ) ) ;
84+
85+ (
86+ by_employee
87+ . penalize ( |_employee_id : & usize , count : & usize | SoftScore :: of ( * count as i64 ) )
88+ . named ( "alias linear" ) ,
89+ by_employee
90+ . penalize ( |_employee_id : & usize , count : & usize | {
91+ SoftScore :: of ( ( * count * * count) as i64 )
92+ } )
93+ . named ( "alias squared" ) ,
94+ )
95+ }
96+
97+ #[ solverforge_constraints]
98+ fn alias_empty_tuple_constraints ( ) -> impl CSet < Plan , SoftScore > {
99+ let by_employee = ConstraintFactory :: < Plan , SoftScore > :: new ( )
100+ . for_each ( shifts as fn ( & Plan ) -> & [ usize ] )
101+ . group_by ( |employee_id : & usize | * employee_id, count ( ) ) ;
102+
103+ (
104+ by_employee
105+ . penalize ( |_employee_id : & usize , count : & usize | SoftScore :: of ( * count as i64 ) )
106+ . named ( "alias empty linear" ) ,
107+ ( ) ,
108+ by_employee
109+ . penalize ( |_employee_id : & usize , count : & usize | {
110+ SoftScore :: of ( ( * count * * count) as i64 )
111+ } )
112+ . named ( "alias empty squared" ) ,
113+ )
114+ }
115+
32116#[ solverforge_constraints]
33117fn call_single_constraints ( ) -> impl ConstraintSet < Plan , SoftScore > {
34118 let by_employee = ConstraintFactory :: < Plan , SoftScore > :: new ( )
@@ -101,4 +185,29 @@ fn main() {
101185 assert_eq ! ( bound_metadata[ 0 ] . name( ) , "bound linear" ) ;
102186 assert_eq ! ( bound_metadata[ 1 ] . name( ) , "fixed duplicate" ) ;
103187 assert_eq ! ( bound_metadata[ 2 ] . name( ) , "bound squared" ) ;
188+
189+ let moved_constraints = moved_name_constraints ( ) ;
190+ let moved_results = moved_constraints. evaluate_each ( & plan) ;
191+ assert_eq ! ( moved_results. len( ) , 3 ) ;
192+ assert_eq ! ( moved_results[ 0 ] . name, "moved fixed" ) ;
193+ assert_eq ! ( moved_results[ 1 ] . name, "moved fixed" ) ;
194+ assert_eq ! ( moved_results[ 2 ] . name, "after move" ) ;
195+
196+ let empty_constraints = empty_tuple_constraints ( ) ;
197+ let empty_results = empty_constraints. evaluate_each ( & plan) ;
198+ assert_eq ! ( empty_results. len( ) , 2 ) ;
199+ assert_eq ! ( empty_results[ 0 ] . name, "empty linear" ) ;
200+ assert_eq ! ( empty_results[ 1 ] . name, "empty squared" ) ;
201+
202+ let alias_constraints = alias_terminal_constraints ( ) ;
203+ let alias_results = alias_constraints. evaluate_each ( & plan) ;
204+ assert_eq ! ( alias_results. len( ) , 2 ) ;
205+ assert_eq ! ( alias_results[ 0 ] . name, "alias linear" ) ;
206+ assert_eq ! ( alias_results[ 1 ] . name, "alias squared" ) ;
207+
208+ let alias_empty_constraints = alias_empty_tuple_constraints ( ) ;
209+ let alias_empty_results = alias_empty_constraints. evaluate_each ( & plan) ;
210+ assert_eq ! ( alias_empty_results. len( ) , 2 ) ;
211+ assert_eq ! ( alias_empty_results[ 0 ] . name, "alias empty linear" ) ;
212+ assert_eq ! ( alias_empty_results[ 1 ] . name, "alias empty squared" ) ;
104213}
0 commit comments