2222import ai .timefold .solver .core .api .score .stream .Constraint ;
2323import ai .timefold .solver .core .api .score .stream .ConstraintFactory ;
2424import ai .timefold .solver .core .api .score .stream .ConstraintProvider ;
25- import ai .timefold .solver .core .api .score .stream .PrecomputeFactory ;
26- import ai .timefold .solver .core .api .score .stream .bi .BiConstraintStream ;
27- import ai .timefold .solver .core .api .score .stream .tri .TriConstraintStream ;
2825
2926public class ExaminationConstraintProvider implements ConstraintProvider {
3027
@@ -51,15 +48,12 @@ public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
5148 };
5249 }
5350
54- private static BiConstraintStream <TopicConflict , Exam > conflictingExamLeft (PrecomputeFactory factory ) {
55- return factory .forEachUnfiltered (TopicConflict .class )
56- .join (Exam .class ,
57- equal (TopicConflict ::getLeftTopic , Exam ::getTopic ));
58- }
59-
6051 protected Constraint conflictingExamsInSamePeriod (ConstraintFactory constraintFactory ) {
61- return constraintFactory .precompute (ExaminationConstraintProvider ::conflictingExamLeft )
62- .filter ((topicConflict , leftExam ) -> leftExam .getPeriod () != null )
52+ return constraintFactory .forEach (TopicConflict .class )
53+ .join (Exam .class ,
54+ equal (TopicConflict ::getLeftTopic ,
55+ Exam ::getTopic ),
56+ filtering ((topicConflict , leftExam ) -> leftExam .getPeriod () != null ))
6357 .ifExists (Exam .class ,
6458 equal ((topicConflict , leftExam ) -> topicConflict .getRightTopic (),
6559 Exam ::getTopic ),
@@ -89,8 +83,13 @@ protected Constraint roomCapacityTooSmall(ConstraintFactory constraintFactory) {
8983 }
9084
9185 protected Constraint periodPenaltyExamCoincidence (ConstraintFactory constraintFactory ) {
92- return constraintFactory .precompute (ExaminationConstraintProvider ::periodPenaltyCoincidenceExamLeft )
93- .filter ((periodPenalty , leftExam ) -> leftExam .getPeriod () != null )
86+ return constraintFactory .forEach (PeriodPenalty .class )
87+ .filter (periodPenalty -> periodPenalty
88+ .getPeriodPenaltyType () == PeriodPenaltyType .EXAM_COINCIDENCE )
89+ .join (Exam .class ,
90+ equal (PeriodPenalty ::getLeftTopic ,
91+ Exam ::getTopic ),
92+ filtering ((periodPenalty , leftExam ) -> leftExam .getPeriod () != null ))
9493 .join (Exam .class ,
9594 equal ((periodPenalty , leftExam ) -> periodPenalty .getRightTopic (),
9695 Exam ::getTopic ),
@@ -101,16 +100,14 @@ protected Constraint periodPenaltyExamCoincidence(ConstraintFactory constraintFa
101100 .asConstraint ("periodPenaltyExamCoincidence" );
102101 }
103102
104- private static BiConstraintStream <PeriodPenalty , Exam > periodPenaltyCoincidenceExamLeft (PrecomputeFactory factory ) {
105- return factory .forEachUnfiltered (PeriodPenalty .class )
106- .filter (periodPenalty -> periodPenalty .getPeriodPenaltyType () == PeriodPenaltyType .EXAM_COINCIDENCE )
107- .join (Exam .class ,
108- equal (PeriodPenalty ::getLeftTopic , Exam ::getTopic ));
109- }
110-
111103 protected Constraint periodPenaltyExclusion (ConstraintFactory constraintFactory ) {
112- return constraintFactory .precompute (ExaminationConstraintProvider ::periodPenaltyExclusionExamLeft )
113- .filter ((periodPenalty , leftExam ) -> leftExam .getPeriod () != null )
104+ return constraintFactory .forEach (PeriodPenalty .class )
105+ .filter (periodPenalty -> periodPenalty
106+ .getPeriodPenaltyType () == PeriodPenaltyType .EXCLUSION )
107+ .join (Exam .class ,
108+ equal (PeriodPenalty ::getLeftTopic ,
109+ Exam ::getTopic ),
110+ filtering ((periodPenalty , leftExam ) -> leftExam .getPeriod () != null ))
114111 .join (Exam .class ,
115112 equal ((periodPenalty , leftExam ) -> periodPenalty .getRightTopic (),
116113 Exam ::getTopic ),
@@ -121,16 +118,13 @@ protected Constraint periodPenaltyExclusion(ConstraintFactory constraintFactory)
121118 .asConstraint ("periodPenaltyExclusion" );
122119 }
123120
124- private static BiConstraintStream <PeriodPenalty , Exam > periodPenaltyExclusionExamLeft (PrecomputeFactory factory ) {
125- return factory .forEachUnfiltered (PeriodPenalty .class )
126- .filter (periodPenalty -> periodPenalty .getPeriodPenaltyType () == PeriodPenaltyType .EXCLUSION )
127- .join (Exam .class ,
128- equal (PeriodPenalty ::getLeftTopic , Exam ::getTopic ));
129- }
130-
131121 protected Constraint periodPenaltyAfter (ConstraintFactory constraintFactory ) {
132- return constraintFactory .precompute (ExaminationConstraintProvider ::periodPenaltyAfterExamLeft )
133- .filter ((periodPenalty , leftExam ) -> leftExam .getPeriod () != null )
122+ return constraintFactory .forEach (PeriodPenalty .class )
123+ .filter (periodPenalty -> periodPenalty .getPeriodPenaltyType () == PeriodPenaltyType .AFTER )
124+ .join (Exam .class ,
125+ equal (PeriodPenalty ::getLeftTopic ,
126+ Exam ::getTopic ),
127+ filtering ((periodPenalty , leftExam ) -> leftExam .getPeriod () != null ))
134128 .join (Exam .class ,
135129 equal ((periodPenalty , leftExam ) -> periodPenalty .getRightTopic (),
136130 Exam ::getTopic ),
@@ -141,16 +135,12 @@ protected Constraint periodPenaltyAfter(ConstraintFactory constraintFactory) {
141135 .asConstraint ("periodPenaltyAfter" );
142136 }
143137
144- private static BiConstraintStream <PeriodPenalty , Exam > periodPenaltyAfterExamLeft (PrecomputeFactory factory ) {
145- return factory .forEachUnfiltered (PeriodPenalty .class )
146- .filter (periodPenalty -> periodPenalty .getPeriodPenaltyType () == PeriodPenaltyType .AFTER )
147- .join (Exam .class ,
148- equal (PeriodPenalty ::getLeftTopic , Exam ::getTopic ));
149- }
150-
151138 protected Constraint roomPenaltyExclusive (ConstraintFactory constraintFactory ) {
152- return constraintFactory .precompute (ExaminationConstraintProvider ::roomPenaltyExclusiveExamLeft )
153- .filter ((roomPenalty , leftExam ) -> leftExam .getPeriod () != null && leftExam .getRoom () != null )
139+ return constraintFactory .forEach (RoomPenalty .class )
140+ .filter (roomPenalty -> roomPenalty .getRoomPenaltyType () == RoomPenaltyType .ROOM_EXCLUSIVE )
141+ .join (Exam .class ,
142+ equal (RoomPenalty ::getTopic , Exam ::getTopic ),
143+ filtering ((roomPenalty , leftExam ) -> leftExam .getPeriod () != null && leftExam .getRoom () != null ))
154144 .join (Exam .class ,
155145 equal ((roomPenalty , leftExam ) -> leftExam .getRoom (),
156146 Exam ::getRoom ),
@@ -162,16 +152,12 @@ protected Constraint roomPenaltyExclusive(ConstraintFactory constraintFactory) {
162152 .asConstraint ("roomPenaltyExclusive" );
163153 }
164154
165- private static BiConstraintStream <RoomPenalty , Exam > roomPenaltyExclusiveExamLeft (PrecomputeFactory factory ) {
166- return factory .forEachUnfiltered (RoomPenalty .class )
167- .filter (roomPenalty -> roomPenalty .getRoomPenaltyType () == RoomPenaltyType .ROOM_EXCLUSIVE )
168- .join (Exam .class ,
169- equal (RoomPenalty ::getTopic , Exam ::getTopic ));
170- }
171-
172155 protected Constraint twoExamsInARow (ConstraintFactory constraintFactory ) {
173- return constraintFactory .precompute (ExaminationConstraintProvider ::topicConflictExamLeft )
174- .filter ((topicConflict , leftExam ) -> leftExam .getPeriod () != null )
156+ return constraintFactory .forEach (TopicConflict .class )
157+ .join (Exam .class ,
158+ equal (TopicConflict ::getLeftTopic ,
159+ Exam ::getTopic ),
160+ filtering ((topicConflict , leftExam ) -> leftExam .getPeriod () != null ))
175161 .join (Exam .class ,
176162 equal ((topicConflict , leftExam ) -> topicConflict .getRightTopic (),
177163 Exam ::getTopic ),
@@ -183,15 +169,12 @@ protected Constraint twoExamsInARow(ConstraintFactory constraintFactory) {
183169 .asConstraint ("twoExamsInARow" );
184170 }
185171
186- private static BiConstraintStream <TopicConflict , Exam > topicConflictExamLeft (PrecomputeFactory factory ) {
187- return factory .forEachUnfiltered (TopicConflict .class )
188- .join (Exam .class ,
189- equal (TopicConflict ::getLeftTopic , Exam ::getTopic ));
190- }
191-
192172 protected Constraint twoExamsInADay (ConstraintFactory constraintFactory ) {
193- return constraintFactory .precompute (ExaminationConstraintProvider ::topicConflictExamLeft )
194- .filter ((topicConflict , leftExam ) -> leftExam .getPeriod () != null )
173+ return constraintFactory .forEach (TopicConflict .class )
174+ .join (Exam .class ,
175+ equal (TopicConflict ::getLeftTopic ,
176+ Exam ::getTopic ),
177+ filtering ((topicConflict , leftExam ) -> leftExam .getPeriod () != null ))
195178 .join (Exam .class ,
196179 equal ((topicConflict , leftExam ) -> topicConflict .getRightTopic (),
197180 Exam ::getTopic ),
@@ -205,8 +188,12 @@ protected Constraint twoExamsInADay(ConstraintFactory constraintFactory) {
205188 }
206189
207190 protected Constraint periodSpread (ConstraintFactory constraintFactory ) {
208- return constraintFactory .precompute (ExaminationConstraintProvider ::configuredTopicConflictExamLeft )
209- .filter ((config , topicConflict , leftExam ) -> leftExam .getPeriod () != null )
191+ return constraintFactory .forEach (ExaminationConstraintProperties .class )
192+ .join (TopicConflict .class )
193+ .join (Exam .class ,
194+ equal ((config , topicConflict ) -> topicConflict .getLeftTopic (),
195+ Exam ::getTopic ),
196+ filtering ((config , topicConflict , leftExam ) -> leftExam .getPeriod () != null ))
210197 .join (Exam .class ,
211198 equal ((config , topicConflict , leftExam ) -> topicConflict .getRightTopic (),
212199 Exam ::getTopic ),
@@ -219,14 +206,6 @@ protected Constraint periodSpread(ConstraintFactory constraintFactory) {
219206 .asConstraint ("periodSpread" );
220207 }
221208
222- private static TriConstraintStream <ExaminationConstraintProperties , TopicConflict , Exam >
223- configuredTopicConflictExamLeft (PrecomputeFactory factory ) {
224- return factory .forEachUnfiltered (ExaminationConstraintProperties .class )
225- .join (TopicConflict .class )
226- .join (Exam .class ,
227- equal ((config , topicConflict ) -> topicConflict .getLeftTopic (), Exam ::getTopic ));
228- }
229-
230209 protected Constraint mixedDurations (ConstraintFactory constraintFactory ) {
231210 // 4 mixed durations of 100, 150, 200 and 200 should only result in 2 penalties (for 100&150 and 100&200).
232211 return constraintFactory .forEach (Exam .class )
@@ -283,5 +262,4 @@ private int getPeriodIndexDifferenceBetweenExams(Exam leftExam,
283262 Exam rightExam ) {
284263 return Math .abs (leftExam .getPeriodIndex () - rightExam .getPeriodIndex ());
285264 }
286-
287265}
0 commit comments