@@ -55,7 +55,6 @@ impl<SB: SurrogateBuilder + DeserializeOwned, C: CstrFn> EgorSolver<SB, C> {
55
55
& self ,
56
56
x_data : & ArrayBase < impl Data < Elem = f64 > , Ix2 > ,
57
57
y_data : & ArrayBase < impl Data < Elem = f64 > , Ix2 > ,
58
- _cstr_funcs : & [ & ( dyn ObjFn < InfillObjData < f64 > > + Sync ) ] ,
59
58
) -> Array2 < f64 > {
60
59
let rng = self . rng . clone ( ) ;
61
60
let sampling = Lhs :: new ( & self . xlimits ) . with_rng ( rng) . kind ( LhsKind :: Maximin ) ;
@@ -66,19 +65,26 @@ impl<SB: SurrogateBuilder + DeserializeOwned, C: CstrFn> EgorSolver<SB, C> {
66
65
. cstr_tol
67
66
. clone ( )
68
67
. unwrap_or ( Array1 :: from_elem ( self . config . n_cstr , DEFAULT_CSTR_TOL ) ) ;
69
- let ( x_dat, _, _, _) = self . next_points (
68
+
69
+ // TODO: Manage fonction constraints
70
+ let fcstrs = Vec :: < Cstr > :: new ( ) ;
71
+ // TODO: c_data has to be passed as argument or better computed using fcstrs(x_data)
72
+ let c_data = Array2 :: zeros ( ( x_data. nrows ( ) , 0 ) ) ;
73
+
74
+ let ( x_dat, _, _, _, _) = self . next_points (
70
75
true ,
71
76
0 ,
72
77
false , // done anyway
73
78
& mut clusterings,
74
79
& mut theta_tunings,
75
80
x_data,
76
81
y_data,
82
+ & c_data,
77
83
& cstr_tol,
78
84
& sampling,
79
85
None ,
80
86
find_best_result_index ( y_data, & cstr_tol) ,
81
- & Vec :: < Cstr > :: new ( ) ,
87
+ & fcstrs ,
82
88
) ;
83
89
x_dat
84
90
}
@@ -249,7 +255,7 @@ where
249
255
PotentialBug ,
250
256
"EgorSolver: No sampling!"
251
257
) ) ?;
252
- let ( mut x_data, mut y_data) = new_state
258
+ let ( mut x_data, mut y_data, mut c_data ) = new_state
253
259
. take_data ( )
254
260
. ok_or_else ( argmin_error_closure ! ( PotentialBug , "EgorSolver: No data!" ) ) ?;
255
261
@@ -270,14 +276,15 @@ where
270
276
271
277
let problem = fobj. take_problem ( ) . unwrap ( ) ;
272
278
let fcstrs = problem. fn_constraints ( ) ;
273
- let ( x_dat, y_dat, infill_value, infill_data) = self . next_points (
279
+ let ( x_dat, y_dat, c_dat , infill_value, infill_data) = self . next_points (
274
280
init,
275
281
state. get_iter ( ) ,
276
282
recluster,
277
283
& mut clusterings,
278
284
& mut theta_inits,
279
285
& x_data,
280
286
& y_data,
287
+ & c_data,
281
288
& state. cstr_tol ,
282
289
& sampling,
283
290
lhs_optim_seed,
@@ -287,12 +294,19 @@ where
287
294
fobj. problem = Some ( problem) ;
288
295
289
296
debug ! ( "Try adding {}" , x_dat) ;
290
- let added_indices = update_data ( & mut x_data, & mut y_data, & x_dat, & y_dat) ;
297
+ let added_indices = update_data (
298
+ & mut x_data,
299
+ & mut y_data,
300
+ & mut c_data,
301
+ & x_dat,
302
+ & y_dat,
303
+ & c_dat,
304
+ ) ;
291
305
292
306
new_state = new_state
293
307
. clusterings ( clusterings. clone ( ) )
294
308
. theta_inits ( theta_inits. clone ( ) )
295
- . data ( ( x_data. clone ( ) , y_data. clone ( ) ) )
309
+ . data ( ( x_data. clone ( ) , y_data. clone ( ) , c_data . clone ( ) ) )
296
310
. infill_value ( infill_value)
297
311
. sampling ( sampling. clone ( ) )
298
312
. param ( x_dat. row ( 0 ) . to_owned ( ) )
@@ -365,7 +379,7 @@ where
365
379
) ;
366
380
new_state. prev_best_index = state. best_index ;
367
381
new_state. best_index = Some ( best_index) ;
368
- new_state = new_state. data ( ( x_data. clone ( ) , y_data. clone ( ) ) ) ;
382
+ new_state = new_state. data ( ( x_data. clone ( ) , y_data. clone ( ) , c_data . clone ( ) ) ) ;
369
383
370
384
Ok ( ( new_state, infill_data, best_index) )
371
385
}
@@ -384,15 +398,23 @@ where
384
398
theta_inits : & mut [ Option < Array2 < f64 > > ] ,
385
399
x_data : & ArrayBase < impl Data < Elem = f64 > , Ix2 > ,
386
400
y_data : & ArrayBase < impl Data < Elem = f64 > , Ix2 > ,
401
+ c_data : & ArrayBase < impl Data < Elem = f64 > , Ix2 > ,
387
402
cstr_tol : & Array1 < f64 > ,
388
403
sampling : & Lhs < f64 , Xoshiro256Plus > ,
389
404
lhs_optim : Option < u64 > ,
390
405
best_index : usize ,
391
406
cstr_funcs : & [ impl CstrFn ] ,
392
- ) -> ( Array2 < f64 > , Array2 < f64 > , f64 , InfillObjData < f64 > ) {
407
+ ) -> (
408
+ Array2 < f64 > ,
409
+ Array2 < f64 > ,
410
+ Array2 < f64 > ,
411
+ f64 ,
412
+ InfillObjData < f64 > ,
413
+ ) {
393
414
debug ! ( "Make surrogate with {}" , x_data) ;
394
415
let mut x_dat = Array2 :: zeros ( ( 0 , x_data. ncols ( ) ) ) ;
395
416
let mut y_dat = Array2 :: zeros ( ( 0 , y_data. ncols ( ) ) ) ;
417
+ let mut c_dat = Array2 :: zeros ( ( 0 , c_data. ncols ( ) ) ) ;
396
418
let mut infill_val = f64:: INFINITY ;
397
419
let mut infill_data = Default :: default ( ) ;
398
420
for i in 0 ..self . config . q_points {
@@ -458,14 +480,42 @@ where
458
480
scale_wb2,
459
481
} ;
460
482
483
+ let cstr_funcs = cstr_funcs
484
+ . iter ( )
485
+ . map ( |cstr| {
486
+ |x : & [ f64 ] ,
487
+ gradient : Option < & mut [ f64 ] > ,
488
+ params : & mut InfillObjData < f64 > |
489
+ -> f64 {
490
+ let x = if self . config . discrete ( ) {
491
+ let xary = Array2 :: from_shape_vec ( ( 1 , x. len ( ) ) , x. to_vec ( ) ) . unwrap ( ) ;
492
+ // We have to cast x to folded space as EgorSolver
493
+ // works internally in the continuous space while
494
+ // the constraint function expects discrete variable in folded space
495
+ to_discrete_space ( & self . config . xtypes , & xary)
496
+ . row ( 0 )
497
+ . into_owned ( ) ;
498
+ & xary. into_iter ( ) . collect :: < Vec < _ > > ( )
499
+ } else {
500
+ x
501
+ } ;
502
+ cstr ( x, gradient, params)
503
+ }
504
+ } )
505
+ . collect :: < Vec < _ > > ( ) ;
506
+ let cstr_funcs = cstr_funcs
507
+ . iter ( )
508
+ . map ( |cstr| cstr as & ( dyn ObjFn < InfillObjData < f64 > > + Sync ) )
509
+ . collect :: < Vec < _ > > ( ) ;
510
+
461
511
match self . find_best_point (
462
512
sampling,
463
513
obj_model. as_ref ( ) ,
464
514
cstr_models,
465
515
cstr_tol,
466
516
lhs_optim,
467
517
& infill_data,
468
- cstr_funcs,
518
+ & cstr_funcs,
469
519
) {
470
520
Ok ( ( infill_obj, xk) ) => {
471
521
match self . get_virtual_point ( & xk, y_data, obj_model. as_ref ( ) , cstr_models) {
@@ -475,7 +525,19 @@ where
475
525
y_dat,
476
526
Array2 :: from_shape_vec( ( 1 , 1 + self . config. n_cstr) , yk) . unwrap( )
477
527
] ;
528
+
529
+ let ck = cstr_funcs
530
+ . iter ( )
531
+ . map ( |cstr| cstr ( & xk. to_vec ( ) , None , & mut infill_data) )
532
+ . collect :: < Vec < _ > > ( ) ;
533
+ c_dat = concatenate ! [
534
+ Axis ( 0 ) ,
535
+ c_dat,
536
+ Array2 :: from_shape_vec( ( 1 , cstr_funcs. len( ) ) , ck) . unwrap( )
537
+ ] ;
538
+
478
539
x_dat = concatenate ! [ Axis ( 0 ) , x_dat, xk. insert_axis( Axis ( 0 ) ) ] ;
540
+
479
541
// infill objective was minimized while infill criterion itself
480
542
// is expected to be maximized hence the negative sign here
481
543
infill_val = -infill_obj;
@@ -494,7 +556,7 @@ where
494
556
}
495
557
}
496
558
}
497
- ( x_dat, y_dat, infill_val, infill_data)
559
+ ( x_dat, y_dat, c_dat , infill_val, infill_data)
498
560
}
499
561
500
562
pub ( crate ) fn compute_scaling (
@@ -550,7 +612,7 @@ where
550
612
cstr_tol : & Array1 < f64 > ,
551
613
lhs_optim_seed : Option < u64 > ,
552
614
infill_data : & InfillObjData < f64 > ,
553
- cstr_funcs : & [ impl CstrFn ] ,
615
+ cstr_funcs : & [ & ( dyn ObjFn < InfillObjData < f64 > > + Sync ) ] ,
554
616
) -> Result < ( f64 , Array1 < f64 > ) > {
555
617
let fmin = infill_data. fmin ;
556
618
@@ -626,30 +688,8 @@ where
626
688
} )
627
689
. collect ( ) ;
628
690
let mut cstr_refs: Vec < _ > = cstrs. iter ( ) . map ( |c| c. as_ref ( ) ) . collect ( ) ;
629
- let cstr_funcs = cstr_funcs
630
- . iter ( )
631
- . map ( |cstr| {
632
- |x : & [ f64 ] , gradient : Option < & mut [ f64 ] > , params : & mut InfillObjData < f64 > | -> f64 {
633
- let x = if self . config . discrete ( ) {
634
- let xary = Array2 :: from_shape_vec ( ( 1 , x. len ( ) ) , x. to_vec ( ) ) . unwrap ( ) ;
635
- // We have to cast x to folded space as EgorSolver
636
- // works internally in the continuous space while
637
- // the constraint function expects discrete variable in folded space
638
- to_discrete_space ( & self . config . xtypes , & xary)
639
- . row ( 0 )
640
- . into_owned ( ) ;
641
- & xary. into_iter ( ) . collect :: < Vec < _ > > ( )
642
- } else {
643
- x
644
- } ;
645
- cstr ( x, gradient, params)
646
- }
647
- } )
648
- . collect :: < Vec < _ > > ( ) ;
649
- let cstr_funcs = cstr_funcs
650
- . iter ( )
651
- . map ( |cstr| cstr as & ( dyn ObjFn < InfillObjData < f64 > > + Sync ) ) ;
652
691
cstr_refs. extend ( cstr_funcs) ;
692
+
653
693
info ! ( "Optimize infill criterion..." ) ;
654
694
while !success && n_optim <= n_max_optim {
655
695
let x_start = sampling. sample ( self . config . n_start ) ;
@@ -818,15 +858,53 @@ where
818
858
pb : & mut Problem < O > ,
819
859
x : & Array2 < f64 > ,
820
860
) -> Array2 < f64 > {
821
- let params = if self . config . discrete ( ) {
861
+ let x = if self . config . discrete ( ) {
822
862
// We have to cast x to folded space as EgorSolver
823
863
// works internally in the continuous space while
824
864
// the objective function expects discrete variable in folded space
825
865
to_discrete_space ( & self . config . xtypes , x)
826
866
} else {
827
867
x. to_owned ( )
828
868
} ;
829
- pb. problem ( "cost_count" , |problem| problem. cost ( & params ) )
869
+ pb. problem ( "cost_count" , |problem| problem. cost ( & x ) )
830
870
. expect ( "Objective evaluation" )
831
871
}
872
+
873
+ pub fn eval_fcstrs < O : DomainConstraints < C > > (
874
+ & self ,
875
+ pb : & mut Problem < O > ,
876
+ x : & Array2 < f64 > ,
877
+ ) -> Array2 < f64 > {
878
+ let problem = pb. take_problem ( ) . unwrap ( ) ;
879
+ let fcstrs = problem. fn_constraints ( ) ;
880
+
881
+ let mut unused = InfillObjData :: default ( ) ;
882
+
883
+ let mut res = Array2 :: zeros ( ( x. nrows ( ) , fcstrs. len ( ) ) ) ;
884
+ Zip :: from ( res. rows_mut ( ) )
885
+ . and ( x. rows ( ) )
886
+ . for_each ( |mut r, xi| {
887
+ let cstr_vals = & fcstrs
888
+ . iter ( )
889
+ . map ( |cstr| {
890
+ let xuser = if self . config . discrete ( ) {
891
+ let xary = xi. to_owned ( ) . insert_axis ( Axis ( 0 ) ) ;
892
+ // We have to cast x to folded space as EgorSolver
893
+ // works internally in the continuous space while
894
+ // the constraint function expects discrete variable in folded space
895
+ to_discrete_space ( & self . config . xtypes , & xary)
896
+ . row ( 0 )
897
+ . into_owned ( ) ;
898
+ & xary. into_iter ( ) . collect :: < Vec < _ > > ( )
899
+ } else {
900
+ xi. as_slice ( ) . unwrap ( )
901
+ } ;
902
+ cstr ( xuser, None , & mut unused)
903
+ } )
904
+ . collect :: < Array1 < _ > > ( ) ;
905
+ r. assign ( cstr_vals)
906
+ } ) ;
907
+ pb. problem = Some ( problem) ;
908
+ res
909
+ }
832
910
}
0 commit comments