Add zero-iteration early exit to the primal solvers, certified by the duality gap.

The primal cost has curvature of at least M in every zone, making it strongly
convex in the M-norm and bounding the suboptimality of any point by the
Fenchel duality gap at its constraint forces:

  cost(qacc) - cost* <= 0.5*grad'*M^-1*grad

Since M's factorization always exists, this certificate is evaluable before
the solver does any work: one triangular solve and one dot product. When the
warmstarted solution is already certified to satisfy the tolerance, CG and
Newton now return with zero iterations; for Newton this skips building and
factorizing the Hessian. If the certificate declines, Newton gets a second
exit after factorization: the Newton decrement, checked before the first
line search.

Because the gap bounds cost suboptimality, stiff constraints can convert it
into force errors of order sqrt(2*gap*stiffness). Newton solutions are
characteristically force-accurate, so Newton zero-iteration exits also
require the gradient criterion, preserving constraint-force accuracy at
rest; CG solutions are characteristically cost-accurate and exit on the gap
alone.

On a settling pile of 50 boxes (300 dofs, ~200 contacts), end-to-end time
per step drops 13% over a settle-then-rest run and 27% in the quiescent
limit, with Newton iterations falling from 0.98 to 0.40 per step.

Tests: WarmstartZeroIterations sweeps solver/cone/jacobian on a settled box,
asserting zero iterations, forward/inverse consistency, and agreement with a
tolerance=0 control solve from the same state. WarmstartZeroIterationsIslands
checks per-island exits with a kicked box next to a settled one.
RefsiteConservesMomentum now requests an exact solve (tolerance=0), since it
asserts momentum conservation tighter than the solver tolerance contract.
PiperOrigin-RevId: 947993735
Change-Id: I2fd855774bff619709b2c386f1ba2714286e0821
This commit is contained in:
Yuval Tassa
2026-07-14 17:23:26 -07:00
committed by Copybara-Service
parent 1e66efd114
commit c69ef03083
6 changed files with 211 additions and 23 deletions
+7 -4
View File
@@ -418,9 +418,10 @@ adjust it properly through the XML.
:at:`iterations`: :at-val:`int, "100"`
Maximum number of iterations of the constraint solver. When the warmstart attribute of :ref:`flag <option-flag>` is
enabled (which is the default), accurate results are obtained with fewer iterations. Larger and more complex systems
with many interacting constraints require more iterations. Note that mjData.solver contains statistics about solver
convergence, also shown in the profiler.
enabled (which is the default), accurate results are obtained with fewer iterations; if the warmstarted solution
already satisfies the tolerance, the CG and Newton solvers terminate with zero iterations. Larger and more complex
systems with many interacting constraints require more iterations. Note that mjData.solver contains statistics about
solver convergence, also shown in the profiler.
.. _option-tolerance:
@@ -428,7 +429,9 @@ adjust it properly through the XML.
Tolerance threshold used for early termination of the iterative solver. For PGS, the threshold is applied to the cost
improvement between two iterations. For CG and Newton, it is applied to the smaller of the cost improvement and the
gradient norm. For Newton, it is additionally applied to the Newton decrement :math:`\tfrac{1}{2} g^T H^{-1} g`, the
predicted cost improvement of the next iteration. Set the tolerance to 0 to disable early termination.
predicted cost improvement of the next iteration. Before the first iteration, CG and Newton also apply it to a
:ref:`convergence certificate<soAlgorithms>` of the warmstarted solution, possibly terminating with zero iterations.
Set the tolerance to 0 to disable early termination.
.. _option-ls_iterations:
+5
View File
@@ -13,6 +13,11 @@ General
early-termination criterion of the :ref:`Newton solver<soAlgorithms>`, alongside cost improvement and gradient norm.
This reduces iteration counts at no accuracy cost. Proposed by :github:user:`adenzler-nvidia` in
:doc:`MJWarp <mjwarp/index>` pull request `1520 <https://github.com/google-deepmind/mujoco_warp/pull/1520>`__.
- The CG and Newton solvers now terminate with zero iterations when a duality-gap certificate proves that the
warmstarted solution already satisfies the tolerance. The certificate requires only the existing mass-matrix
factorization, so quiescent scenes skip Hessian construction, factorization and the line search entirely. Newton
zero-iteration exits additionally require the gradient criterion, preserving Newton's characteristic force-level
accuracy. See :ref:`Warmstart<soAlgorithms>` in the Computation chapter for details.
- :ref:`mj_encode` now supports encoding of MJB and TXT files.
- :ref:`mj_setConst` now recomputes the ``mjModel.{body,geom,site}_sameframe`` flags, to account for changes in
body/geom/site frames after compilation.
+8
View File
@@ -1445,6 +1445,14 @@ representations of the constraint Jacobian and related matrices.
bootstraps the solver when constraints persist across time steps, but avoids carrying over stale forces from
constraints that have disappeared.
Because every zone of the piecewise-quadratic cost has curvature of at least :math:`M`, the cost is strongly convex
in the :math:`M`-norm, which bounds the suboptimality of any point by the duality gap at its constraint forces:
:math:`\text{cost}(a) - \text{cost}^* \le \tfrac{1}{2} g^T M^{-1} g`. Before starting iterations, the CG and Newton
solvers evaluate this certificate at the warmstarted point, using the already-computed factorization of
:math:`M`. If it is below tolerance, convergence is proven and the solver returns immediately with zero iterations;
in the Newton case this skips constructing and factorizing the Hessian. In a quiescent, well-warmstarted scene this
eliminates nearly the entire cost of the constraint solver.
.. _soIsland:
Constraint islands
+4 -3
View File
@@ -1105,9 +1105,10 @@ does not need timing, and in that case there is no reason to call timing functio
One part of the simulation pipeline that needs to be monitored closely is the iterative constraint solver. The
simplest diagnostic here is ``mjData.solver_niter`` which shows how many iterations the solver took on the last call to
mj_step or ``mj_forward``. Note that the solver has tolerance parameters for early termination, so this number is
usually smaller than the maximum number of iterations allowed. The array ``mjData.solver`` contains one
:ref:`mjSolverStat` data structure per iteration of the constraint solver, with information about the constraint state
and line search.
usually smaller than the maximum number of iterations allowed; it can be 0 when a warmstarted solution is already
certified as converged, in which case no iterations are performed and no statistics are written. The array
``mjData.solver`` contains one :ref:`mjSolverStat` data structure per iteration of the constraint solver, with
information about the constraint state and line search.
When the option :at:`fwdinv` is enabled in ``mjModel.opt.enableflags``, the field ``mjData.fwdinv`` is also populated.
It contains the difference between the forward and inverse dynamics, in terms of generalized forces and constraint