11package ai .timefold .solver .core .impl .score .stream .bavet ;
22
3- import java .util .Collections ;
43import java .util .IdentityHashMap ;
5- import java .util .List ;
64import java .util .Map ;
75
86import ai .timefold .solver .core .api .score .Score ;
97import ai .timefold .solver .core .api .score .constraint .ConstraintMatchTotal ;
108import ai .timefold .solver .core .api .score .constraint .Indictment ;
119import ai .timefold .solver .core .impl .score .director .stream .BavetConstraintStreamScoreDirectorFactory ;
1210import ai .timefold .solver .core .impl .score .stream .bavet .common .PropagationQueue ;
13- import ai .timefold .solver .core .impl .score .stream .bavet .common .Propagator ;
1411import ai .timefold .solver .core .impl .score .stream .bavet .uni .AbstractForEachUniNode ;
1512import ai .timefold .solver .core .impl .score .stream .common .inliner .AbstractScoreInliner ;
1613
2421public final class BavetConstraintSession <Score_ extends Score <Score_ >> {
2522
2623 private final AbstractScoreInliner <Score_ > scoreInliner ;
27- private final Map <Class <?>, List <AbstractForEachUniNode <Object >>> declaredClassToNodeMap ;
28- private final Propagator [][] layeredNodes ; // First level is the layer, second determines iteration order.
24+ private final NodeNetwork nodeNetwork ;
2925 private final Map <Class <?>, AbstractForEachUniNode <Object >[]> effectiveClassToNodeArrayMap ;
3026
3127 BavetConstraintSession (AbstractScoreInliner <Score_ > scoreInliner ) {
32- this (scoreInliner , Collections . emptyMap (), new Propagator [ 0 ][ 0 ] );
28+ this (scoreInliner , NodeNetwork . EMPTY );
3329 }
3430
35- BavetConstraintSession (AbstractScoreInliner <Score_ > scoreInliner ,
36- Map <Class <?>, List <AbstractForEachUniNode <Object >>> declaredClassToNodeMap ,
37- Propagator [][] layeredNodes ) {
31+ BavetConstraintSession (AbstractScoreInliner <Score_ > scoreInliner , NodeNetwork nodeNetwork ) {
3832 this .scoreInliner = scoreInliner ;
39- this .declaredClassToNodeMap = declaredClassToNodeMap ;
40- this .layeredNodes = layeredNodes ;
41- this .effectiveClassToNodeArrayMap = new IdentityHashMap <>(declaredClassToNodeMap .size ());
33+ this .nodeNetwork = nodeNetwork ;
34+ this .effectiveClassToNodeArrayMap = new IdentityHashMap <>(nodeNetwork .forEachNodeCount ());
4235 }
4336
4437 public void insert (Object fact ) {
@@ -52,12 +45,7 @@ private AbstractForEachUniNode<Object>[] findNodes(Class<?> factClass) {
5245 // Map.computeIfAbsent() would have created lambdas on the hot path, this will not.
5346 var nodeArray = effectiveClassToNodeArrayMap .get (factClass );
5447 if (nodeArray == null ) {
55- nodeArray = declaredClassToNodeMap .entrySet ()
56- .stream ()
57- .filter (entry -> entry .getKey ().isAssignableFrom (factClass ))
58- .map (Map .Entry ::getValue )
59- .flatMap (List ::stream )
60- .toArray (AbstractForEachUniNode []::new );
48+ nodeArray = nodeNetwork .getApplicableForEachNodes (factClass );
6149 effectiveClassToNodeArrayMap .put (factClass , nodeArray );
6250 }
6351 return nodeArray ;
@@ -78,31 +66,10 @@ public void retract(Object fact) {
7866 }
7967
8068 public Score_ calculateScore (int initScore ) {
81- var layerCount = layeredNodes .length ;
82- for (var layerIndex = 0 ; layerIndex < layerCount ; layerIndex ++) {
83- calculateScoreInLayer (layerIndex );
84- }
69+ nodeNetwork .propagate ();
8570 return scoreInliner .extractScore (initScore );
8671 }
8772
88- private void calculateScoreInLayer (int layerIndex ) {
89- var nodesInLayer = layeredNodes [layerIndex ];
90- var nodeCount = nodesInLayer .length ;
91- if (nodeCount == 1 ) {
92- nodesInLayer [0 ].propagateEverything ();
93- } else {
94- for (var node : nodesInLayer ) {
95- node .propagateRetracts ();
96- }
97- for (var node : nodesInLayer ) {
98- node .propagateUpdates ();
99- }
100- for (var node : nodesInLayer ) {
101- node .propagateInserts ();
102- }
103- }
104- }
105-
10673 public AbstractScoreInliner <Score_ > getScoreInliner () {
10774 return scoreInliner ;
10875 }
0 commit comments