[ 
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)

Reply via email to