1
1
package ai .timefold .solver .core .api .score .analysis ;
2
2
3
3
import static ai .timefold .solver .core .impl .score .director .InnerScoreDirector .getConstraintAnalysis ;
4
+ import static org .assertj .core .api .AssertionsForClassTypes .assertThat ;
5
+ import static org .assertj .core .api .AssertionsForClassTypes .assertThatThrownBy ;
4
6
import static org .assertj .core .api .SoftAssertions .assertSoftly ;
5
7
6
8
import java .util .Arrays ;
@@ -26,6 +28,131 @@ void empty() {
26
28
softly .assertThat (diff .score ()).isEqualTo (SimpleScore .of (0 ));
27
29
softly .assertThat (diff .constraintMap ()).isEmpty ();
28
30
});
31
+
32
+ var summary = scoreAnalysis .summarize ();
33
+ assertThat (summary )
34
+ .isEqualTo ("""
35
+ Explanation of score (0):
36
+ Constraint matches:
37
+ """ );
38
+ }
39
+
40
+ @ Test
41
+ void summarize () {
42
+ var constraintPackage = "constraintPackage" ;
43
+ var constraintName1 = "constraint1" ;
44
+ var constraintName2 = "constraint2" ;
45
+ var constraintName3 = "constraint3" ;
46
+ var constraintId1 = ConstraintRef .of (constraintPackage , constraintName1 );
47
+ var constraintId2 = ConstraintRef .of (constraintPackage , constraintName2 );
48
+ var constraintId3 = ConstraintRef .of (constraintPackage , constraintName3 );
49
+
50
+ var constraintMatchTotal = new DefaultConstraintMatchTotal <>(constraintId1 , SimpleScore .of (1 ));
51
+ addConstraintMatch (constraintMatchTotal , SimpleScore .of (2 ), "A" , "B" , "C" );
52
+ addConstraintMatch (constraintMatchTotal , SimpleScore .of (4 ), "A" , "B" );
53
+ addConstraintMatch (constraintMatchTotal , SimpleScore .of (6 ), "B" , "C" );
54
+ addConstraintMatch (constraintMatchTotal , SimpleScore .of (7 ), "C" );
55
+ addConstraintMatch (constraintMatchTotal , SimpleScore .of (8 ));
56
+ var constraintMatchTotal2 = new DefaultConstraintMatchTotal <>(constraintId2 , SimpleScore .of (3 ));
57
+ addConstraintMatch (constraintMatchTotal2 , SimpleScore .of (3 ), "B" , "C" , "D" );
58
+ addConstraintMatch (constraintMatchTotal2 , SimpleScore .of (6 ), "B" , "C" );
59
+ addConstraintMatch (constraintMatchTotal2 , SimpleScore .of (9 ), "C" , "D" );
60
+ addConstraintMatch (constraintMatchTotal2 , SimpleScore .of (10 ), "D" );
61
+ addConstraintMatch (constraintMatchTotal2 , SimpleScore .of (12 ));
62
+ var emptyConstraintMatchTotal1 = new DefaultConstraintMatchTotal <>(constraintId3 , SimpleScore .of (0 ));
63
+ var constraintAnalysisMap = Map .of (
64
+ constraintMatchTotal .getConstraintRef (), getConstraintAnalysis (constraintMatchTotal , true ),
65
+ constraintMatchTotal2 .getConstraintRef (), getConstraintAnalysis (constraintMatchTotal2 , true ),
66
+ emptyConstraintMatchTotal1 .getConstraintRef (), getConstraintAnalysis (emptyConstraintMatchTotal1 , true ));
67
+ var scoreAnalysis = new ScoreAnalysis <>(SimpleScore .of (67 ), constraintAnalysisMap );
68
+
69
+ // Single constraint analysis
70
+ var constraintSummary = constraintAnalysisMap .get (constraintMatchTotal .getConstraintRef ()).summarize ();
71
+ assertThat (constraintSummary )
72
+ .isEqualTo ("""
73
+ Explanation of score (27):
74
+ Constraint matches:
75
+ 27: constraint (constraint1) has 5 matches:
76
+ 2: justified with ([A, B, C])
77
+ 4: justified with ([A, B])
78
+ 6: justified with ([B, C])
79
+ ...
80
+ """ );
81
+
82
+ // Complete score analysis
83
+ var summary = scoreAnalysis .summarize ();
84
+ assertThat (scoreAnalysis .getConstraintAnalysis (constraintPackage , constraintName1 ).matchCount ()).isEqualTo (5 );
85
+ assertThat (summary )
86
+ .isEqualTo ("""
87
+ Explanation of score (67):
88
+ Constraint matches:
89
+ 0: constraint (constraint3) has no matches.
90
+ 27: constraint (constraint1) has 5 matches:
91
+ 2: justified with ([A, B, C])
92
+ 4: justified with ([A, B])
93
+ 6: justified with ([B, C])
94
+ ...
95
+ 40: constraint (constraint2) has 5 matches:
96
+ 3: justified with ([B, C, D])
97
+ 6: justified with ([B, C])
98
+ 9: justified with ([C, D])
99
+ ...
100
+ """ );
101
+ }
102
+
103
+ @ Test
104
+ void summarizeUninitializedSolution () {
105
+ var constraintPackage = "constraintPackage" ;
106
+ var constraintName1 = "constraint1" ;
107
+ var constraintName2 = "constraint2" ;
108
+ var constraintId1 = ConstraintRef .of (constraintPackage , constraintName1 );
109
+ var constraintId2 = ConstraintRef .of (constraintPackage , constraintName2 );
110
+
111
+ var constraintMatchTotal = new DefaultConstraintMatchTotal <>(constraintId1 , SimpleScore .of (0 ));
112
+ var constraintMatchTotal2 = new DefaultConstraintMatchTotal <>(constraintId2 , SimpleScore .of (0 ));
113
+ var constraintAnalysisMap = Map .of (
114
+ constraintMatchTotal .getConstraintRef (), getConstraintAnalysis (constraintMatchTotal , true ),
115
+ constraintMatchTotal2 .getConstraintRef (), getConstraintAnalysis (constraintMatchTotal2 , true ));
116
+ var scoreAnalysis = new ScoreAnalysis <>(SimpleScore .ofUninitialized (3 , 0 ), constraintAnalysisMap );
117
+
118
+ // Single constraint analysis
119
+ var constraintSummary = constraintAnalysisMap .get (constraintMatchTotal .getConstraintRef ()).summarize ();
120
+ assertThat (constraintSummary )
121
+ .isEqualTo ("""
122
+ Explanation of score (0):
123
+ Constraint matches:
124
+ 0: constraint (constraint1) has no matches.
125
+ """ );
126
+
127
+ // Complete score analysis
128
+ var summary = scoreAnalysis .summarize ();
129
+ assertThat (scoreAnalysis .getConstraintAnalysis (constraintPackage , constraintName1 ).matchCount ()).isZero ();
130
+ assertThat (summary )
131
+ .isEqualTo ("""
132
+ Explanation of score (3init/0):
133
+ Constraint matches:
134
+ 0: constraint (constraint1) has no matches.
135
+ 0: constraint (constraint2) has no matches.
136
+ """ );
137
+ }
138
+
139
+ @ Test
140
+ void failFastSummarize () {
141
+ var constraintPackage = "constraintPackage" ;
142
+ var constraintName1 = "constraint1" ;
143
+ var constraintId1 = ConstraintRef .of (constraintPackage , constraintName1 );
144
+
145
+ var constraintMatchTotal = new DefaultConstraintMatchTotal <>(constraintId1 , SimpleScore .of (1 ));
146
+ addConstraintMatch (constraintMatchTotal , SimpleScore .of (2 ), "A" , "B" , "C" );
147
+ var constraintAnalysisMap = Map .of (
148
+ constraintMatchTotal .getConstraintRef (), getConstraintAnalysis (constraintMatchTotal , false ));
149
+ var scoreAnalysis = new ScoreAnalysis <>(SimpleScore .of (3 ), constraintAnalysisMap );
150
+
151
+ assertThatThrownBy (scoreAnalysis ::summarize )
152
+ .hasMessageContaining ("The constraint matches must be non-null" );
153
+
154
+ assertThatThrownBy (() -> constraintAnalysisMap .values ().stream ().findFirst ().get ().matchCount ())
155
+ .hasMessageContaining ("The constraint matches must be non-null" );
29
156
}
30
157
31
158
@ Test
0 commit comments