API Reference
Index
DFMethods.HISTORY_FIELDSDFMethods.AbsResidualTolDFMethods.AbstractCallbackDFMethods.AbstractConstraintSetDFMethods.AbstractDFProjectionDFMethods.AbstractInertialRuleDFMethods.AbstractIterateUpdateDFMethods.AbstractSearchDirectionDFMethods.AbstractStoppingCriterionDFMethods.AdaptiveClampedBacktrackDFMethods.AnyOfDFMethods.BoxSetDFMethods.CappedBoxDFMethods.ConstantBacktrackDFMethods.ConstrainedNonlinearProblemDFMethods.DFProjectionDFMethods.DFProjectionCacheDFMethods.DFSciMLCacheDFMethods.DirectUpdateDFMethods.DirectionNormTolDFMethods.HalfSpaceDFMethods.HalpernUpdateDFMethods.HistoryCallbackDFMethods.InertialDFMethods.IntersectionDFMethods.LoggingCallbackDFMethods.MaxFEvalsDFMethods.MaxItersDFMethods.MaxTimeDFMethods.NoInertialDFMethods.RealSpaceDFMethods.RelResidualTolDFMethods.ResidualNormBacktrackDFMethods.SolodovSvaiterProjectionDFMethods.SpectralThreeTermDFMethods.StepNormTolDFMethods.UserSetDFMethods.UserStopCommonSolve.initCommonSolve.solve!CommonSolve.step!DFMethods.apply_inertial!DFMethods.approx_project_X_halfspace!DFMethods.direction!DFMethods.inertial_coefDFMethods.init_cacheDFMethods.init_stateDFMethods.on_event!DFMethods.projectDFMethods.project!DFMethods.update_iterate!
Problem types
DFMethods.ConstrainedNonlinearProblem — Type
ConstrainedNonlinearProblem(inner::NonlinearProblem, set::AbstractConstraintSet)
ConstrainedNonlinearProblem(f, u0, p = NullParameters();
set::AbstractConstraintSet,
lb = nothing, ub = nothing, kwargs...)Wraps a SciMLBase.NonlinearProblem with a feasibility set the algorithm must respect. The constraint becomes part of the problem (where it belongs), not the algorithm — so one DFProjection instance solves many problems with different feasibility sets.
Use this for non-box constraints (HalfSpace, CappedBox, Intersection, UserSet). For pure box constraints, prefer NonlinearProblem(f, u0; lb, ub) directly — SciMLBase's native support.
A standard SciMLBase.NonlinearProblem covers unconstrained problems and box-constrained problems (via prob.lb / prob.ub). ConstrainedNonlinearProblem wraps a NonlinearProblem together with an AbstractConstraintSet for arbitrary closed convex feasible sets.
Algorithm types
DFMethods.AbstractDFProjection — Type
AbstractDFProjectionSupertype for all derivative-free projection algorithms in DFMethods. Concrete subtypes (e.g., DFProjection in algorithm.jl) wire together a search direction, a line search, an inertial rule, and a constraint set.
Subtypes SciMLBase.AbstractNonlinearAlgorithm, so every concrete algorithm participates in solve(prob::NonlinearProblem, alg; kwargs...) out of the box.
Convergence assumptions (e.g., monotonicity of $F$, closed convex $X$) are documented on the Algorithm page of the manual. The library does not enforce them at runtime — algorithms iterate regardless and either converge or terminate via a stopping criterion.
DFMethods.DFProjection — Type
DFProjection(; direction, linesearch, inertial, iterate_update,
abstol, reltol, maxiters, maxtime, stopping, ζ,
inner_maxiter, maxbt, callbacks)Concrete derivative-free projection algorithm with pluggable components. The constraint set lives on the problem, not on the algorithm — see ConstrainedNonlinearProblem and the lb/ub keywords of NonlinearProblem.
Fields
direction::AbstractSearchDirection— search-direction rule. Default:SpectralThreeTerm().linesearch::LineSearch.AbstractLineSearchAlgorithm— line search. Default:ResidualNormBacktrack().inertial::AbstractInertialRule— inertial rule. Default:Inertial(0.25).iterate_update::AbstractIterateUpdate— post-line-search iterate update strategy. Default:SolodovSvaiterProjection(). Alternatives:DirectUpdate(),HalpernUpdate(β).abstol::Float64— absolute residual tolerance used to build the default stopping. Default:1e-6.reltol::Float64— relative residual tolerance (target‖F(z_k)‖ ≤ reltol·‖F(x_0)‖) used to build the default stopping.0disables it. Default:0.0.maxiters::Int— outer-iteration cap used to build the default stopping. Default:2000.maxtime::Float64— wall-clock budget in seconds used to build the default stopping.Infdisables it. Default:Inf.stopping::AbstractStoppingCriterion— full stopping rule. If not supplied, built from the knobs above asAnyOf(AbsResidualTol(abstol)[, RelResidualTol(reltol)], MaxIters(maxiters)[, MaxTime(maxtime)])— the bracketed criteria appear only whenreltol > 0/maxtimeis finite.ζ::Float64— approximate-projection tolerance factor used bySolodovSvaiterProjection. Default:0.5.inner_maxiter::Int— max inner-projection iterations (Dykstra). Default:500.maxbt::Int— max line-search backtracks per iteration. Default:50.callbacks::Vector{<:AbstractCallback}— observer callbacks fired during the solve. Default: empty.
Stopping criteria
abstol, reltol, maxiters, and maxtime are convenience knobs that build the default stopping rule (mirroring the SciML common-solver options of the same name). For composite or domain-specific criteria, pass stopping = AnyOf(StepNormTol(...), DirectionNormTol(...), …); the knob fields are still stored (for introspection and SciMLBase kwarg overrides) but step! ignores them in favour of the supplied stopping. When a stopping rule is supplied explicitly, solve-time tolerance keywords (abstol/reltol/maxiters/maxtime) cannot be re-applied and are reported via a verbose warning.
DFMethods.DFProjectionCache — Type
DFProjectionCache{T, Alg, F, S, DirState, LSCache, IUpState, StopState}Mutable per-solve state. Created via init_cache(F, x0, alg). All per-iteration buffers are pre-allocated; step! does not allocate.
Parametric on element type T <: AbstractFloat, derived from eltype(x0) (or Float64 if eltype(x0) is non-floating, e.g. Int).
Common state (vectors)
x,x_prev,w,w_prev,z,d,d_prev— iteration vectors,Vector{T}.Fw,Fw_prev,Fz— function values,Vector{T}.x_new,scratch1— generic scratch,Vector{T}.
Pluggable component state (typed via parameters)
direction_state::DirState—init_state(alg.direction, ...). Defaultnothing.line_search_cache::LSCache— populated by the line-search component. Defaultnothing(Stage 2 transition state; filled by Stage 3 once LineSearch.jl is adopted).iterate_update_state::IUpState—init_state(...)for the iterate-update strategy. In Stage 2 this is always aSolodovSvaiterState(holding the projection scratch and Dykstra buffers).stopping_state::StopState—init_state(alg.stopping, ...). Defaultnothing.
Common scalars
k::Int— iteration counter (0-based).n_evals::Int— total F evaluations.converged::Bool,done::Bool,retcode::Symbol,resid::T.F0_norm::T—‖F(x_0)‖, used byRelResidualTol.t_start::Float64— wall-clock seconds at solve start (forMaxTime).α_prev::T— previous line-search step size, surfaced todirection!viactx.α_prev.
Solving
DFMethods.init_cache — Function
init_cache(F, x0, alg) -> DFProjectionCacheAllocate per-solve buffers and prepare the initial state. Projects x0 onto set to ensure the feasibility invariant x_0 ∈ X. Evaluates F once at the projected x_0 to populate F0_norm (used by RelResidualTol) and starts the wall-clock for MaxTime.
The internal DFMethods.step!(::DFProjectionCache) advances one outer iteration on the inner cache and is used by CommonSolve.step! below. User-level driving goes through solve(prob, alg) or the init / step! / solve! triplet documented under SciML integration.
SciML integration
DFMethods.DFSciMLCache — Type
DFSciMLCacheWrapper cache returned by CommonSolve.init(prob, alg; …). Carries the original NonlinearProblem, the user-facing algorithm, the inner Phase 2 DFProjectionCache, and the resolved verbose flag (used by solve! to decide whether to warn on a non-Success exit). CommonSolve.solve! drives the inner cache to termination and packages the result as a NonlinearSolution.
CommonSolve.init — Method
CommonSolve.init(prob::NonlinearProblem, alg::DFProjection;
abstol, reltol, maxiters, maxtime, verbose, kwargs...)
-> DFSciMLCacheBuild a cache for solve(prob, alg; …). Honors the SciML common-solver options that map onto DFMethods' callback-based stopping system:
abstol→AbsResidualTol(abstol)reltol→RelResidualTol(reltol)(target‖F(z_k)‖ ≤ reltol·‖F(x_0)‖)maxiters→MaxIters(maxiters)maxtime→MaxTime(maxtime)seconds (nothing⇒ no limit)verbose→ toggles the non-convergence warning emitted bysolve!
Each defaults to the matching field on alg; any that is supplied overrides it by rebuilding the default stopping rule. If alg was built with an explicit stopping=, these tolerance keywords cannot be applied and (when verbose) a warning is emitted.
All other SciML common-solver keywords — termination_condition, internalnorm, alias_u0, show_trace, store_trace, trace_level — are accepted and absorbed without error. DFMethods uses its own callback-based termination and the Euclidean residual norm, so solve(prob, ::DFProjection; any_standard_kwarg…) never throws.
CommonSolve.step! — Method
CommonSolve.step!(cache::DFSciMLCache) -> cacheAdvance the inner cache by one outer iteration of the algorithm. No-op if the inner cache has already terminated. Returns the wrapper cache so calls chain.
Usage:
using NonlinearSolve, DFMethods
cache = init(prob, alg)
while !cache.inner.done
step!(cache)
end
sol = solve!(cache)For batched runs, solve(prob, alg) (or equivalently solve!(init(prob, alg))) is the higher-level entry point that handles the loop internally.
CommonSolve.solve! — Method
CommonSolve.solve!(cache::DFSciMLCache) -> NonlinearSolutionDrive the inner cache to termination, then build and return a SciMLBase.NonlinearSolution.
Search directions
DFMethods.AbstractSearchDirection — Type
AbstractSearchDirectionSupertype for search-direction rules. Concrete subtypes implement the single 3-argument method
direction!(d, rule, ctx)where the output direction d is written in place and ctx is a NamedTuple carrying the per-iteration cache state. The vector fields alias into the DFProjectionCache buffers, parametric on element type T, where T = eltype(x0) <: AbstractFloat (with Float64 fallback if eltype(x0) is not floating). The fields are:
| Field | Type | Description |
|---|---|---|
ctx.Fw | Vector{T} | $F$ at the inertial point $w_k$ |
ctx.Fw_prev | Vector{T} | $F$ at the previous inertial point $w_{k-1}$ |
ctx.w | Vector{T} | inertial point $w_k$ |
ctx.w_prev | Vector{T} | previous inertial point $w_{k-1}$ |
ctx.d_prev | Vector{T} | previous direction $d_{k-1}$ |
ctx.k | Int | iteration index (0-based) |
ctx.α_prev | T | previous line-search step $\alpha_{k-1}$; one(T) at k = 0 |
A rule that doesn't need a given field simply ignores it. New cache fields can be added in future versions without breaking existing direction methods — they will just be unused by older code.
For ctx.k == 0, only ctx.Fw is meaningful; the other fields may be uninitialized. Rules typically set d = -Fw at k = 0.
The convergence theory for this class of algorithms requires sufficient descent (-Fw' d ≥ c‖Fw‖²) and boundedness (‖d‖ ≤ c̄‖Fw‖). It is the rule author's responsibility to ensure these hold.
DFMethods.SpectralThreeTerm — Type
SpectralThreeTerm(; r=0.1, alpha_bar=1.0, alpha_min=1e-10, alpha_max=1e30)Spectral three-term derivative-free direction. The formula is:
d_0 = -F(w_0)
d_k = -ϑ_k^I · F(w_k) + β_k · d_{k-1} - ϑ_k^II · y_{k-1} (k ≥ 1)with
y_{k-1} = F(w_k) - F(w_{k-1})
s_{k-1} = (w_k - w_{k-1}) + r · y_{k-1}
ϑ_k^I = clamp((s_{k-1}' y_{k-1}) / (y_{k-1}' y_{k-1}), alpha_min, alpha_max)
v_k = max(alpha_bar · ‖d_{k-1}‖ · ‖y_{k-1}‖, ‖F(w_{k-1})‖²)
β_k = (F(w_k)' y_{k-1}) / v_k
ϑ_k^II = (F(w_k)' d_{k-1}) / v_kIn the degenerate case y_{k-1} = 0, $ϑ_k^I$ falls back to alpha_min, preserving the strict-descent property $F(w_k)' d_k ≤ -\alpha_{\min} \, \|F(w_k)\|^2$.
The uniform bound alpha_min ≤ ϑ_k^I ≤ alpha_max is what underwrites the sufficient-descent and trust-region properties of this class of algorithms.
Parameters
r: spectral parameter in the definition ofs_{k-1}(default 0.1).alpha_bar: the parameter $\bar{α}_1$ in the definition ofv_k(default 1.0).alpha_min: lower clamp on the spectral coefficient $ϑ_k^I$ (default1e-10); also the degenerate-case fallback.alpha_max: upper clamp on the spectral coefficient $ϑ_k^I$ (default1e30).
DFMethods.direction! — Function
direction!(d, rule, ctx)In-place compute $d = d_k$ per rule. See AbstractSearchDirection for the ctx NamedTuple shape.
Line searches
DFMethods.ConstantBacktrack — Type
ConstantBacktrack(; σ=0.01, ρ=0.6, maxbt=50)Backtracking line search with γ_k ≡ 1 — Armijo's classical form.
DFMethods.ResidualNormBacktrack — Type
ResidualNormBacktrack(; σ=0.01, ρ=0.6, maxbt=50)Backtracking with γ_k = ‖F(z_k)‖. Default line search for DFProjection().
DFMethods.AdaptiveClampedBacktrack — Type
AdaptiveClampedBacktrack(; σ=0.01, ρ=0.6, lo=1e-4, Δ_init=10.0, maxbt=50)Backtracking with γ_k = clamp(‖F(z_k)‖, lo, lo + Δ). The Δ upper-bound range is held on the cache (mutable; could adapt across solves in a future extension; not currently updated).
Each is a subtype of LineSearch.AbstractLineSearchAlgorithm (from LineSearch.jl) and implements the standard CommonSolve.init / CommonSolve.solve! contract. User-defined line searches obey the same contract.
Iterate-update strategies
DFMethods.AbstractIterateUpdate — Type
AbstractIterateUpdateSupertype for the iterate-update strategy: given the inputs (w, d, α, z, Fw, Fz, set, k, ζ, inner_maxiter, state), produce x_{k+1}. Concrete subtypes implement
update_iterate!(x_new, rule::AbstractIterateUpdate, ctx)writing into x_new and returning it. ctx is a NamedTuple; see SolodovSvaiterProjection, DirectUpdate, and HalpernUpdate for built-in strategies.
The strategy may declare its per-solve state via init_state(rule, prob, x0, alg). The state is held on DFProjectionCache.iterate_update_state and surfaced to update_iterate! via ctx.state.
DFMethods.SolodovSvaiterProjection — Type
SolodovSvaiterProjection(; γ = 1.0)Default iterate-update strategy. Implements the hyperplane projection scheme of Solodov & Svaiter (1999): given the trial point z with residual F(z), construct the separating hyperplane H_k = {x : F(z)' (x − z) ≤ 0} and project the target w − γ·λ_k F(z) onto X ∩ H_k to tolerance ε_k = (ζ²/2) ‖γ·λ_k F(z)‖² = (ζ²/2) γ² λ_k² ‖F(z)‖².
The 1999 scheme assumes exact projection onto X ∩ H_k. DFMethods realizes it through the inexact-projection refinement standard in the broader Solodov–Svaiter inexact-projection lineage: a Dykstra inner loop terminated at the tolerance ε_k above (driven by approx_project_X_halfspace!). For X = RealSpace the inner solver collapses to a single exact halfspace projection regardless of ε_k.
The relaxation factor γ ∈ (0, 2) controls the step length past the separating hyperplane. The convergence bound for this family carries a factor of γ(2 − γ) (maximized at γ = 1); some derivative-free projection methods set γ larger (e.g. 1.6–1.8) to trade theoretical contraction for empirical speed on test problems.
Parameters
γ::Float64 = 1.0: relaxation factor; must lie in(0, 2).
Caveat on under-relaxation (γ < 1)
For X = RealSpace the target w − γ·λ·F(z) with γ < 1 lies on the strict-violation side of H_k; the exact halfspace projection then brings it back to the boundary, recovering the γ = 1 iterate. In short, γ ≤ 1 cancels in RealSpace. The relaxation has effect for γ > 1 (target sits inside H_k, projection no-op) and for non-trivial X (joint projection onto X ∩ H_k is shaped by both constraints). The ε_k tolerance is scaled by γ² so Dykstra stops to a constant fractional accuracy of the projection step regardless of γ.
DFMethods.DirectUpdate — Type
DirectUpdate()Stateless update: x_{k+1} = project(z, set). Simplest possible scheme — take the trial point and project it onto the feasible set. Useful as a baseline for comparison and as a building block in higher-level methods.
DFMethods.HalpernUpdate — Type
HalpernUpdate(β)Halpern-style averaging with feasibility maintenance:
x_{k+1} = P_X(β · x_0 + (1 − β) · z_k)where P_X is projection onto the problem's feasibility set X. The trial point z_k = w_k + α_k d_k is generally infeasible, so the final projection is required to maintain the framework invariant x_k ∈ X.
The parameter β is either a scalar (constant across iterations) or a callable β(k) -> Float64 (per-iteration schedule, e.g. k -> 1 / (k + 2) for the classical schedule with strong convergence to the nearest fixed point).
Reference
Halpern, B. (1967). Fixed Points of Nonexpanding Maps. Bulletin of the AMS 73(6): 957–961. doi:10.1090/S0002-9904-1967-11864-0.
DFMethods.update_iterate! — Function
update_iterate!(x_new, rule::AbstractIterateUpdate, ctx) -> x_newIn-place: write the next iterate into x_new per rule's logic. ctx is a NamedTuple with fields w, d, α, z, Fw, Fz, set, k, ζ, inner_maxiter, state. See AbstractIterateUpdate.
DFMethods.init_state — Function
init_state(component, prob, x0, alg) -> stateAllocate per-solve state for a pluggable algorithm component (search direction, line search, iterate-update strategy, stopping criterion). The returned state is held on DFProjectionCache in the slot matching the component's role. Components that are stateless (e.g. SpectralThreeTerm) return nothing; components that need per-iteration scratch (e.g. the default Solodov–Svaiter iterate-update strategy with its Dykstra buffers) return a small struct holding their allocations.
Default: nothing. Concrete components override.
This is an internal helper (not exported). The DFProjectionCache constructor calls it once per pluggable component during init_cache.
Inertial rules
DFMethods.AbstractInertialRule — Type
AbstractInertialRuleSupertype for inertial-extrapolation rules. A rule produces the inertial coefficient $θ_k$ from the iteration index, current iterate, and previous iterate. The inertial point is then
w_k = x_k + θ_k (x_k - x_{k-1}).DFMethods.Inertial — Type
Inertial(θ = 0.25)Standard summable-step inertial-extrapolation rule:
θ_k = min(θ, 1 / (k² · ‖x_k - x_{k-1}‖)) if x_k ≠ x_{k-1}
θ otherwiseθ ∈ (0, 1); 0.25 is a common default value in the literature.
The 1/k² cap ensures $\sum_k θ_k \|x_k - x_{k-1}\| \le \sum_k 1/k^2 < ∞$, which is the summability condition that drives the convergence proof for inertial schemes of this class. Lineage: Alvarez & Attouch (2001) introduced the heavy-ball / inertial idea for monotone operators; Maingé (2008) gave the modern form for inertial KM-type algorithms; the specific 1/k² cap used here is the form adopted by recent derivative-free projection methods.
julia> Inertial().θ
0.25
julia> Inertial(0.4).θ
0.4
julia> inertial_coef(Inertial(0.25), 0, [1.0], [0.0]) # k=0: no inertia
0.0DFMethods.NoInertial — Type
NoInertial()Disables inertia: $w_k = x_k$. Useful for ablation comparisons against the inertial variant.
julia> inertial_coef(NoInertial(), 5, [1.0, 2.0], [0.0, 1.0])
0.0DFMethods.inertial_coef — Function
inertial_coef(rule, k, xk, xkm1) -> θ_k::Float64Compute the inertial coefficient. k is the iteration index (0-based); xk is the current iterate; xkm1 is the previous iterate.
DFMethods.apply_inertial! — Function
apply_inertial!(w, rule, k, xk, xkm1) -> (w, θ_k)Compute $w = x_k + θ_k (x_k - x_{k-1})$ in place, returning $θ_k$ too.
Callbacks
DFMethods.AbstractCallback — Type
AbstractCallbackSupertype for solve-time callbacks. Implement on_event!(cb, cache, event::Symbol) to observe state at specific lifecycle events. Default behavior: observe-only (return nothing).
Stopping criteria are a special case — see AbstractStoppingCriterion, which subtypes AbstractCallback and returns (stopped::Bool, retcode::Symbol) from on_event! to signal termination.
Events fired in v0.2:
| Event | Where it fires |
|---|---|
:initialize | Once, at end of init_cache |
:post_linesearch | After the line search; cache.Fz is fresh |
:post_iter | After the state shift; cache.k incremented |
:terminate | Once, on any termination |
The minimal 4-event set is intentional. More events (:pre_iter, :post_direction, :post_iterate_update) may be added in a future release if real need emerges.
DFMethods.on_event! — Function
on_event!(cb, cache, event::Symbol)Called by the algorithm at each instrumented lifecycle event. For AbstractCallback subtypes that observe only (e.g. HistoryCallback, LoggingCallback), return value is ignored. For AbstractStoppingCriterion subtypes, return (stopped::Bool, retcode::Symbol).
Default (observer): nothing.
DFMethods.HistoryCallback — Type
HistoryCallback(; fields = HISTORY_FIELDS)
HistoryCallback(extractor::Function)Per-iteration history accumulator. Two constructor paths:
- Pre-declared field names (the common case): pick any subset of
HISTORY_FIELDS. Each iter,on_event!(cb, cache, :post_iter)appends a NamedTuple with those fields tocb.history. - Custom extractor:
HistoryCallback(extractor = cache -> NamedTuple)bypassesfieldsand uses the user's function to produce each row. Useful for derived quantities (e.g.max(abs, F), condition numbers).
Constructor errors if both fields and extractor are supplied.
Example
hist = HistoryCallback(fields = (:k, :F_norm))
sol = solve(prob, DFProjection(callbacks = [hist]))
hist.history # Vector{NamedTuple} with .k and .F_norm per rowDFMethods.LoggingCallback — Type
LoggingCallback(; io = stdout, columns = HISTORY_FIELDS, every = 1,
header_every = 50, footer = true)Per-iteration table logger. Prints:
- A header row at
:initialize - One row per iteration at
:post_iter, respectingevery(1 = every iter, 10 = every 10th iter) - Header re-prints every
header_everyrows (set to0to disable) - A footer summary at
:terminate(skip viafooter = false)
DFMethods.HISTORY_FIELDS — Constant
HISTORY_FIELDSAvailable scalar fields for HistoryCallback and the default column set for LoggingCallback.
| Field | Meaning |
|---|---|
:k | Outer iteration index |
:F_norm | ‖F(z_k)‖ (residual at last trial point) |
:d_norm | ‖d_k‖, current search direction |
:α | Last accepted line-search step α_k |
:n_evals | Cumulative F evaluations |
:resid | cache.resid (NaN until set at termination) |
:elapsed | Wall-clock seconds since solve start |
julia> HISTORY_FIELDS
(:k, :F_norm, :d_norm, :α, :n_evals, :resid, :elapsed)Stopping criteria
DFMethods.AbstractStoppingCriterion — Type
AbstractStoppingCriterion <: AbstractCallbackSupertype for stopping criteria. Concrete subtypes implement on_event!(crit, cache, event::Symbol) -> (Bool, Symbol) for the events they care about.
The default fallback returns (false, :Default) — i.e., never stops. Concrete criteria override on_event! for their relevant event(s).
DFMethods.AbsResidualTol — Type
AbsResidualTol(abstol)Stop when $\|F(z_k)\| \le \text{abstol}$ (post line search). Retcode :Success.
DFMethods.RelResidualTol — Type
RelResidualTol(rtol; abstol=0)Stop when $\|F(z_k)\| \le \text{abstol} + \text{rtol} \cdot \|F(x_0)\|$ (post line search). Retcode :Success.
DFMethods.StepNormTol — Type
StepNormTol(xtol)Stop when $\|x_k - x_{k-1}\| \le \text{xtol}$ at end of iteration. Catches stalls. Retcode :Stalled.
DFMethods.DirectionNormTol — Type
DirectionNormTol(dtol)Stop when $\|d_k\| \le \text{dtol}$. Retcode :Stalled. Pair with AbsResidualTol (via AnyOf) for a complete picture — a vanishing direction is not the same as a vanishing residual.
DFMethods.MaxIters — Type
MaxIters(maxiters)Stop when cache.k >= maxiters. Retcode :MaxIters.
DFMethods.MaxTime — Type
MaxTime(maxtime)Stop when elapsed wall-clock time exceeds maxtime seconds. Retcode :MaxTime.
DFMethods.MaxFEvals — Type
MaxFEvals(maxevals)Stop when total function evaluations reach maxevals. Retcode :MaxFEvals.
DFMethods.UserStop — Type
UserStop(f)User-supplied predicate. f(cache) -> (stopped::Bool, retcode::Symbol). Called at :post_iter by default.
DFMethods.AnyOf — Type
AnyOf(criteria...)Composite criterion: stops when any constituent stops. Delegates each event to all sub-criteria in declaration order; the first to fire wins and its retcode propagates.
Constraint sets and projections
DFMethods.AbstractConstraintSet — Type
AbstractConstraintSetSupertype for all constraint sets. Concrete subtypes implement project!(y, x, set) that writes the orthogonal projection of x onto the set into y and returns y.
DFMethods.RealSpace — Type
RealSpace()The whole of $\mathbb{R}^n$ — projection is the identity. Use to disable constraints (e.g., for unconstrained comparison with NonlinearSolve.jl's SimpleDFSane).
julia> project([1.0, -2.0, 3.0], RealSpace())
3-element Vector{Float64}:
1.0
-2.0
3.0DFMethods.BoxSet — Type
BoxSet(lower, upper)Box constraint $\{x : \text{lower}_i \le x_i \le \text{upper}_i\}$. lower and upper are vectors of equal length with lower[i] ≤ upper[i] element-wise. Use BoxSet(fill(a, n), fill(b, n)) for uniform scalar bounds.
julia> project([2.0, -3.0, 0.5], BoxSet([-1.0, -1.0, -1.0], [1.0, 1.0, 1.0]))
3-element Vector{Float64}:
1.0
-1.0
0.5DFMethods.HalfSpace — Type
HalfSpace(a, c)Half-space $\{x : a^\top x \le c\}$. a is the normal vector (must be nonzero), c the offset. Projection:
y = x if a' x ≤ c
y = x − ((a' x − c)/‖a‖²) a otherwiseThe hyperplane $H_k$ in the Solodov–Svaiter step is a HalfSpace.
DFMethods.Intersection — Type
Intersection(set1, set2; maxiter=200, tol=1e-12)Intersection of two closed convex sets. Projection uses Dykstra's algorithm (alternating projection with two correction sequences). For $\text{Box} \cap \text{HalfSpace}$ (the polyhedral set $\Omega$ realized by CappedBox), Dykstra converges geometrically.
For workloads that need general polyhedral projection, a direct QP solver (JuMP + HiGHS) will be added in Phase 2 as an alternative backend.
DFMethods.CappedBox — Type
CappedBox(a, b, c)The polyhedral set $\Omega(a, b, c) = \{x \in \mathbb{R}^n : a \le x_i \le b,\ \sum_i x_i \le c\}$ — a uniform-bound box intersected with a single budget-style halfspace. a, b, c are scalars; the dimension n is inferred from the input vector at projection time. This set is a common experimental domain in the convex-constrained nonlinear-equations literature.
Projection
Closed-form via bisection on a 1D Lagrange multiplier:
- Compute the box projection $y_B = \mathrm{clamp}(x, a, b)$.
- If $\mathbf{1}^\top y_B \le c$ → return $y_B$ (constraint inactive).
- Otherwise find $λ^* > 0$ such that $\sum_i \mathrm{clamp}(x_i - λ^*, a, b) = c$, then return $\mathrm{clamp}(x - λ^* \mathbf{1}, a, b)$.
The sum is piecewise-linear monotone-decreasing in λ, so bisection converges in O(log(1/tol)) steps.
Feasibility
The set is empty iff n·a > c. project! throws ArgumentError in that case (the feasibility check requires n, so it cannot happen at construction time).
DFMethods.UserSet — Type
UserSet(proj!)Constraint set defined by a user-supplied in-place projection proj!(y, x) that writes the projection of x onto the set into y. The user is responsible for ensuring proj! projects onto a closed convex set — otherwise the algorithm's convergence guarantees do not hold.
DFMethods.project! — Function
project!(y::AbstractVector, x::AbstractVector, set::AbstractConstraintSet) -> yIn-place orthogonal projection of x onto set. Writes the projection into y and returns y. Each concrete AbstractConstraintSet subtype provides its own method; see the individual set docstrings for the projection formula or algorithm used.
For an allocating wrapper, see project.
DFMethods.project — Function
project(x, set) -> VectorAllocating out-of-place projection. For tests and small problems. Inside the algorithm hot loop, always use project!.
DFMethods.approx_project_X_halfspace! — Function
approx_project_X_halfspace!(out, target, X, a, c, ε,
p_buf, q_buf, scratch, out_prev;
maxiter=500) -> outApproximate projection of target onto $X \cap H$ with $H = \{x : a^\top x \le c\}$, via Dykstra. Inner buffers (p_buf, q_buf, scratch, out_prev) are pre-allocated by the caller (typically the algorithm cache). Stops when $\|y - y_{\text{prev}}\|^2 \le \epsilon$ or maxiter reached.