-
-
Notifications
You must be signed in to change notification settings - Fork 211
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Detect diagonal noise in SDESystem
#2882
Detect diagonal noise in SDESystem
#2882
Conversation
SDESystem
For reference, the reason for the noise structure is that the Levy area, computed as the correlation between the Brownian motions, is the thing that is difficult and thus requires splitting SDE solvers into non-commutative, commutative, and "diagonal" methods, where diagonal can specialize the Levy area calculation to effectively be trivial and thus achieve higher order. If you have one Brownian motion, then the Levy area is also trivial, and so the diagonal noise solvers also are higher order on scalar noise with a small change to the form (which the solvers do), and so diagonal noise and scalar noise hit the same higher order solver code path than the other noise types. Additionally there's additive noise which can hit different solver types, but that does not have signaling at the problem level and is just a solver choice. I would like MTK to signal it somehow, since it's somewhat common and the best solvers are those for additive noise (since that is the most trivial noise case, so you get much higher order). |
Downstream failure is unrelated. @baggepinnen do you know what that is? |
Before you merge, I just realized one thing I should do to make it a bit more robust |
Okay, that should be better. The change I just pushed can now detect cases like when the noise equations would be [a 0
b 0
0 c] which is also actually diagonal noise. |
Why would that be diagonal? 1 and 2 share the same brownian motion in that case? |
Wait, so if the noise equation is [a
b
c] then all three are independent, but if its [a 0
b 0
0 c] then |
Yes, see https://docs.sciml.ai/DiffEqDocs/stable/tutorials/sde_example/#Example-4:-Systems-of-SDEs-with-Non-Diagonal-Noise for how it is all defined. |
to be concrete, what I mean is that both of these should describe diagonal noise, right? @parameters σ ρ β
@variables x(t) y(t) z(t)
@brownian a
eqs = [D(x) ~ σ * (y - x) + 0.1a * x,
D(y) ~ x * (ρ - z) - y + 0.1a * y,
D(z) ~ x * y - β * z + 0.1a * z]
@mtkbuild de = System(eqs, t) and @parameters σ ρ β
@variables x(t) y(t) z(t)
@brownian a b
eqs = [D(x) ~ σ * (y - x) + 0.1a * x,
D(y) ~ x * (ρ - z) - y + 0.1a * y,
D(z) ~ x * y - β * z + 0.1b * z]
@mtkbuild de = System(eqs, t) I'd find it rather distressing if the first was considered diagonal, but the second was considered correlated... |
The first is a scalar noise SDE, which uses the simplified function form of the diagonal noise https://docs.sciml.ai/DiffEqDocs/stable/tutorials/sde_example/#Example-3:-Systems-of-SDEs-with-Scalar-Noise but with a scalar noise process. The second is non-diagonal and more specifically non-commutative (with commutative defined in https://docs.sciml.ai/DiffEqDocs/stable/solvers/sde_solve/#special_noise_forms). |
Actually I see your row equation thing is missing the part where "but with a scalar noise process". MTK does not really handle that part of the construction right now, so maybe it's best to keep that to non-diagonal until that can be specialized more. |
Hm okay I think there's something I'm just not understanding here. Should I just revert to doing # Fix for https://github.com/SciML/ModelingToolkit.jl/issues/2490
noise_eqs = isdiag(sorted_g_rows) # Does each row have only one non-zero entry?
diag(sorted_g_rows)
elseif sorted_g_rows isa AbstractMatrix && size(sorted_g_rows, 2) == 1
sorted_g_rows[:, 1] # Take a vector slice so solver knows there's no mixing
else
sorted_g_rows
end ? |
only make the diagonal one separate for now. Scalar noise needs to change the WienerProcess that is passed and I'm not sure that's handled |
Okay, sounds good. |
Okay, update on this. I had previously misunderstood what was going on, and when a user uses just one I was confused about this because of the differences in meaning between a In order to correctly handle scalar noise, I've added another field to Since this package doesn't depend on packages which define |
Ah, I just noticed that before you could actually create |
b712a12
to
e2ec9c7
Compare
Fixes #2490
see #2882 (comment) for current state of PR
Checklist
contributor guidelines, in particular the SciML Style Guide and
COLPRAC.
Additional context
The idea here is that without this change, we were basically not communicating to the solver when the noise equations are either a diagonal matrix (using N independent
@brownian
s once), or aNx1
matrix (only one@brownian
variablewhich also means diagonal noise rather confusinglywhich means scalar noise)Example:
Result before:
Result after: