Running Solves
The pounce command-line driver solves built-in TNLPs and AMPL .nl
files. Its console output mirrors upstream ipopt’s banner,
per-iteration table, and final summary, so anyone used to reading
ipopt logs can read pounce logs unchanged.
Basic usage
pounce problem.nl
pounce problem.nl print_level=8 max_iter=500 tol=1e-10
pounce problem.nl linear_solver=ma57 # with --features ma57
pounce problem.nl --options-file tuned.opt # upstream-format options file
pounce problem.nl option_file_name=tuned.opt # the Ipopt spelling; same thing
pounce problem.nl --no-options-file # ignore ./pounce.opt, ./ipopt.opt
Trailing KEY=VALUE pairs follow the same syntax and semantics as the
upstream Ipopt CLI; they override values loaded from the options file.
With no options file named, ./pounce.opt or ./ipopt.opt is read if
present, as ipopt reads ./ipopt.opt. See
Solver Options.
Built-in problems
pounce --list-problems
pounce --problem quadratic
pounce --problem rosenbrock
quadratic—min (x[0]-3)² + (x[1]-4)²(unconstrained, optimum(3, 4)).rosenbrock—min 100·(x[1]-x[0]²)² + (1-x[0])²(unconstrained, optimum(1, 1)).bounded-quadratic—quadraticwith box bounds0 ≤ x ≤ 2(optimum at the upper corner(2, 2)).eq-quadratic—min x[0]² + x[1]²s.t.x[0] + x[1] = 1(a single equality).circle—min x[0]s.t.x[0]² + x[1]² = 1(a nonlinear equality).infeasible-eq— two contradictory equalities (x[0]+x[1]=1and=2); exercises the infeasibility-detection path.
Run pounce --list-problems for the authoritative list.
Built-in problems have no .nl stub, so they only write a .sol file
when --sol-output is given explicitly.
Degenerate / MPCC NLPs — the ℓ₁-exact penalty-barrier wrapper
For problems where the standard IPM thrashes in restoration because LICQ fails at the iterate (degenerate equalities, MPCC-like complementarity), enable the Thierry–Biegler ℓ₁-exact penalty-barrier wrapper:
pounce problem.nl l1_exact_penalty_barrier=yes
The wrapper turns every equality row c_i(x) = g_i into a
slack-relaxed c_i(x) − p_i + n_i = g_i with (p_i, n_i) ≥ 0,
augments the objective by ρ · Σ(p + n), and runs a
Byrd–Nocedal–Waltz outer loop that escalates ρ until the slacks
collapse (constraints satisfied) or saturate (locally infeasible
problem detected). The user-visible (x*, λ*) are reported in the
original variable space.
For everyday use, the simpler form is an auto-fallback:
pounce problem.nl l1_fallback_on_restoration_failure=yes
POUNCE first runs the standard solve. If it terminates in
Restoration_Failed, Infeasible_Problem_Detected,
Solved_To_Acceptable_Level, Maximum_Iterations_Exceeded, or
Not_Enough_Degrees_Of_Freedom, the wrapper is invoked transparently
and the result is promoted to Solve_Succeeded only if the retry
succeeds. Otherwise the original status is preserved.
The tuning knobs are listed under Solver Options.
AMPL / Pyomo solver mode
AMPL drivers — and Pyomo’s ASL interface — invoke a solver as
solver problem.nl -AMPL. Pass -AMPL to run pounce that way:
pounce problem.nl -AMPL
It changes nothing about the solve itself; it switches the process to
the AMPL exit-code contract (see below), so the driver reads the
termination from the .sol file rather than the exit status. The
pyomo-pounce package builds on top of this mode.
Dual sign conventions
Two different quantities are in play, and they differ by a sign. Getting them confused is easy, so pounce names them differently:
| Surface | Quantity | Meaning |
|---|---|---|
.sol dual block, Pyomo model.dual | marginal | d obj / d b — the shadow price |
mult_g (Python API, JSON solution.lambda) | Lagrange multiplier | the λ of L = f + λ'g − z_L(x−x_L) + z_U(x−x_U) |
They are related by marginal = −λ. The .sol writer performs this
negation, so a .sol (and therefore Pyomo’s model.dual) carries shadow
prices with the same sign Ipopt, glpk, CBC and CONOPT report. For
min x₀²+x₁² s.t. x₀+x₁ = b the optimum is b²/2, so a .sol written at
b = 2 reports +2.
The Python API’s mult_g keeps the Lagrange-multiplier convention, which
matches cyipopt and satisfies the stationarity identity above directly.
If you are comparing a mult_g against a model.dual for the same solve,
expect them to differ by a sign — that is by design, not a bug.
Before v0.9.1 the
.solwriter emitted the Lagrange multiplier without converting it, so every AMPL/Pyomo dual came back negated relative to every other solver (#271). Objectives and primal solutions were never affected.
Exit codes
0—Solve_Succeeded(orSolved_To_Acceptable_Level).- non-zero — any other
ApplicationReturnStatus.
In AMPL solver mode (-AMPL) the exit code instead follows the AMPL
contract: 0 for any solve that ran and produced a .sol file —
limit-reached, infeasible, even a failed solve — since the termination
is carried by the file’s solve_result_num. Genuine startup failures
(unreadable .nl, bad option) still exit non-zero.
Diagnostics & introspection
pounce --about # version, build info, features, backends
pounce problem.nl --dump kkt:5-10 --dump iterate # dump per-iteration diagnostics
pounce problem.nl --dump kkt --dump-dir /tmp/d # override the dump root
--about— print version, build info, enabled features, and linear-solver backends, then exit.--dump <cat>[:<spec>]— write the diagnostic category to per-iteration files (JSONL). Wired categories arekktanditerate; an optional:<spec>selects iterations (e.g.kkt:5,kkt:2-10,iterate:all).--dump-dir <path>— override the dump root (default./pounce-dump-<timestamp>).--dump-format <fmt>— dump format (defaultjsonl).
Help
pounce --help
pounce --version # also -v, -V