Improvements to minimize.least_squares.

All changes make functionality more similar to SciPy least squares:
- Use adaptive findiff epsilon.
- Make termination on step size relative to norm(x).
- Add termination on gradient norm.
- Make default tolerances like SciPy's.

PiperOrigin-RevId: 745221614
Change-Id: Iee93256651fca8154c97fa3bdaa9c67ede28e573
This commit is contained in:
Yuval Tassa
2025-04-08 11:21:15 -07:00
committed by Copybara-Service
parent 96dda6ea75
commit 55e3ca3acf
2 changed files with 43 additions and 17 deletions
+4 -5
View File
@@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""Tests for minimize.py."""
import io
@@ -32,7 +31,7 @@ class MinimizeTest(absltest.TestCase):
x, _ = minimize.least_squares(x0, residual, output=out)
expected_x = np.array((1.0, 1.0))
np.testing.assert_array_almost_equal(x, expected_x)
self.assertIn('norm(dx) < tol', out.getvalue())
self.assertIn('norm(gradient) < tol', out.getvalue())
def test_start_at_minimum(self) -> None:
def residual(x):
@@ -43,7 +42,7 @@ class MinimizeTest(absltest.TestCase):
x, _ = minimize.least_squares(x0, residual, output=out)
expected_x = np.array((1.0, 1.0))
np.testing.assert_array_almost_equal(x, expected_x)
self.assertIn('norm(dx) < tol', out.getvalue())
self.assertIn('norm(gradient) < tol', out.getvalue())
self.assertIn('exact minimum found', out.getvalue())
def test_jac_callback(self) -> None:
@@ -61,7 +60,7 @@ class MinimizeTest(absltest.TestCase):
)
expected_x = np.array((1.0, 1.0))
np.testing.assert_array_almost_equal(x, expected_x)
self.assertIn('norm(dx) < tol', out.getvalue())
self.assertIn('norm(gradient) < tol', out.getvalue())
self.assertIn('Jacobian matches', out.getvalue())
# Try with bad Jacobian, ask least_squares to check it.
@@ -116,7 +115,7 @@ class MinimizeTest(absltest.TestCase):
x0, residual, bounds=bounds_types['inbounds'], output=out
)
np.testing.assert_array_almost_equal(x, expected_x)
self.assertIn('norm(dx) < tol', out.getvalue())
self.assertIn('norm(gradient) < tol', out.getvalue())
# Test different bounds conditions.
for bounds in bounds_types.values():