solvers¶
solvers
¶
ODE solvers that integrate a learned velocity field.
The historical module name was deltaflow.samplers, which still
imports from here for backward compatibility.
EulerSolver
¶
Bases: BaseSolver
Explicit (forward) Euler integrator for the flow-matching ODE.
Integrates \(\mathrm{d}x/\mathrm{d}t = v_\theta(x, t)\) with the first-order update
using a single velocity evaluation per step. It is cheap but incurs
\(\mathcal{O}(\Delta t^2)\) local truncation error (\(\mathcal{O}(\Delta
t)\) global), so prefer HeunSolver when
accuracy at low step counts matters.
Source code in deltaflow/core/base_solver.py
sample
¶
Generate samples by integrating the velocity field.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Tensor
|
initial state (shape/device/dtype template if |
required |
n_steps
|
int
|
number of Euler integration steps. |
50
|
x_cond
|
Optional[Tensor]
|
optional partially-noised starting point, if given the
initial state becomes |
None
|
t_start
|
float
|
starting time, used together with |
0.0
|
t_end
|
float
|
end time, defaults to |
1.0
|
**cond
|
Any
|
extra keyword arguments forwarded to the velocity model. |
{}
|
Source code in deltaflow/solvers/euler.py
EquilibriumSolver
¶
Bases: BaseSolver
Gradient-descent sampler for an Equilibrium Matching landscape.
A field trained with EquilibriumInterpolant
approximates the time-invariant equilibrium gradient of an implicit
energy \(E\), pointing from noise toward data, \(f(x) \approx -\nabla
E(x)\). Unlike flow/diffusion models, samples are not obtained by
integrating a velocity over a fixed time horizon. Instead they are found by
optimising a noise draw down the landscape,
which is gradient descent on \(E\) (ascent along \(f\)). Because sampling
is decoupled from any prescribed trajectory, the step size step_size
and the number of steps n_steps are free knobs, and adaptive compute is
just running more iterations.
Nesterov (NAG-GD). With momentum > 0 the solver uses the
accelerated look-ahead update from the paper,
which reaches high-quality samples in fewer steps than vanilla gradient descent.
No time. An EqM field is a BaseEquilibriumField, a
time-invariant \(f(x)\) with no time (or \(\gamma\)) argument. The solver
therefore calls it as model(x, **cond) and there is no eval_time or
time_scale to route, sampling is pure optimisation on the landscape.
References
Wang and Du, "Equilibrium Matching: Generative Modeling with Implicit Energy-Based Models" (2025), https://arxiv.org/abs/2510.02300.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
Callable
|
callable |
required |
step_size
|
float
|
gradient-descent step \(\eta\). |
0.05
|
momentum
|
float
|
Nesterov coefficient \(\mu\). |
0.0
|
Source code in deltaflow/solvers/gradient_descent.py
step
¶
Single vanilla gradient-descent step (t/dt are ignored).
Provided for BaseSolver compatibility. The momentum-aware loop lives
in sample.
Source code in deltaflow/solvers/gradient_descent.py
sample
¶
Sample by gradient descent on the learned equilibrium landscape.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Tensor
|
initial noise state (shape/device/dtype template). |
required |
n_steps
|
int
|
number of gradient-descent iterations. |
100
|
step_size
|
Optional[float]
|
overrides |
None
|
momentum
|
Optional[float]
|
overrides |
None
|
show_progress
|
bool
|
display a tqdm progress bar if available. |
True
|
**cond
|
Any
|
extra keyword arguments forwarded to the model unchanged. |
{}
|
Source code in deltaflow/solvers/gradient_descent.py
HeunSolver
¶
Bases: BaseSolver
Heun (improved-Euler) second-order predictor-corrector integrator.
Each step takes an Euler predictor and averages the velocity at the current and predicted states,
This costs two velocity evaluations per step but has \(\mathcal{O}(\Delta t^3)\) local truncation error (\(\mathcal{O}(\Delta t^2)\) global), so it typically matches Euler's quality at half the number of steps. It is the trapezoidal-rule integrator widely used in EDM-style samplers.
Source code in deltaflow/core/base_solver.py
PosteriorSolver
¶
Bases: BaseSolver
Base-solver wrapper that adds a per-step measurement-likelihood gradient.
For an inverse problem with measurement \(y = A(x) + n\), this samples from the posterior \(p(x \mid y)\) by nudging an unconditional flow-matching solver toward the data-consistency term at every step. Given the current state \(x_t\) and velocity \(v_\theta(x_t, t)\), one step is
where \(\mathcal{T}\) is the flow-matching Tweedie decomposition that maps
\((x_t, v_t, t)\) to the clean-signal estimate \(\hat{x}_1\) (see
deltaflow.inverse.tweedie), and \(\eta\) is the guidance_scale.
The likelihood gradient is obtained by autograd, so if the velocity field
operates on VAE latents while \(A\) is defined on pixels, passing a decoder
to the likelihood object pulls the gradient back into latent space
automatically. Only the sampling-time ODE is modified. The pretrained
velocity field is untouched.
References
Kim et al., "FlowDPS: Flow-Driven Posterior Sampling for Inverse Problems" (2025), https://arxiv.org/abs/2503.08136. "Flower: A Flow-Matching Solver for Inverse Problems" (2025), https://arxiv.org/abs/2509.26287.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_solver
|
BaseSolver
|
any |
required |
likelihood
|
Likelihood
|
object with a |
required |
tweedie
|
Optional[BaseTweedie]
|
flow-matching Tweedie decomposition \(\mathcal{T}\) to derive
\(\hat{x}_1\) from \((x_t, v_t, t)\). Defaults to
|
None
|
guidance_scale
|
float
|
step size \(\eta\) on the likelihood gradient. Larger values snap harder to the measurement but risk over-shooting. |
1.0
|
grad_normalize
|
bool
|
if |
False
|