diff --git a/CHANGELOG.md b/CHANGELOG.md index aba8337c..3d5ba81a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/). Note: This is the main Changelog file for the Rust solver. The Changelog file for the Python interface (`opengen`) can be found in [/open-codegen/CHANGELOG.md](open-codegen/CHANGELOG.md) + +## [v0.8.1] - 2023-10-27 + +### Fixed + +- Fix bug in implementation of `ball2.rs` (radius was being ignored for balls centered not at the origin) + + + @@ -256,7 +267,8 @@ This is a breaking API change. --------------------- --> -[v0.7.8]: https://github.com/alphaville/optimization-engine/compare/v0.7.7...v0.8.0 +[v0.8.1]: https://github.com/alphaville/optimization-engine/compare/v0.8.0...v0.8.1 +[v0.8.0]: https://github.com/alphaville/optimization-engine/compare/v0.7.7...v0.8.0 [v0.7.7]: https://github.com/alphaville/optimization-engine/compare/v0.7.6...v0.7.7 [v0.7.6]: https://github.com/alphaville/optimization-engine/compare/v0.7.5...v0.7.6 [v0.7.5]: https://github.com/alphaville/optimization-engine/compare/v0.7.4...v0.7.5 diff --git a/Cargo.toml b/Cargo.toml index 13adc99f..e130711f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,7 @@ homepage = "https://alphaville.github.io/optimization-engine/" repository = "https://github.com/alphaville/optimization-engine" # Version of this crate (SemVer) -version = "0.8.0" +version = "0.8.1" edition = "2018" diff --git a/src/constraints/ball2.rs b/src/constraints/ball2.rs index a35dd4e0..a26d2944 100644 --- a/src/constraints/ball2.rs +++ b/src/constraints/ball2.rs @@ -31,7 +31,7 @@ impl<'a> Constraint for Ball2<'a> { if norm_difference > self.radius { x.iter_mut().zip(center.iter()).for_each(|(x, c)| { - *x = *c + (*x - *c) / norm_difference; + *x = *c + self.radius * (*x - *c) / norm_difference; }); } } else { diff --git a/src/constraints/tests.rs b/src/constraints/tests.rs index f73a3d7b..a09b3c16 100644 --- a/src/constraints/tests.rs +++ b/src/constraints/tests.rs @@ -226,7 +226,7 @@ fn t_rectangle_only_xmax() { } #[test] -fn t_ball_at_origin() { +fn t_ball2_at_origin() { let radius = 1.0; let mut x = [1.0, 1.0]; let ball = Ball2::new(None, radius); @@ -246,7 +246,47 @@ fn t_ball_at_origin() { } #[test] -fn t_ball_elsewhere() { +fn t_ball2_at_origin_different_radius_outside() { + let radius = 0.8; + let mut x = [1.0, 1.0]; + let ball = Ball2::new(None, radius); + ball.project(&mut x); + let norm_proj_x = crate::matrix_operations::norm2(&x); + unit_test_utils::assert_nearly_equal(radius, norm_proj_x, 1e-10, 1e-12, "wrong norm"); +} + +#[test] +fn t_ball2_at_origin_different_radius_inside() { + let radius = 0.8; + let mut x = [-0.2, 0.15]; + let ball = Ball2::new(None, radius); + ball.project(&mut x); + unit_test_utils::assert_nearly_equal_array(&x, &[-0.2, 0.15], 1e-10, 1e-12, "wrong"); +} + +#[test] +fn t_ball2_at_center_different_radius_outside() { + let radius = 1.2; + let mut x = [1.0, 1.0]; + let center = [-0.8, -1.1]; + let ball = Ball2::new(Some(¢er), radius); + ball.project(&mut x); + let norm_x_minus_c = crate::matrix_operations::norm2_squared_diff(&x, ¢er).sqrt(); + unit_test_utils::assert_nearly_equal(radius, norm_x_minus_c, 1e-10, 1e-12, "wrong norm"); +} + +#[test] +fn t_ball2_at_center_different_radius_inside() { + let radius = 1.2; + let mut x = [-0.9, -0.85]; + let center = [-0.8, -1.1]; + let ball = Ball2::new(Some(¢er), radius); + ball.project(&mut x); + unit_test_utils::assert_nearly_equal_array(&[-0.9, -0.85], &x, 1e-10, 1e-12, "wrong result"); +} + +#[test] +fn t_ball2_elsewhere() { let radius = 1.0; let center = [1.0, 1.0]; let mut x = [2.0, 2.0]; @@ -465,7 +505,7 @@ fn t_cartesian_product_dimension() { #[test] fn t_cartesian_ball_no_constraint() { let xc = [1., 0., 0.]; - let radius = 0.5; + let radius = 1.0; let ball2 = Ball2::new(Some(&xc), radius); let no_constraints = NoConstraints::new(); let cartesian = CartesianProduct::new_with_capacity(4)