Skip to content

Commit 2cba707

Browse files
committed
more thorough testing (f32+f64)
1 parent e61c3f9 commit 2cba707

4 files changed

Lines changed: 159 additions & 0 deletions

File tree

.github/pull_request_template.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
- OpEn version ...
1414
- opengen version ...
1515

16+
## Merge dependencies
17+
18+
- PR xyz should be merged first
19+
1620
## Checklist
1721

1822
- [ ] Documentation

src/alm/tests.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,80 @@ fn t_alm_numeric_test_1() {
390390
);
391391
}
392392

393+
#[test]
394+
fn t_alm_numeric_test_1_f32() {
395+
let tolerance = 1e-4_f32;
396+
let nx = 3;
397+
let n1 = 2;
398+
let n2 = 0;
399+
let lbfgs_mem = 3;
400+
let panoc_cache = PANOCCache::<f32>::new(nx, tolerance, lbfgs_mem);
401+
let mut alm_cache = AlmCache::<f32>::new(panoc_cache, n1, n2);
402+
403+
let set_c = Ball2::new(None, 1.0_f32);
404+
let bounds = Ball2::new(None, 10.0_f32);
405+
let set_y = Ball2::new(None, 10_000.0_f32);
406+
407+
let factory = AlmFactory::new(
408+
mocks::f0::<f32>,
409+
mocks::d_f0::<f32>,
410+
Some(mocks::mapping_f1_affine::<f32>),
411+
Some(mocks::mapping_f1_affine_jacobian_product::<f32>),
412+
no_mapping::<f32>(),
413+
no_jacobian_mapping::<f32>(),
414+
Some(set_c),
415+
n2,
416+
);
417+
418+
let set_c_b = Ball2::new(None, 1.0_f32);
419+
let alm_problem = AlmProblem::new(
420+
bounds,
421+
Some(set_c_b),
422+
Some(set_y),
423+
|u: &[f32], xi: &[f32], cost: &mut f32| -> FunctionCallResult { factory.psi(u, xi, cost) },
424+
|u: &[f32], xi: &[f32], grad: &mut [f32]| -> FunctionCallResult {
425+
factory.d_psi(u, xi, grad)
426+
},
427+
Some(mocks::mapping_f1_affine::<f32>),
428+
no_mapping::<f32>(),
429+
n1,
430+
n2,
431+
);
432+
433+
let mut alm_optimizer = AlmOptimizer::new(&mut alm_cache, alm_problem)
434+
.with_delta_tolerance(1e-3_f32)
435+
.with_max_outer_iterations(30)
436+
.with_epsilon_tolerance(1e-4_f32)
437+
.with_initial_inner_tolerance(1e-2_f32)
438+
.with_inner_tolerance_update_factor(0.5_f32)
439+
.with_initial_penalty(1.0_f32)
440+
.with_penalty_update_factor(1.2_f32)
441+
.with_sufficient_decrease_coefficient(0.1_f32)
442+
.with_initial_lagrange_multipliers(&vec![5.0_f32; n1]);
443+
444+
let mut u = vec![0.0_f32; nx];
445+
let solver_result = alm_optimizer.solve(&mut u);
446+
assert!(solver_result.is_ok());
447+
let r = solver_result.unwrap();
448+
assert_eq!(ExitStatus::Converged, r.exit_status());
449+
assert!(r.num_outer_iterations() > 0 && r.num_outer_iterations() <= 30);
450+
assert!(r.last_problem_norm_fpr() < tolerance);
451+
assert!(r.delta_y_norm_over_c() < 1e-3_f32);
452+
453+
let mut f1u = vec![0.0_f32; n1];
454+
assert!(mocks::mapping_f1_affine(&u, &mut f1u).is_ok());
455+
let mut projection = f1u.clone();
456+
let set_c_check = Ball2::new(None, 1.0_f32);
457+
set_c_check.project(&mut projection);
458+
assert!((f1u[0] - projection[0]).abs() < 2e-3_f32);
459+
assert!((f1u[1] - projection[1]).abs() < 2e-3_f32);
460+
461+
let cost_actual = r.cost();
462+
let mut cost_expected = 0.0_f32;
463+
assert!(mocks::f0(&u, &mut cost_expected).is_ok());
464+
assert!((cost_actual - cost_expected).abs() < 2e-3_f32);
465+
}
466+
393467
fn mapping_f2(u: &[f64], res: &mut [f64]) -> FunctionCallResult {
394468
res[0] = u[0];
395469
res[1] = u[1];

src/constraints/tests.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,27 @@ fn t_cartesian_product_ball_and_rectangle() {
491491
);
492492
}
493493

494+
#[test]
495+
fn t_cartesian_product_ball_and_rectangle_f32() {
496+
let xmin1 = vec![-1.0_f32; 2];
497+
let xmax1 = vec![1.0_f32; 2];
498+
let rectangle1 = Rectangle::new(Some(&xmin1), Some(&xmax1));
499+
500+
let radius = 1.0_f32;
501+
let ball = Ball2::new(None, radius);
502+
503+
let cart_prod = CartesianProduct::new()
504+
.add_constraint(2, rectangle1)
505+
.add_constraint(5, ball);
506+
507+
let mut x = [-4.0_f32, 0.25_f32, 2.0_f32, -1.0_f32, 2.0_f32];
508+
cart_prod.project(&mut x);
509+
510+
assert_eq!([-1.0_f32, 0.25_f32], x[..2]);
511+
let ball_norm = crate::matrix_operations::norm2(&x[2..5]);
512+
assert!((ball_norm - radius).abs() < 1e-5_f32);
513+
}
514+
494515
#[test]
495516
fn t_second_order_cone_case_i() {
496517
let soc = SecondOrderCone::new(1.0);
@@ -529,6 +550,17 @@ fn t_second_order_cone_case_iii() {
529550
assert!((norm_z - alpha * x[2]).abs() <= 1e-7);
530551
}
531552

553+
#[test]
554+
fn t_second_order_cone_case_iii_f32() {
555+
let alpha = 1.5_f32;
556+
let soc = SecondOrderCone::new(alpha);
557+
let mut x = vec![1.0_f32, 1.0_f32, 0.1_f32];
558+
soc.project(&mut x);
559+
let norm_z = crate::matrix_operations::norm2(&x[..=1]);
560+
assert!(norm_z <= alpha * x[2] + 1e-5_f32);
561+
assert!((norm_z - alpha * x[2]).abs() <= 1e-4_f32);
562+
}
563+
532564
#[test]
533565
#[should_panic]
534566
fn t_second_order_cone_illegal_alpha_i() {
@@ -885,6 +917,17 @@ fn t_ball1_random_optimality_conditions() {
885917
}
886918
}
887919

920+
#[test]
921+
fn t_ball1_projection_f32() {
922+
let ball1 = Ball1::new(None, 1.0_f32);
923+
let mut x = [2.0_f32, -1.0_f32, 0.0_f32];
924+
ball1.project(&mut x);
925+
assert!((x[0] - 1.0_f32).abs() < 1e-6_f32);
926+
assert!(x[1].abs() < 1e-6_f32);
927+
assert!(x[2].abs() < 1e-6_f32);
928+
assert!(crate::matrix_operations::norm1(&x) <= 1.0_f32 + 1e-6_f32);
929+
}
930+
888931
#[test]
889932
fn t_ball1_random_optimality_conditions_centered() {
890933
for n in (10..=60).step_by(10) {

src/core/panoc/panoc_optimizer.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,44 @@ mod tests {
263263
);
264264
}
265265

266+
#[test]
267+
fn t_panoc_optimizer_rosenbrock_f32() {
268+
let tolerance = 1e-4_f32;
269+
let a_param = 1.0_f32;
270+
let b_param = 200.0_f32;
271+
let n_dimension = 2;
272+
let lbfgs_memory = 8;
273+
let max_iters = 120;
274+
let mut u_solution = [-1.5_f32, 0.9_f32];
275+
276+
let cost_gradient = |u: &[f32], grad: &mut [f32]| -> FunctionCallResult {
277+
mocks::rosenbrock_grad(a_param, b_param, u, grad);
278+
Ok(())
279+
};
280+
let cost_function = |u: &[f32], c: &mut f32| -> FunctionCallResult {
281+
*c = mocks::rosenbrock_cost(a_param, b_param, u);
282+
Ok(())
283+
};
284+
285+
let radius = 2.0_f32;
286+
let bounds = constraints::Ball2::new(None, radius);
287+
let mut panoc_cache = PANOCCache::<f32>::new(n_dimension, tolerance, lbfgs_memory);
288+
let problem = Problem::new(&bounds, cost_gradient, cost_function);
289+
let mut panoc = PANOCOptimizer::new(problem, &mut panoc_cache).with_max_iter(max_iters);
290+
let status = panoc.solve(&mut u_solution).unwrap();
291+
292+
assert_eq!(max_iters, panoc.max_iter);
293+
assert!(status.has_converged());
294+
assert!(status.iterations() < max_iters);
295+
assert!(status.norm_fpr() < tolerance);
296+
297+
let mut u_project = [0.0_f32; 2];
298+
u_project.copy_from_slice(&u_solution);
299+
bounds.project(&mut u_project);
300+
assert!((u_solution[0] - u_project[0]).abs() < 1e-5_f32);
301+
assert!((u_solution[1] - u_project[1]).abs() < 1e-5_f32);
302+
}
303+
266304
#[test]
267305
fn t_panoc_in_loop() {
268306
/* USER PARAMETERS */

0 commit comments

Comments
 (0)