@@ -454,6 +454,20 @@ def concat(self, other):
454
454
else :
455
455
raise RuntimeError (f'Unhandled constraint stream type { type (other )} .' )
456
456
457
+ def complement (self , cls : type [A ]) -> 'UniConstraintStream[A]' :
458
+ """
459
+ Adds to the stream all instances of a given class which are not yet present in it.
460
+ These instances must be present in the solution,
461
+ which means the class needs to be either a planning entity or a problem fact.
462
+
463
+ Parameters
464
+ ----------
465
+ cls : Type[A]
466
+ the type of the instances to add to the stream.
467
+ """
468
+ result = self .delegate .complement (get_class (cls ))
469
+ return TriConstraintCollector (result , self .package , self .a_type )
470
+
457
471
def penalize (self , constraint_weight : ScoreType , match_weigher : Callable [[A ], int ] = None ) -> \
458
472
'UniConstraintBuilder[A, ScoreType]' :
459
473
"""
@@ -1000,6 +1014,40 @@ def concat(self, other):
1000
1014
else :
1001
1015
raise RuntimeError (f'Unhandled constraint stream type { type (other )} .' )
1002
1016
1017
+ @overload
1018
+ def complement (self , cls : type [A ]) -> 'BiConstraintStream[A, B]' :
1019
+ ...
1020
+
1021
+ @overload
1022
+ def complement (self , cls : type [A ], padding : Callable [[A ], B ]) -> 'BiConstraintStream[A, B]' :
1023
+ ...
1024
+
1025
+ def complement (self , cls : type [A ], padding = None ):
1026
+ """
1027
+ Adds to the stream all instances of a given class which are not yet present in it.
1028
+ These instances must be present in the solution,
1029
+ which means the class needs to be either a planning entity or a problem fact.
1030
+
1031
+ The instances will be read from the first element of the input tuple.
1032
+ When an output tuple needs to be created for the newly inserted instances,
1033
+ the first element will be the new instance.
1034
+ The rest of the tuple will be padded with the result of the padding function.
1035
+
1036
+ Parameters
1037
+ ----------
1038
+ cls : Type[A]
1039
+ the type of the instances to add to the stream.
1040
+
1041
+ padding : Callable[[A], B]
1042
+ a function that computes the padding value for the second fact in the new tuple.
1043
+ """
1044
+ if None == padding :
1045
+ result = self .delegate .complement (get_class (cls ))
1046
+ return TriConstraintCollector (result , self .package , self .a_type , self .b_type )
1047
+ java_padding = function_cast (padding , self .a_type )
1048
+ result = self .delegate .complement (get_class (cls ), java_padding )
1049
+ return TriConstraintCollector (result , self .package , self .a_type , self .b_type )
1050
+
1003
1051
def penalize (self , constraint_weight : ScoreType , match_weigher : Callable [[A , B ], int ] = None ) -> \
1004
1052
'BiConstraintBuilder[A, B, ScoreType]' :
1005
1053
"""
@@ -1544,6 +1592,51 @@ def concat(self, other):
1544
1592
else :
1545
1593
raise RuntimeError (f'Unhandled constraint stream type { type (other )} .' )
1546
1594
1595
+ @overload
1596
+ def complement (self , cls : type [A ]) -> 'TriConstraintStream[A, B, C]' :
1597
+ ...
1598
+
1599
+ @overload
1600
+ def complement (self , cls : type [A ], padding_b : Callable [[A ], B ], padding_c : Callable [[A ], C ]) \
1601
+ -> 'TriConstraintStream[A, B, C]' :
1602
+ ...
1603
+
1604
+ def complement (self , cls : type [A ], padding_b = None , padding_c = None ):
1605
+ """
1606
+ Adds to the stream all instances of a given class which are not yet present in it.
1607
+ These instances must be present in the solution,
1608
+ which means the class needs to be either a planning entity or a problem fact.
1609
+
1610
+ The instances will be read from the first element of the input tuple.
1611
+ When an output tuple needs to be created for the newly inserted instances,
1612
+ the first element will be the new instance.
1613
+ The rest of the tuple will be padded with the result of the padding function,
1614
+ applied on the new instance.
1615
+
1616
+ Padding functions are optional, but if one is provided, then both must-be provided.
1617
+
1618
+ Parameters
1619
+ ----------
1620
+ cls : Type[A]
1621
+ the type of the instances to add to the stream.
1622
+
1623
+ padding_b : Callable[[A], B]
1624
+ a function that computes the padding value for the second fact in the new tuple.
1625
+
1626
+ padding_c : Callable[[A], C]
1627
+ a function that computes the padding value for the third fact in the new tuple.
1628
+ """
1629
+ if None == padding_b == padding_c :
1630
+ result = self .delegate .complement (get_class (cls ))
1631
+ return TriConstraintCollector (result , self .package , self .a_type , self .b_type , self .c_type )
1632
+ specified_count = sum (x is not None for x in [padding_b , padding_c ])
1633
+ if specified_count != 0 :
1634
+ raise ValueError (f'If a padding function is provided, both are expected, got { specified_count } instead.' )
1635
+ java_padding_b = function_cast (padding_b , self .a_type )
1636
+ java_padding_c = function_cast (padding_c , self .a_type )
1637
+ result = self .delegate .complement (get_class (cls ), java_padding_b , java_padding_c )
1638
+ return TriConstraintCollector (result , self .package , self .a_type , self .b_type , self .c_type )
1639
+
1547
1640
def penalize (self , constraint_weight : ScoreType ,
1548
1641
match_weigher : Callable [[A , B , C ], int ] = None ) -> 'TriConstraintBuilder[A, B, C, ScoreType]' :
1549
1642
"""
@@ -2016,7 +2109,6 @@ def map(self, *mapping_functions):
2016
2109
JClass ('java.lang.Object' ))
2017
2110
if len (mapping_functions ) == 4 :
2018
2111
return QuadConstraintStream (self .delegate .map (* translated_functions ), self .package ,
2019
-
2020
2112
JClass ('java.lang.Object' ), JClass ('java.lang.Object' ),
2021
2113
JClass ('java.lang.Object' ), JClass ('java.lang.Object' ))
2022
2114
raise RuntimeError (f'Impossible state: missing case for { len (mapping_functions )} .' )
@@ -2027,7 +2119,6 @@ def flatten_last(self, flattening_function) -> 'QuadConstraintStream[A,B,C,D]':
2027
2119
"""
2028
2120
translated_function = function_cast (flattening_function , self .d_type )
2029
2121
return QuadConstraintStream (self .delegate .flattenLast (translated_function ), self .package ,
2030
-
2031
2122
self .a_type , self .b_type , self .c_type , JClass ('java.lang.Object' ))
2032
2123
2033
2124
def distinct (self ) -> 'QuadConstraintStream[A,B,C,D]' :
@@ -2083,6 +2174,55 @@ def concat(self, other):
2083
2174
else :
2084
2175
raise RuntimeError (f'Unhandled constraint stream type { type (other )} .' )
2085
2176
2177
+ @overload
2178
+ def complement (self , cls : type [A ]) -> 'QuadConstraintStream[A, B, C, D]' :
2179
+ ...
2180
+
2181
+ @overload
2182
+ def complement (self , cls : type [A ], padding_b : Callable [[A ], B ], padding_c : Callable [[A ], C ],
2183
+ padding_d : Callable [[A ], D ]) -> 'QuadConstraintStream[A, B, C, D]' :
2184
+ ...
2185
+
2186
+ def complement (self , cls : type [A ], padding_b = None , padding_c = None , padding_d = None ):
2187
+ """
2188
+ Adds to the stream all instances of a given class which are not yet present in it.
2189
+ These instances must be present in the solution,
2190
+ which means the class needs to be either a planning entity or a problem fact.
2191
+
2192
+ The instances will be read from the first element of the input tuple.
2193
+ When an output tuple needs to be created for the newly inserted instances,
2194
+ the first element will be the new instance.
2195
+ The rest of the tuple will be padded with the result of the padding function,
2196
+ applied on the new instance.
2197
+
2198
+ Padding functions are optional, but if one is provided, then all three must-be provided.
2199
+
2200
+ Parameters
2201
+ ----------
2202
+ cls : Type[A]
2203
+ the type of the instances to add to the stream.
2204
+
2205
+ padding_b : Callable[[A], B]
2206
+ a function that computes the padding value for the second fact in the new tuple.
2207
+
2208
+ padding_c : Callable[[A], C]
2209
+ a function that computes the padding value for the third fact in the new tuple.
2210
+
2211
+ padding_d : Callable[[A], D]
2212
+ a function that computes the padding value for the fourth fact in the new tuple.
2213
+ """
2214
+ if None == padding_b == padding_c == padding_d :
2215
+ result = self .delegate .complement (get_class (cls ))
2216
+ return QuadConstraintCollector (result , self .package , self .a_type , self .b_type , self .c_type , self .d_type )
2217
+ specified_count = sum (x is not None for x in [padding_b , padding_c , padding_d ])
2218
+ if specified_count != 0 :
2219
+ raise ValueError (f'If a padding function is provided, all 3 are expected, got { specified_count } instead.' )
2220
+ java_padding_b = function_cast (padding_b , self .a_type )
2221
+ java_padding_c = function_cast (padding_c , self .a_type )
2222
+ java_padding_d = function_cast (padding_d , self .a_type )
2223
+ result = self .delegate .complement (get_class (cls ), java_padding_b , java_padding_c , java_padding_d )
2224
+ return QuadConstraintCollector (result , self .package , self .a_type , self .b_type , self .c_type , self .d_type )
2225
+
2086
2226
def penalize (self , constraint_weight : ScoreType ,
2087
2227
match_weigher : Callable [[A , B , C , D ], int ] = None ) -> 'QuadConstraintBuilder[A, B, C, D, ScoreType]' :
2088
2228
"""
0 commit comments