1
- use ndarray:: { Array1 , Array2 , ArrayBase , Axis , Data , Ix1 , Ix2 , Zip } ;
1
+ use ndarray:: { concatenate , Array1 , Array2 , ArrayBase , Axis , Data , Ix1 , Ix2 , Zip } ;
2
2
use ndarray_stats:: QuantileExt ;
3
3
4
4
use crate :: utils:: sort_axis:: * ;
@@ -46,39 +46,54 @@ pub fn find_best_result_index_from<F: Float>(
46
46
current_index : usize , /* current best index */
47
47
offset_index : usize ,
48
48
ydata : & ArrayBase < impl Data < Elem = F > , Ix2 > , /* the whole data so far */
49
+ cdata : & ArrayBase < impl Data < Elem = F > , Ix2 > , /* the whole function cstrs data so far */
49
50
cstr_tol : & Array1 < F > ,
50
51
) -> usize {
51
- let new_ydata = ydata. slice ( s ! [ offset_index.., ..] ) ;
52
+ // let new_ydata = ydata.slice(s![offset_index.., ..]);
53
+
54
+ let alldata = concatenate ! [ Axis ( 1 ) , ydata. to_owned( ) , cdata. to_owned( ) ] ;
55
+ let alltols = concatenate ! [ Axis ( 0 ) , cstr_tol. to_owned( ) , Array1 :: zeros( cdata. ncols( ) ) ] ;
56
+
57
+ let new_ydata = alldata. slice ( s ! [ offset_index.., ..] ) ;
52
58
53
59
let best = ydata. row ( current_index) ;
54
60
let min = new_ydata
55
61
. outer_iter ( )
56
62
. enumerate ( )
57
63
. fold ( ( usize:: MAX , best) , |a, b| {
58
- std:: cmp:: min_by ( a, b, |( i, u) , ( j, v) | cstr_min ( ( * i, u) , ( * j, v) , cstr_tol ) )
64
+ std:: cmp:: min_by ( a, b, |( i, u) , ( j, v) | cstr_min ( ( * i, u) , ( * j, v) , & alltols ) )
59
65
} ) ;
60
66
match min {
61
67
( usize:: MAX , _) => current_index,
62
68
( index, _) => offset_index + index,
63
69
}
64
70
}
65
71
66
- /// Find best (eg minimal) cost value (y_data\[0\]) with valid constraints (y_data\[1..\] < cstr_tol).
67
- /// y_data containing ns samples [objective, cstr_1, ... cstr_nc] is given as a matrix (ns, nc + 1)
72
+ /// Find best (eg minimal) cost value (y_data\[0\]) with valid constraints, meaning
73
+ /// * y_data\[1..\] < cstr_tol
74
+ /// * c_data[..] < 0
75
+ ///
76
+ /// y_data containing ns samples [objective, cstr_1, ... cstr_nc] is given as a matrix (ns, nc + 1)
77
+ /// c_data containing [fcstr_1, ... fcstr1_nfc] where fcstr_i is the value of function constraints at x_i
68
78
pub fn find_best_result_index < F : Float > (
69
79
y_data : & ArrayBase < impl Data < Elem = F > , Ix2 > ,
80
+ c_data : & ArrayBase < impl Data < Elem = F > , Ix2 > ,
70
81
cstr_tol : & Array1 < F > ,
71
82
) -> usize {
72
- if y_data. ncols ( ) > 1 {
83
+ if y_data. ncols ( ) > 1 || c_data. ncols ( ) > 0 {
84
+ // Merge metamodelised constraints and function constraints
85
+ let alldata = concatenate ! [ Axis ( 1 ) , y_data. to_owned( ) , c_data. to_owned( ) ] ;
86
+ let alltols = concatenate ! [ Axis ( 0 ) , cstr_tol. to_owned( ) , Array1 :: zeros( c_data. ncols( ) ) ] ;
87
+
73
88
// Compute sum of violated constraints
74
- let cstrs = y_data . slice ( s ! [ .., 1 ..] ) ;
89
+ let cstrs = & alldata . slice ( s ! [ .., 1 ..] ) ;
75
90
let mut c_obj = Array2 :: zeros ( ( y_data. nrows ( ) , 2 ) ) ;
76
91
77
92
Zip :: from ( c_obj. rows_mut ( ) )
78
93
. and ( cstrs. rows ( ) )
79
- . and ( y_data . slice ( s ! [ .., 0 ] ) )
94
+ . and ( alldata . slice ( s ! [ .., 0 ] ) )
80
95
. for_each ( |mut c_obj_row, c_row, obj| {
81
- let c_sum = zip ( c_row, cstr_tol )
96
+ let c_sum = zip ( c_row, & alltols )
82
97
. filter ( |( c, ctol) | * c > ctol)
83
98
. fold ( F :: zero ( ) , |acc, ( c, ctol) | acc + ( * c - * ctol) . abs ( ) ) ;
84
99
c_obj_row. assign ( & array ! [ c_sum, * obj] ) ;
@@ -106,13 +121,13 @@ pub fn find_best_result_index<F: Float>(
106
121
let mut index = 0 ;
107
122
108
123
// sort regardoing minimal objective
109
- let perm = y_data . sort_axis_by ( Axis ( 0 ) , |i, j| y_data [ [ i, 0 ] ] < y_data [ [ j, 0 ] ] ) ;
110
- let y_sort = y_data . to_owned ( ) . permute_axis ( Axis ( 0 ) , & perm) ;
124
+ let perm = alldata . sort_axis_by ( Axis ( 0 ) , |i, j| alldata [ [ i, 0 ] ] < alldata [ [ j, 0 ] ] ) ;
125
+ let y_sort = alldata . to_owned ( ) . permute_axis ( Axis ( 0 ) , & perm) ;
111
126
112
127
// Take the first one which do not violate constraints
113
128
for ( i, row) in y_sort. axis_iter ( Axis ( 0 ) ) . enumerate ( ) {
114
129
let success =
115
- zip ( row. slice ( s ! [ 1 ..] ) , cstr_tol ) . fold ( true , |acc, ( c, tol) | acc && c < tol) ;
130
+ zip ( row. slice ( s ! [ 1 ..] ) , & alltols ) . fold ( true , |acc, ( c, tol) | acc && c < tol) ;
116
131
117
132
if success {
118
133
index = i;
@@ -170,28 +185,29 @@ mod tests {
170
185
fn test_find_best_obj ( ) {
171
186
// respect constraint (0, 1, 2) and minimize obj (1)
172
187
let ydata = array ! [ [ 1.0 , -0.15 ] , [ -1.0 , -0.01 ] , [ 2.0 , -0.2 ] , [ -3.0 , 2.0 ] ] ;
188
+ let cdata = array ! [ [ ] , [ ] , [ ] , [ ] ] ;
173
189
let cstr_tol = Array1 :: from_elem ( 4 , 0.1 ) ;
174
- assert_abs_diff_eq ! ( 1 , find_best_result_index( & ydata, & cstr_tol) ) ;
190
+ assert_abs_diff_eq ! ( 1 , find_best_result_index( & ydata, & cdata , & cstr_tol) ) ;
175
191
176
192
// respect constraint (0, 1, 2) and minimize obj (2)
177
193
let ydata = array ! [ [ 1.0 , -0.15 ] , [ -1.0 , -0.01 ] , [ -2.0 , -0.2 ] , [ -3.0 , 2.0 ] ] ;
178
194
let cstr_tol = Array1 :: from_elem ( 4 , 0.1 ) ;
179
- assert_abs_diff_eq ! ( 2 , find_best_result_index( & ydata, & cstr_tol) ) ;
195
+ assert_abs_diff_eq ! ( 2 , find_best_result_index( & ydata, & cdata , & cstr_tol) ) ;
180
196
181
197
// all out of tolerance => minimize constraint overshoot sum (0)
182
198
let ydata = array ! [ [ 1.0 , 0.15 ] , [ -1.0 , 0.3 ] , [ 2.0 , 0.2 ] , [ -3.0 , 2.0 ] ] ;
183
199
let cstr_tol = Array1 :: from_elem ( 4 , 0.1 ) ;
184
- assert_abs_diff_eq ! ( 0 , find_best_result_index( & ydata, & cstr_tol) ) ;
200
+ assert_abs_diff_eq ! ( 0 , find_best_result_index( & ydata, & cdata , & cstr_tol) ) ;
185
201
186
202
// all in tolerance => min obj
187
203
let ydata = array ! [ [ 1.0 , 0.15 ] , [ -1.0 , 0.3 ] , [ 2.0 , 0.2 ] , [ -3.0 , 2.0 ] ] ;
188
204
let cstr_tol = Array1 :: from_elem ( 4 , 3.0 ) ;
189
- assert_abs_diff_eq ! ( 3 , find_best_result_index( & ydata, & cstr_tol) ) ;
205
+ assert_abs_diff_eq ! ( 3 , find_best_result_index( & ydata, & cdata , & cstr_tol) ) ;
190
206
191
207
// unconstrained => min obj
192
208
let ydata = array ! [ [ 1.0 ] , [ -1.0 ] , [ 2.0 ] , [ -3.0 ] ] ;
193
209
let cstr_tol = Array1 :: from_elem ( 4 , 0.1 ) ;
194
- assert_abs_diff_eq ! ( 3 , find_best_result_index( & ydata, & cstr_tol) ) ;
210
+ assert_abs_diff_eq ! ( 3 , find_best_result_index( & ydata, & cdata , & cstr_tol) ) ;
195
211
}
196
212
197
213
#[ test]
@@ -216,11 +232,12 @@ mod tests {
216
232
[ -5.50801509642 , 1.951629235996e-7 , 2.48275059533e-6 ] ,
217
233
[ -5.50801399313 , -6.707576982734e-8 , 1.03991762046e-6 ]
218
234
] ;
235
+ let c_data = Array2 :: zeros ( ( y_data. nrows ( ) , 0 ) ) ;
219
236
let cstr_tol = Array1 :: from_vec ( vec ! [ 1e-6 ; 2 ] ) ; // this is the default
220
- let index = find_best_result_index ( & y_data, & cstr_tol) ;
237
+ let index = find_best_result_index ( & y_data, & c_data , & cstr_tol) ;
221
238
assert_eq ! ( 11 , index) ;
222
239
let cstr_tol = Array1 :: from_vec ( vec ! [ 2e-6 ; 2 ] ) ;
223
- let index = find_best_result_index ( & y_data, & cstr_tol) ;
240
+ let index = find_best_result_index ( & y_data, & c_data , & cstr_tol) ;
224
241
assert_eq ! ( 17 , index) ;
225
242
}
226
243
@@ -246,11 +263,12 @@ mod tests {
246
263
[ -5.50801509642 , 1.951629235996e-7 , 2.48275059533e-6 ] ,
247
264
[ -5.50801399313 , -6.707576982734e-8 , 1.03991762046e-6 ]
248
265
] ;
266
+ let c_data = Array2 :: zeros ( ( y_data. nrows ( ) , 0 ) ) ;
249
267
let cstr_tol = Array1 :: from_vec ( vec ! [ 2e-6 ; 2 ] ) ;
250
- let index = find_best_result_index_from ( 11 , 12 , & y_data, & cstr_tol) ;
268
+ let index = find_best_result_index_from ( 11 , 12 , & y_data, & c_data , & cstr_tol) ;
251
269
assert_eq ! ( 17 , index) ;
252
270
let cstr_tol = Array1 :: from_vec ( vec ! [ 2e-6 ; 2 ] ) ;
253
- let index = find_best_result_index ( & y_data, & cstr_tol) ;
271
+ let index = find_best_result_index ( & y_data, & c_data , & cstr_tol) ;
254
272
assert_eq ! ( 17 , index) ;
255
273
}
256
274
}
0 commit comments