Skip to content

Commit 45f5066

Browse files
committed
test adjoint
1 parent 2cd9890 commit 45f5066

3 files changed

Lines changed: 37 additions & 1 deletion

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ site/
99
.idea/
1010
.venv/
1111
uv.lock
12+
.vscode/

diffrax/_adjoint.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
AbstractSRK,
2323
AbstractStratonovichSolver,
2424
)
25-
from ._term import AbstractTerm, AdjointTerm
25+
from ._term import AbstractTerm, AdjointTerm, MultiTerm
26+
from ._typing import get_origin_no_specials
2627

2728

2829
ω = cast(Callable, ω)
@@ -847,6 +848,12 @@ def loop(
847848
"`diffrax.BacksolveAdjoint` is only compatible with solvers that take "
848849
"a single term."
849850
)
851+
if get_origin_no_specials(solver.term_structure, "term_structure") is MultiTerm:
852+
raise NotImplementedError(
853+
f"`diffrax.BacksolveAdjoint` is not compatible with solver "
854+
f"`{type(solver).__name__}`, or any solver with requirements on "
855+
"the noise. For SDEs, use a basic solver such as `diffrax.Euler`."
856+
)
850857
if event is not None:
851858
raise NotImplementedError(
852859
"`diffrax.BacksolveAdjoint` is not compatible with events."

test/test_adjoint.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,34 @@ def run(y0__args, adjoint):
414414
assert tree_allclose(grads1, grads3, rtol=1e-3, atol=1e-3)
415415

416416

417+
@pytest.mark.parametrize(
418+
"solver",
419+
(diffrax.ShARK(), diffrax.SEA(), diffrax.SRA1(), diffrax.SlowRK()),
420+
)
421+
def test_backsolve_multiterm_solver_error(solver, getkey):
422+
# https://github.com/patrick-kidger/diffrax/issues/558
423+
t0, t1, dt0 = 0, 1, 0.01
424+
bm = diffrax.VirtualBrownianTree(
425+
t0, t1, 1e-3, (2,), key=getkey(), levy_area=diffrax.SpaceTimeLevyArea
426+
)
427+
drift = diffrax.ODETerm(lambda t, y, args: -y)
428+
diffusion = diffrax.ControlTerm(
429+
lambda t, y, args: lx.DiagonalLinearOperator(0.1 * jnp.zeros_like(y)), bm
430+
)
431+
terms = diffrax.MultiTerm(drift, diffusion)
432+
433+
@eqx.filter_jit
434+
@jax.grad
435+
def run(y0):
436+
sol = diffrax.diffeqsolve(
437+
terms, solver, t0, t1, dt0, y0, adjoint=diffrax.BacksolveAdjoint()
438+
)
439+
return jnp.sum(cast(Array, sol.ys))
440+
441+
with pytest.raises(NotImplementedError, match="not compatible with solver"):
442+
run(jnp.array([1.0, 2.0]))
443+
444+
417445
def test_implicit_runge_kutta_direct_adjoint():
418446
diffrax.diffeqsolve(
419447
diffrax.ODETerm(lambda t, y, args: -y),

0 commit comments

Comments
 (0)