[ https://issues.apache.org/jira/browse/MATH-1679?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17986558#comment-17986558 ]
Ruiqi Dong commented on MATH-1679: ---------------------------------- Thank you for reviewing this issue. After reconsidering, I believe the {{}} {code:java} !Double.isInfinite(lower[i]) {code} check is actually unnecessary. > MultivariateFunctionMappingAdapter constructor allows equal lower and upper > bounds, causing invalid mappings > ------------------------------------------------------------------------------------------------------------- > > Key: MATH-1679 > URL: https://issues.apache.org/jira/browse/MATH-1679 > Project: Commons Math > Issue Type: Bug > Components: legacy > Affects Versions: 3.6.1 > Reporter: Ruiqi Dong > Priority: Major > Original Estimate: 0.5h > Remaining Estimate: 0.5h > > The {{MultivariateFunctionMappingAdapter}} constructor does not validate the > case where {{lower[i] == upper[i]}} for bounded parameters. This creates > mathematically invalid mappers that use {{Sigmoid}} and {{Logit}} functions > with degenerate intervals. When lower and upper bounds are equal, the > parameter space collapses to a single point, making the {{Logit}} function > mathematically undefined (division by zero). This can lead to {{NaN}} or > infinity values during optimization, causing numerical instability. > Test Case: > @Test > void testConstructorThrowsWhenLowerEqualsUpper() { > MultivariateFunction bounded = point -> 0.0; > double[] lower = \{2.0}; > double[] upper = \{2.0}; > > assertThrows(NumberIsTooSmallException.class, () -> > new MultivariateFunctionMappingAdapter(bounded, lower, upper), > "Should throw when lower and upper bounds are equal"); > } > > Test Result: > [*ERROR*] > org.apache.commons.math4.legacy.optim.nonlinear.scalar.MultivariateFunctionMappingAdapterTest.testConstructorThrowsWhenLowerEqualsUpper > -- Time elapsed: 0.004 s <<< FAILURE! > org.opentest4j.AssertionFailedError: Should throw when lower and upper bounds > are equal ==> Expected > org.apache.commons.math4.legacy.exception.NumberIsTooSmallException to be > thrown, but nothing was thrown. > at > org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:152) > at org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:73) > at org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:39) > at org.junit.jupiter.api.Assertions.assertThrows(Assertions.java:3153) > at > org.apache.commons.math4.legacy.optim.nonlinear.scalar.MultivariateFunctionMappingAdapterTest.testConstructorThrowsWhenLowerEqualsUpper(MultivariateFunctionMappingAdapterTest.java:181) > at java.lang.reflect.Method.invoke(Method.java:498) > at java.util.ArrayList.forEach(ArrayList.java:1259) > at java.util.ArrayList.forEach(ArrayList.java:1259) > > Root Cause Analysis: > The current validation code only checks: > if (!(upper[i] >= lower[i])) { > throw new NumberIsTooSmallException(upper[i], lower[i], true); > } > This correctly handles {{upper < lower}} and {{NaN}} cases (as noted in the > comment), but allows {{upper == lower}} to pass through. > Suggested Fix: > for (int i = 0; i < lower.length; ++i) { > // existing check > if (!(upper[i] >= lower[i])) { > throw new NumberIsTooSmallException(upper[i], lower[i], true); > } > // add this check > if (upper[i] == lower[i] && !Double.isInfinite(lower[i])) { > throw new NumberIsTooSmallException(upper[i], lower[i], false); > } > } -- This message was sent by Atlassian Jira (v8.20.10#820010)