Skip to content

Enzyme: Cannot differentiate through MTK DAE solve (MutabilityException / RuntimeActivityError) #1359

@ChrisRackauckas-Claude

Description

@ChrisRackauckas-Claude

Description

Enzyme fails to differentiate through solve for an MTK ODEProblem with DAE initialization (algebraic constraints with guesses). Three different calling conventions were tested, each producing a different error:

  1. Enzyme.gradient(Reverse, loss, tunables)EnzymeMutabilityException — closure captures mutable state (ODEProblem containing arrays)
  2. Enzyme.gradient(Reverse, Const(loss), tunables)EnzymeRuntimeActivityError — constant memory stored/returned to differentiable variable
  3. Enzyme.gradient(set_runtime_activity(Reverse), Const(loss), tunables)MethodError: no method matching MixedDuplicated(::ODESolution...)

MWE

import Pkg
Pkg.activate(; temp = true)
Pkg.add(["ModelingToolkit", "OrdinaryDiffEq", "Enzyme",
    "SciMLSensitivity", "SciMLStructures", "SymbolicIndexingInterface"])

using ModelingToolkit, OrdinaryDiffEq, Enzyme
using ModelingToolkit: t_nounits as t, D_nounits as D
using SciMLSensitivity
import SciMLStructures as SS
using SymbolicIndexingInterface

# Minimal DAE system: ODE + algebraic constraint requiring initialization
@parameters a b
@variables x(t) y(t)

eqs = [
    D(x) ~ a * x + y,
    0 ~ x^2 - b * y,  # algebraic constraint
]

@mtkbuild sys = ODESystem(eqs, t)

prob = ODEProblem(sys, [x => 1.0], (0.0, 1.0), [a => -0.5, b => 2.0],
    guesses = [y => 1.0])
tunables, repack, _ = SS.canonicalize(SS.Tunable(), parameter_values(prob))

# Forward solve works fine
sol = solve(prob, Rodas5P())

loss = let prob = prob, repack = repack
    p -> begin
        new_prob = remake(prob; p = repack(p))
        sol = solve(new_prob, Rodas5P(); abstol = 1e-8, reltol = 1e-6)
        sum(sol)
    end
end

# Attempt 1: plain Reverse
grad = Enzyme.gradient(Enzyme.Reverse, loss, tunables)
# => EnzymeMutabilityException

# Attempt 2: Const(loss)
grad = Enzyme.gradient(Enzyme.Reverse, Enzyme.Const(loss), tunables)
# => EnzymeRuntimeActivityError

# Attempt 3: set_runtime_activity + Const
grad = Enzyme.gradient(set_runtime_activity(Enzyme.Reverse), Enzyme.Const(loss), tunables)
# => MethodError: no method matching MixedDuplicated(::ODESolution...)

Errors

Attempt 1:

EnzymeMutabilityException: Function argument passed to autodiff cannot be proven readonly.

Attempt 2:

EnzymeRuntimeActivityError: Detected potential need for runtime activity.
Constant memory is stored (or returned) to a differentiable variable and correctness cannot be guaranteed with static activity analysis.

Attempt 3:

MethodError: no method matching MixedDuplicated(::ODESolution{Float64, 2, ...}, ...)

Environment

  • Julia 1.12
  • ModelingToolkit v11
  • Enzyme v0.13 / Enzyme_jll v0.0.249
  • SciMLSensitivity latest

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions