-
-
Notifications
You must be signed in to change notification settings - Fork 85
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
Summary of issues with ODE Bayesian parameter estimation benchmarks #496
Comments
Also, any benchmark should probably include multiple chains run in parallel and combined to estimate mixing/ESS. |
We do not take benchmarks offline when someone does not like the results. That's not how open science works. They are open for everyone to edit. If you want to see a change, please edit them. As of right now, they are the best measurements we know of. If you don't like them, please submit a pull request. We have on-going pull requests such as #495. We do all of our development in the open for everyone to see: taking down the benchmarks is tantamount to stopping development. The point of open benchmarks is to keep improving them, not to hide them. We don't do that when we look good, and we do not do that when we look bad. We share as much information as possible about the accuracy with the timings so that people can made educated statements about the results given what they see. Given the remarks you have been able to make just by reading the results, it's clear that we have shared enough information for people to see the good and the flaws of the current status of these benchmarks. That means that it's doing it's job sufficiently well of remarking on the current status, and if anything more should be added to further characterize the landscape, not less.
That sounds like good information to share online to everyone and to let people see if they can improve it. If there is no setup for these samplers to obtain this posterior for this relatively simple ODE, that's good information to have!
Thanks for pointing that out. Can you submit a PR?
We looked at that in detail. There were changes made to omit compile time: Even without that, it's referenced in there that the compile times are around 10 seconds. For a 1000 second benchmark, I do not think the 10 seconds are the biggest deal. It's also not a huge deal for Turing either. I'm not sure why there is such a focus on the 1%.
That should improve, yes. If you have suggestions, please open a PR.
Let's do both. That would be most informative. How would I make such ESS/s histograms? Could you share the code, or open a PR?
Thanks for noting this. How would we change this in Stan? It might be easiest to just change Turing.jl and DynamicHMC.jl, but it would be nice to make this explicit and try multiple values. Maybe this could help the Lorenz results as well.
The benchmark computers have 32-cores and routinely run benchmarks that take upwards of 16 hours. There are plenty of other PDE benchmarks included in this setup, for example there's https://benchmarks.sciml.ai/html/MOLPDE/Filament.html and then there's thousands of ODEs stiff equations https://benchmarks.sciml.ai/stable/Bio/BCR/ . There are big systems, and there are small systems. They use different methods. All matter in some way. If you only look at the ones on "toy" problems, then you will only see "toy" problems, but there are many more in this set if you click to the other pages. That said, such "toy" problems are actually very similar to the PKPD models used for the estimation of dosing characteristics that was used for the dose predictions for the COVID-19 vaccine. As such, doing big repeated estimations on small sets of ODEs is not something to scoff at but rather is something that is a crucial part of many modern applications and should be optimized like any others (those PKPD estimations are routinely done other large datasets with many patients, so it may be <10 ODEs, but it's in some sense similar to doing tens of thousands of such estimations, so performance matters!) |
that's fine. You can still contribute by sharing some Stan code. That's probably even more helpful since that's the part we know least. If you know how to make Stan output the ESS/s, please share. |
You are of course free to do whatever you want, but I don't think it's reasonable to publish/keep online, link to and quote benchmarks which are known to have major and minor flaws and which tend to mislead non-experts. Even I had to rerun the code on my local machine and inspect the source code to understand what's going on, and I doubt many other people do that. That being said, I don't know how to fix the benchmarks in Julia. |
These benchmarks are yours too. That's is why they are free to be edited. What we need more than anything is probably more Stan code, so if you have Stan code for the things you're asking for then please share. |
With:
building in https://buildkite.com/julialang/scimlbenchmarks-dot-jl/builds/965, big chunks of this are handled. What I'm really missing are ways to get the ESS/s and do direct gradient timings. The Turing devs (@devmotion) can probably do the Turing side quite easily, though we might need some help on the Stan code. |
For gradient comparisons one could use or build on https://github.com/torfjelde/TuringBenchmarking.jl (there was some discussion about moving it to TuringLang).
|
@devmotion can you help with sorting this one out? Once that's done, we can close this since all that's left is a duplicate of #494 if I haven't missed anything. We should also make DynamicHMC print out more, though I'm not sure how to do that.
Cool! That would be good to include. |
Yeah, that's what should be done.
I think the Stan code/model is fine (where it defines the same posterior as the Turing code). I think what can be changed/improved is passing the right compile flags to Stan, but I wouldn't know how to do that from Julia. Flags that seem to work and improve performance a bit (but not a lot) are:
which should go into the cmdstan The other thing that should be improved is postprocessing/reporting of results, but as @devmotion explained, there are several options to estimates ESS, and I simply don't know the Julia ecosystem well enough to know which implementation to use or how to use it. |
IMO that would not make the benchmark fairer. I think the correct thing to do is to benchmark the Julia packages with the default compile flags (they are not optimized or tuned for the benchmarks) with Stan with the default compile flags. Of course, alternatively one could try to hyperoptimize everything as much as possible - but that's less realistic as users will just go with the default flags, I assume. If Stan's default compile flags are suboptimal they should be changed by Stan but I don't think it's fair to tune thrm for this benchmark.
As I wrote, since StanSample.jl already reports results in the same output format as Turing (and other packages) and this format already supports ESS/s, the only missing piece is that StanSample.jl has to include the computation time when constructing its output. Then estimates would be based on the same algorithm and comparisons would be fair. |
I disagree. In my experience, people fitting ODE models generally care about performance, and this includes changing some easily accessible compiler flags for Stan. Similarly, you could just let Julia fit the model that "the average user" would code up, but this would be much slower?. Either of the choices for Julia will have a bigger impact on performance than enabling the "standard" Stan performance flags. |
FWIW, I tend to agree with @nsiccha. Playing with compiler flags seems to be the norm for aggressively optimised Stan models. Since Turing models are being optimised by actual Turing devs, this doesn't seem unreasonable. |
Surely the models (regardless of whether it's Stan or Turing or ...) should be optimized, and any help for optimizing the Stan models is very much appreciated (BTW I don't think the Turing models are completely optimized, definitely not if you're using DiffEqBayes - but that's a different topic). But there's no special compiler optimization or tricks going on in the Turing side - we just benchmark the package as it is and as users would install it. Similarly, maybe for Stan one should just install cmdstan via Conda? It seems that's what users on Windows, e.g., are supposed to do anyway: https://mc-stan.org/docs/cmdstan-guide/cmdstan-installation.html |
Our benchmark rules are: https://github.com/SciML/SciMLBenchmarks.jl#rules-optimal-fair-and-reproducible
So I think it's fair to use the better compiler flags. We try to setup everyone's "optimization tricks" wherever possible, but then also document their effects. So it would be good for example if we could have a version with special compiler flags and the default: that would demonstrate the amount of performance improvement due to the flags. It wouldn't be too hard to just have two Stan binaries built and swap the call? We normally do this kind of gradation for everything. Stan is a bit of a PITA here since it's an order of magnitude harder to install than other packages, but now that we have a basis to work from it shouldn't be too bad.
They are definitely not, which is why I added the direct version so they can start being optimized. They are definitely not close to optimized yet though. |
Yeah, I think it would also be a good idea to show Julia implementation which are optimized to different degrees, just so that people know what's possible and how big of an impact each step might have. But maybe this only encourages people to implent their model suboptimally... |
I'm guessing it can also happen that some "optimizations" can even have an adverse effect in some cases, which would also be interesting to see. |
Indeed, like how in https://benchmarks.sciml.ai/dev/MultiLanguage/ode_wrapper_packages/#Stiff-Problem-2:-HIRES static arrays are worse than using in-place, even though the ODE is small. That's why we just try to show it all: the main use case of the benchmarks is just internal to help find performance regressions and figure out what the optimal way to do things is to change tutorials. For example, the current result of these Bayesian benchmarks has been to speedup the rate at which we deprecate the Turing wrapper, which is being made clear through the current results.
This is a completely separate repo from the docs and tutorials, so hopefully people aren't using it as a tutorial for anything other than how to choose methods |
Since the objective function is now type-stable: ```julia prob = build_opf_optimization_prob(dataset) @code_warntype prob.f.f(test_u0, nothing) ``` ```julia MethodInstance for (::var"#opf_objective#497"{Dict{Int64, Vector{Float64}}, Dict{Int64, Int64}, Vector{Int64}})(::Vector{Float64}, ::Nothing) from (::var"#opf_objective#497")(x, param) @ Main c:\Users\accou\.julia\dev\SciMLBenchmarks\benchmarks\OptimizationFrameworks\optimal_powerflow.jmd:329 Arguments #self#::var"#opf_objective#497"{Dict{Int64, Vector{Float64}}, Dict{Int64, Int64}, Vector{Int64}} x::Vector{Float64} param::Core.Const(nothing) Locals @_4::Union{Nothing, Tuple{Int64, Int64}} cost::Float64 i::Int64 _cost_arr::Vector{Float64} pg::Float64 Body::Float64 1 ─ (cost = 0.0) │ %2 = Core.getfield(#self#, :ref_gen_idxs)::Vector{Int64} │ (@_4 = Base.iterate(%2)) │ %4 = (@_4 === nothing)::Bool │ %5 = Base.not_int(%4)::Bool └── goto #4 if not %5 2 ┄ %7 = @_4::Tuple{Int64, Int64} │ (i = Core.getfield(%7, 1)) │ %9 = Core.getfield(%7, 2)::Int64 │ %10 = Core.getfield(#self#, :lookup_pg)::Dict{Int64, Int64} │ %11 = Base.getindex(%10, i)::Int64 │ (pg = Base.getindex(x, %11)) │ %13 = Core.getfield(#self#, :cost_arrs)::Dict{Int64, Vector{Float64}} │ (_cost_arr = Base.getindex(%13, i)) │ %15 = cost::Float64 │ %16 = Base.getindex(_cost_arr, 1)::Float64 │ %17 = Main.:^::Core.Const(^) │ %18 = pg::Float64 │ %19 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2}) │ %20 = (%19)()::Core.Const(Val{2}()) │ %21 = Base.literal_pow(%17, %18, %20)::Float64 │ %22 = (%16 * %21)::Float64 │ %23 = Base.getindex(_cost_arr, 2)::Float64 │ %24 = (%23 * pg)::Float64 │ %25 = Base.getindex(_cost_arr, 3)::Float64 │ %26 = (%22 + %24 + %25)::Float64 │ (cost = %15 + %26) │ (@_4 = Base.iterate(%2, %9)) │ %29 = (@_4 === nothing)::Bool │ %30 = Base.not_int(%29)::Bool └── goto #4 if not %30 3 ─ goto #2 4 ┄ return cost ``` Along with the constraint function ```julia ret = zeros(length(prob.lcons)) @code_warntype prob.f.cons(ret, test_u0, nothing) ``` ```julia MethodInstance for (::var"#opf_constraints#498"{Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Tuple{Int64, Int64, Int64}, Int64}, Dict{Tuple{Int64, Int64, Int64}, Int64}, Vector{Tuple{Int64, Int64, Int64}}, Vector{Tuple{Int64, Int64, Int64}}, Dict{Int64, Vector{Tuple{Int64, Int64, Int64}}}, Dict{Int64, Vector{Int64}}, Vector{Int64}, Vector{Int64}, Dict{Int64, Int64}, Dict{Int64, Int64}, Dict{Int64, Int64}, Dict{Int64, Int64}, Dict{Int64, Int64}, Dict{Int64, Int64}})(::Vector{Float64}, ::Vector{Float64}, ::Nothing) from (::var"#opf_constraints#498")(ret, x, param) @ Main c:\Users\accou\.julia\dev\SciMLBenchmarks\benchmarks\OptimizationFrameworks\optimal_powerflow.jmd:341 Arguments #self#::var"#opf_constraints#498"{Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Tuple{Int64, Int64, Int64}, Int64}, Dict{Tuple{Int64, Int64, Int64}, Int64}, Vector{Tuple{Int64, Int64, Int64}}, Vector{Tuple{Int64, Int64, Int64}}, Dict{Int64, Vector{Tuple{Int64, Int64, Int64}}}, Dict{Int64, Vector{Int64}}, Vector{Int64}, Vector{Int64}, Dict{Int64, Int64}, Dict{Int64, Int64}, Dict{Int64, Int64}, Dict{Int64, Int64}, Dict{Int64, Int64}, Dict{Int64, Int64}} ret::Vector{Float64} x::Vector{Float64} param::Core.Const(nothing) Locals @_5::Union{Nothing, Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}}} @_6::Union{Nothing, Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}}} @_7::Union{Nothing, Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}}} @_8::Union{Nothing, Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}}} @_9::Union{Nothing, Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}}} @_10::Union{Nothing, Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}}} @_11::Union{Nothing, Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}}} @_12::Union{Nothing, Tuple{Tuple{Int64, Int64}, Tuple{Int64, Int64}}} @_13::Union{Nothing, Tuple{Tuple{Int64, Int64}, Tuple{Int64, Int64}}} @_14::Union{Nothing, Tuple{Tuple{Int64, Int64}, Tuple{Int64, Int64}}} offsetidx::Int64 @_16::Int64 i@_17::Int64 reti@_18::Int64 #494::var"#494#500"{Vector{Float64}, Dict{Tuple{Int64, Int64, Int64}, Int64}} #493::var"#493#499"{Vector{Float64}, Dict{Int64, Int64}} @_21::Int64 i@_22::Int64 reti@_23::Int64 #496::var"#496#502"{Vector{Float64}, Dict{Tuple{Int64, Int64, Int64}, Int64}} #495::var"#495#501"{Vector{Float64}, Dict{Int64, Int64}} @_26::Int64 i@_27::Int64 reti@_28::Int64 @_29::Int64 @_30::Int64 j@_31::Int64 l@_32::Int64 i@_33::Int64 reti@_34::Int64 @_35::Int64 @_36::Int64 j@_37::Int64 i@_38::Int64 l@_39::Int64 reti@_40::Int64 @_41::Int64 @_42::Int64 j@_43::Int64 i@_44::Int64 l@_45::Int64 reti@_46::Int64 @_47::Int64 @_48::Int64 j@_49::Int64 i@_50::Int64 l@_51::Int64 reti@_52::Int64 @_53::Int64 @_54::Int64 j@_55::Int64 i@_56::Int64 l@_57::Int64 reti@_58::Int64 @_59::Int64 @_60::Int64 j@_61::Int64 i@_62::Int64 l@_63::Int64 reti@_64::Int64 @_65::Int64 @_66::Int64 j@_67::Int64 i@_68::Int64 l@_69::Int64 reti@_70::Int64 Body::Nothing 1 ── Core.NewvarNode(:(@_5)) │ Core.NewvarNode(:(@_6)) │ Core.NewvarNode(:(@_7)) │ Core.NewvarNode(:(@_8)) │ Core.NewvarNode(:(@_9)) │ Core.NewvarNode(:(@_10)) │ Core.NewvarNode(:(@_11)) │ Core.NewvarNode(:(@_12)) │ Core.NewvarNode(:(@_13)) │ (offsetidx = 0) │ %11 = Core.getfield(#self#, :ref_buses_idxs)::Vector{Int64} │ %12 = Main.enumerate(%11)::Base.Iterators.Enumerate{Vector{Int64}} │ (@_14 = Base.iterate(%12)) │ %14 = (@_14 === nothing)::Bool │ %15 = Base.not_int(%14)::Bool └─── goto #4 if not %15 2 ┄─ %17 = @_14::Tuple{Tuple{Int64, Int64}, Tuple{Int64, Int64}} │ %18 = Core.getfield(%17, 1)::Tuple{Int64, Int64} │ %19 = Base.indexed_iterate(%18, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)]) │ (reti@_18 = Core.getfield(%19, 1)) │ (@_16 = Core.getfield(%19, 2)) │ %22 = Base.indexed_iterate(%18, 2, @_16::Core.Const(2))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(3)]) │ (i@_17 = Core.getfield(%22, 1)) │ %24 = Core.getfield(%17, 2)::Tuple{Int64, Int64} │ %25 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64} │ %26 = Base.getindex(%25, i@_17)::Int64 │ %27 = Base.getindex(x, %26)::Float64 │ %28 = (reti@_18 + offsetidx::Core.Const(0))::Int64 │ Base.setindex!(ret, %27, %28) │ (@_14 = Base.iterate(%12, %24)) │ %31 = (@_14 === nothing)::Bool │ %32 = Base.not_int(%31)::Bool └─── goto #4 if not %32 3 ── goto #2 4 ┄─ %35 = offsetidx::Core.Const(0) │ %36 = Core.getfield(#self#, :ref_buses_idxs)::Vector{Int64} │ %37 = Main.length(%36)::Int64 │ (offsetidx = %35 + %37) │ %39 = Core.getfield(#self#, :ref_bus_idxs)::Vector{Int64} │ %40 = Main.enumerate(%39)::Base.Iterators.Enumerate{Vector{Int64}} │ (@_13 = Base.iterate(%40)) │ %42 = (@_13 === nothing)::Bool │ %43 = Base.not_int(%42)::Bool └─── goto #7 if not %43 5 ┄─ %45 = @_13::Tuple{Tuple{Int64, Int64}, Tuple{Int64, Int64}} │ %46 = Core.getfield(%45, 1)::Tuple{Int64, Int64} │ %47 = Base.indexed_iterate(%46, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)]) │ (reti@_23 = Core.getfield(%47, 1)) │ (@_21 = Core.getfield(%47, 2)) │ %50 = Base.indexed_iterate(%46, 2, @_21::Core.Const(2))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(3)]) │ (i@_22 = Core.getfield(%50, 1)) │ %52 = Core.getfield(%45, 2)::Tuple{Int64, Int64} │ %53 = Main.:(var"#493#499")::Core.Const(var"#493#499") │ %54 = Core.typeof(x)::Core.Const(Vector{Float64}) │ %55 = Core.getfield(#self#, :lookup_pg)::Dict{Int64, Int64} │ %56 = Core.typeof(%55)::Core.Const(Dict{Int64, Int64}) │ %57 = Core.apply_type(%53, %54, %56)::Core.Const(var"#493#499"{Vector{Float64}, Dict{Int64, Int64}}) │ %58 = Core.getfield(#self#, :lookup_pg)::Dict{Int64, Int64} │ (#493 = %new(%57, x, %58)) │ %60 = #493::var"#493#499"{Vector{Float64}, Dict{Int64, Int64}} │ %61 = Core.getfield(#self#, :ref_bus_gens)::Dict{Int64, Vector{Int64}} │ %62 = Base.getindex(%61, i@_22)::Vector{Int64} │ %63 = Base.Generator(%60, %62)::Base.Generator{Vector{Int64}, var"#493#499"{Vector{Float64}, Dict{Int64, Int64}}} │ %64 = (:init,)::Core.Const((:init,)) │ %65 = Core.apply_type(Core.NamedTuple, %64)::Core.Const(NamedTuple{(:init,)}) │ %66 = Core.tuple(0.0)::Core.Const((0.0,)) │ %67 = (%65)(%66)::Core.Const((init = 0.0,)) │ %68 = Core.kwcall(%67, Main.sum, %63)::Float64 │ %69 = Core.getfield(#self#, :bus_pd)::Dict{Int64, Float64} │ %70 = Base.getindex(%69, i@_22)::Float64 │ %71 = (%68 - %70)::Float64 │ %72 = Core.getfield(#self#, :bus_gs)::Dict{Int64, Float64} │ %73 = Base.getindex(%72, i@_22)::Float64 │ %74 = Main.:^::Core.Const(^) │ %75 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %76 = Base.getindex(%75, i@_22)::Int64 │ %77 = Base.getindex(x, %76)::Float64 │ %78 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2}) │ %79 = (%78)()::Core.Const(Val{2}()) │ %80 = Base.literal_pow(%74, %77, %79)::Float64 │ %81 = (%73 * %80)::Float64 │ %82 = (%71 - %81)::Float64 │ %83 = Main.:(var"#494#500")::Core.Const(var"#494#500") │ %84 = Core.typeof(x)::Core.Const(Vector{Float64}) │ %85 = Core.getfield(#self#, :p_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64} │ %86 = Core.typeof(%85)::Core.Const(Dict{Tuple{Int64, Int64, Int64}, Int64}) │ %87 = Core.apply_type(%83, %84, %86)::Core.Const(var"#494#500"{Vector{Float64}, Dict{Tuple{Int64, Int64, Int64}, Int64}}) │ %88 = Core.getfield(#self#, :p_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64} │ (#494 = %new(%87, x, %88)) │ %90 = #494::var"#494#500"{Vector{Float64}, Dict{Tuple{Int64, Int64, Int64}, Int64}} │ %91 = Core.getfield(#self#, :ref_bus_arcs)::Dict{Int64, Vector{Tuple{Int64, Int64, Int64}}} │ %92 = Base.getindex(%91, i@_22)::Vector{Tuple{Int64, Int64, Int64}} │ %93 = Base.Generator(%90, %92)::Base.Generator{Vector{Tuple{Int64, Int64, Int64}}, var"#494#500"{Vector{Float64}, Dict{Tuple{Int64, Int64, Int64}, Int64}}} │ %94 = Main.sum(%93)::Float64 │ %95 = (%82 - %94)::Float64 │ %96 = (reti@_23 + offsetidx)::Int64 │ Base.setindex!(ret, %95, %96) │ (@_13 = Base.iterate(%40, %52)) │ %99 = (@_13 === nothing)::Bool │ %100 = Base.not_int(%99)::Bool └─── goto #7 if not %100 6 ── goto #5 7 ┄─ %103 = offsetidx::Int64 │ %104 = Core.getfield(#self#, :ref_bus_idxs)::Vector{Int64} │ %105 = Main.length(%104)::Int64 │ (offsetidx = %103 + %105) │ %107 = Core.getfield(#self#, :ref_bus_idxs)::Vector{Int64} │ %108 = Main.enumerate(%107)::Base.Iterators.Enumerate{Vector{Int64}} │ (@_12 = Base.iterate(%108)) │ %110 = (@_12 === nothing)::Bool │ %111 = Base.not_int(%110)::Bool └─── goto #10 if not %111 8 ┄─ %113 = @_12::Tuple{Tuple{Int64, Int64}, Tuple{Int64, Int64}} │ %114 = Core.getfield(%113, 1)::Tuple{Int64, Int64} │ %115 = Base.indexed_iterate(%114, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)]) │ (reti@_28 = Core.getfield(%115, 1)) │ (@_26 = Core.getfield(%115, 2)) │ %118 = Base.indexed_iterate(%114, 2, @_26::Core.Const(2))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(3)]) │ (i@_27 = Core.getfield(%118, 1)) │ %120 = Core.getfield(%113, 2)::Tuple{Int64, Int64} │ %121 = Main.:(var"#495#501")::Core.Const(var"#495#501") │ %122 = Core.typeof(x)::Core.Const(Vector{Float64}) │ %123 = Core.getfield(#self#, :lookup_qg)::Dict{Int64, Int64} │ %124 = Core.typeof(%123)::Core.Const(Dict{Int64, Int64}) │ %125 = Core.apply_type(%121, %122, %124)::Core.Const(var"#495#501"{Vector{Float64}, Dict{Int64, Int64}}) │ %126 = Core.getfield(#self#, :lookup_qg)::Dict{Int64, Int64} │ (#495 = %new(%125, x, %126)) │ %128 = #495::var"#495#501"{Vector{Float64}, Dict{Int64, Int64}} │ %129 = Core.getfield(#self#, :ref_bus_gens)::Dict{Int64, Vector{Int64}} │ %130 = Base.getindex(%129, i@_27)::Vector{Int64} │ %131 = Base.Generator(%128, %130)::Base.Generator{Vector{Int64}, var"#495#501"{Vector{Float64}, Dict{Int64, Int64}}} │ %132 = (:init,)::Core.Const((:init,)) │ %133 = Core.apply_type(Core.NamedTuple, %132)::Core.Const(NamedTuple{(:init,)}) │ %134 = Core.tuple(0.0)::Core.Const((0.0,)) │ %135 = (%133)(%134)::Core.Const((init = 0.0,)) │ %136 = Core.kwcall(%135, Main.sum, %131)::Float64 │ %137 = Core.getfield(#self#, :bus_qd)::Dict{Int64, Float64} │ %138 = Base.getindex(%137, i@_27)::Float64 │ %139 = (%136 - %138)::Float64 │ %140 = Core.getfield(#self#, :bus_bs)::Dict{Int64, Float64} │ %141 = Base.getindex(%140, i@_27)::Float64 │ %142 = Main.:^::Core.Const(^) │ %143 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %144 = Base.getindex(%143, i@_27)::Int64 │ %145 = Base.getindex(x, %144)::Float64 │ %146 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2}) │ %147 = (%146)()::Core.Const(Val{2}()) │ %148 = Base.literal_pow(%142, %145, %147)::Float64 │ %149 = (%141 * %148)::Float64 │ %150 = (%139 + %149)::Float64 │ %151 = Main.:(var"#496#502")::Core.Const(var"#496#502") │ %152 = Core.typeof(x)::Core.Const(Vector{Float64}) │ %153 = Core.getfield(#self#, :q_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64} │ %154 = Core.typeof(%153)::Core.Const(Dict{Tuple{Int64, Int64, Int64}, Int64}) │ %155 = Core.apply_type(%151, %152, %154)::Core.Const(var"#496#502"{Vector{Float64}, Dict{Tuple{Int64, Int64, Int64}, Int64}}) │ %156 = Core.getfield(#self#, :q_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64} │ (#496 = %new(%155, x, %156)) │ %158 = #496::var"#496#502"{Vector{Float64}, Dict{Tuple{Int64, Int64, Int64}, Int64}} │ %159 = Core.getfield(#self#, :ref_bus_arcs)::Dict{Int64, Vector{Tuple{Int64, Int64, Int64}}} │ %160 = Base.getindex(%159, i@_27)::Vector{Tuple{Int64, Int64, Int64}} │ %161 = Base.Generator(%158, %160)::Base.Generator{Vector{Tuple{Int64, Int64, Int64}}, var"#496#502"{Vector{Float64}, Dict{Tuple{Int64, Int64, Int64}, Int64}}} │ %162 = Main.sum(%161)::Float64 │ %163 = (%150 - %162)::Float64 │ %164 = (reti@_28 + offsetidx)::Int64 │ Base.setindex!(ret, %163, %164) │ (@_12 = Base.iterate(%108, %120)) │ %167 = (@_12 === nothing)::Bool │ %168 = Base.not_int(%167)::Bool └─── goto #10 if not %168 9 ── goto #8 10 ┄ %171 = offsetidx::Int64 │ %172 = Core.getfield(#self#, :ref_bus_idxs)::Vector{Int64} │ %173 = Main.length(%172)::Int64 │ (offsetidx = %171 + %173) │ %175 = Core.getfield(#self#, :ref_arcs_from)::Vector{Tuple{Int64, Int64, Int64}} │ %176 = Main.enumerate(%175)::Base.Iterators.Enumerate{Vector{Tuple{Int64, Int64, Int64}}} │ (@_11 = Base.iterate(%176)) │ %178 = (@_11 === nothing)::Bool │ %179 = Base.not_int(%178)::Bool └─── goto #13 if not %179 11 ┄ %181 = @_11::Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}} │ %182 = Core.getfield(%181, 1)::Tuple{Int64, Tuple{Int64, Int64, Int64}} │ %183 = Base.indexed_iterate(%182, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)]) │ (reti@_34 = Core.getfield(%183, 1)) │ (@_30 = Core.getfield(%183, 2)) │ %186 = Base.indexed_iterate(%182, 2, @_30::Core.Const(2))::Core.PartialStruct(Tuple{Tuple{Int64, Int64, Int64}, Int64}, Any[Tuple{Int64, Int64, Int64}, Core.Const(3)]) │ %187 = Core.getfield(%186, 1)::Tuple{Int64, Int64, Int64} │ %188 = Base.indexed_iterate(%187, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)]) │ (l@_32 = Core.getfield(%188, 1)) │ (@_29 = Core.getfield(%188, 2)) │ %191 = Base.indexed_iterate(%187, 2, @_29::Core.Const(2))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(3)]) │ (i@_33 = Core.getfield(%191, 1)) │ (@_29 = Core.getfield(%191, 2)) │ %194 = Base.indexed_iterate(%187, 3, @_29::Core.Const(3))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(4)]) │ (j@_31 = Core.getfield(%194, 1)) │ %196 = Core.getfield(%181, 2)::Tuple{Int64, Int64} │ %197 = Core.getfield(#self#, :br_g)::Dict{Int64, Float64} │ %198 = Base.getindex(%197, l@_32)::Float64 │ %199 = Core.getfield(#self#, :br_g_fr)::Dict{Int64, Float64} │ %200 = Base.getindex(%199, l@_32)::Float64 │ %201 = (%198 + %200)::Float64 │ %202 = Core.getfield(#self#, :br_ttm)::Dict{Int64, Float64} │ %203 = Base.getindex(%202, l@_32)::Float64 │ %204 = (%201 / %203)::Float64 │ %205 = Main.:^::Core.Const(^) │ %206 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %207 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64} │ %208 = Base.getindex(%207, l@_32)::Int64 │ %209 = Base.getindex(%206, %208)::Int64 │ %210 = Base.getindex(x, %209)::Float64 │ %211 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2}) │ %212 = (%211)()::Core.Const(Val{2}()) │ %213 = Base.literal_pow(%205, %210, %212)::Float64 │ %214 = (%204 * %213)::Float64 │ %215 = Core.getfield(#self#, :br_g)::Dict{Int64, Float64} │ %216 = Base.getindex(%215, l@_32)::Float64 │ %217 = -%216::Float64 │ %218 = Core.getfield(#self#, :br_tr)::Dict{Int64, Float64} │ %219 = Base.getindex(%218, l@_32)::Float64 │ %220 = (%217 * %219)::Float64 │ %221 = Core.getfield(#self#, :br_b)::Dict{Int64, Float64} │ %222 = Base.getindex(%221, l@_32)::Float64 │ %223 = Core.getfield(#self#, :br_ti)::Dict{Int64, Float64} │ %224 = Base.getindex(%223, l@_32)::Float64 │ %225 = (%222 * %224)::Float64 │ %226 = (%220 + %225)::Float64 │ %227 = Core.getfield(#self#, :br_ttm)::Dict{Int64, Float64} │ %228 = Base.getindex(%227, l@_32)::Float64 │ %229 = (%226 / %228)::Float64 │ %230 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %231 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64} │ %232 = Base.getindex(%231, l@_32)::Int64 │ %233 = Base.getindex(%230, %232)::Int64 │ %234 = Base.getindex(x, %233)::Float64 │ %235 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %236 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64} │ %237 = Base.getindex(%236, l@_32)::Int64 │ %238 = Base.getindex(%235, %237)::Int64 │ %239 = Base.getindex(x, %238)::Float64 │ %240 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64} │ %241 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64} │ %242 = Base.getindex(%241, l@_32)::Int64 │ %243 = Base.getindex(%240, %242)::Int64 │ %244 = Base.getindex(x, %243)::Float64 │ %245 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64} │ %246 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64} │ %247 = Base.getindex(%246, l@_32)::Int64 │ %248 = Base.getindex(%245, %247)::Int64 │ %249 = Base.getindex(x, %248)::Float64 │ %250 = (%244 - %249)::Float64 │ %251 = Main.cos(%250)::Float64 │ %252 = (%234 * %239 * %251)::Float64 │ %253 = (%229 * %252)::Float64 │ %254 = Core.getfield(#self#, :br_b)::Dict{Int64, Float64} │ %255 = Base.getindex(%254, l@_32)::Float64 │ %256 = -%255::Float64 │ %257 = Core.getfield(#self#, :br_tr)::Dict{Int64, Float64} │ %258 = Base.getindex(%257, l@_32)::Float64 │ %259 = (%256 * %258)::Float64 │ %260 = Core.getfield(#self#, :br_g)::Dict{Int64, Float64} │ %261 = Base.getindex(%260, l@_32)::Float64 │ %262 = Core.getfield(#self#, :br_ti)::Dict{Int64, Float64} │ %263 = Base.getindex(%262, l@_32)::Float64 │ %264 = (%261 * %263)::Float64 │ %265 = (%259 - %264)::Float64 │ %266 = Core.getfield(#self#, :br_ttm)::Dict{Int64, Float64} │ %267 = Base.getindex(%266, l@_32)::Float64 │ %268 = (%265 / %267)::Float64 │ %269 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %270 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64} │ %271 = Base.getindex(%270, l@_32)::Int64 │ %272 = Base.getindex(%269, %271)::Int64 │ %273 = Base.getindex(x, %272)::Float64 │ %274 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %275 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64} │ %276 = Base.getindex(%275, l@_32)::Int64 │ %277 = Base.getindex(%274, %276)::Int64 │ %278 = Base.getindex(x, %277)::Float64 │ %279 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64} │ %280 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64} │ %281 = Base.getindex(%280, l@_32)::Int64 │ %282 = Base.getindex(%279, %281)::Int64 │ %283 = Base.getindex(x, %282)::Float64 │ %284 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64} │ %285 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64} │ %286 = Base.getindex(%285, l@_32)::Int64 │ %287 = Base.getindex(%284, %286)::Int64 │ %288 = Base.getindex(x, %287)::Float64 │ %289 = (%283 - %288)::Float64 │ %290 = Main.sin(%289)::Float64 │ %291 = (%273 * %278 * %290)::Float64 │ %292 = (%268 * %291)::Float64 │ %293 = (%214 + %253 + %292)::Float64 │ %294 = Core.getfield(#self#, :p_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64} │ %295 = Core.tuple(l@_32, i@_33, j@_31)::Tuple{Int64, Int64, Int64} │ %296 = Base.getindex(%294, %295)::Int64 │ %297 = Base.getindex(x, %296)::Float64 │ %298 = (%293 - %297)::Float64 │ %299 = (reti@_34 + offsetidx)::Int64 │ Base.setindex!(ret, %298, %299) │ (@_11 = Base.iterate(%176, %196)) │ %302 = (@_11 === nothing)::Bool │ %303 = Base.not_int(%302)::Bool └─── goto #13 if not %303 12 ─ goto #11 13 ┄ %306 = offsetidx::Int64 │ %307 = Core.getfield(#self#, :ref_arcs_from)::Vector{Tuple{Int64, Int64, Int64}} │ %308 = Main.length(%307)::Int64 │ (offsetidx = %306 + %308) │ %310 = Core.getfield(#self#, :ref_arcs_to)::Vector{Tuple{Int64, Int64, Int64}} │ %311 = Main.enumerate(%310)::Base.Iterators.Enumerate{Vector{Tuple{Int64, Int64, Int64}}} │ (@_10 = Base.iterate(%311)) │ %313 = (@_10 === nothing)::Bool │ %314 = Base.not_int(%313)::Bool └─── goto #16 if not %314 14 ┄ %316 = @_10::Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}} │ %317 = Core.getfield(%316, 1)::Tuple{Int64, Tuple{Int64, Int64, Int64}} │ %318 = Base.indexed_iterate(%317, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)]) │ (reti@_40 = Core.getfield(%318, 1)) │ (@_36 = Core.getfield(%318, 2)) │ %321 = Base.indexed_iterate(%317, 2, @_36::Core.Const(2))::Core.PartialStruct(Tuple{Tuple{Int64, Int64, Int64}, Int64}, Any[Tuple{Int64, Int64, Int64}, Core.Const(3)]) │ %322 = Core.getfield(%321, 1)::Tuple{Int64, Int64, Int64} │ %323 = Base.indexed_iterate(%322, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)]) │ (l@_39 = Core.getfield(%323, 1)) │ (@_35 = Core.getfield(%323, 2)) │ %326 = Base.indexed_iterate(%322, 2, @_35::Core.Const(2))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(3)]) │ (i@_38 = Core.getfield(%326, 1)) │ (@_35 = Core.getfield(%326, 2)) │ %329 = Base.indexed_iterate(%322, 3, @_35::Core.Const(3))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(4)]) │ (j@_37 = Core.getfield(%329, 1)) │ %331 = Core.getfield(%316, 2)::Tuple{Int64, Int64} │ %332 = Core.getfield(#self#, :br_g)::Dict{Int64, Float64} │ %333 = Base.getindex(%332, l@_39)::Float64 │ %334 = Core.getfield(#self#, :br_g_to)::Dict{Int64, Float64} │ %335 = Base.getindex(%334, l@_39)::Float64 │ %336 = (%333 + %335)::Float64 │ %337 = Main.:^::Core.Const(^) │ %338 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %339 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64} │ %340 = Base.getindex(%339, l@_39)::Int64 │ %341 = Base.getindex(%338, %340)::Int64 │ %342 = Base.getindex(x, %341)::Float64 │ %343 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2}) │ %344 = (%343)()::Core.Const(Val{2}()) │ %345 = Base.literal_pow(%337, %342, %344)::Float64 │ %346 = (%336 * %345)::Float64 │ %347 = Core.getfield(#self#, :br_g)::Dict{Int64, Float64} │ %348 = Base.getindex(%347, l@_39)::Float64 │ %349 = -%348::Float64 │ %350 = Core.getfield(#self#, :br_tr)::Dict{Int64, Float64} │ %351 = Base.getindex(%350, l@_39)::Float64 │ %352 = (%349 * %351)::Float64 │ %353 = Core.getfield(#self#, :br_b)::Dict{Int64, Float64} │ %354 = Base.getindex(%353, l@_39)::Float64 │ %355 = Core.getfield(#self#, :br_ti)::Dict{Int64, Float64} │ %356 = Base.getindex(%355, l@_39)::Float64 │ %357 = (%354 * %356)::Float64 │ %358 = (%352 - %357)::Float64 │ %359 = Core.getfield(#self#, :br_ttm)::Dict{Int64, Float64} │ %360 = Base.getindex(%359, l@_39)::Float64 │ %361 = (%358 / %360)::Float64 │ %362 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %363 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64} │ %364 = Base.getindex(%363, l@_39)::Int64 │ %365 = Base.getindex(%362, %364)::Int64 │ %366 = Base.getindex(x, %365)::Float64 │ %367 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %368 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64} │ %369 = Base.getindex(%368, l@_39)::Int64 │ %370 = Base.getindex(%367, %369)::Int64 │ %371 = Base.getindex(x, %370)::Float64 │ %372 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64} │ %373 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64} │ %374 = Base.getindex(%373, l@_39)::Int64 │ %375 = Base.getindex(%372, %374)::Int64 │ %376 = Base.getindex(x, %375)::Float64 │ %377 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64} │ %378 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64} │ %379 = Base.getindex(%378, l@_39)::Int64 │ %380 = Base.getindex(%377, %379)::Int64 │ %381 = Base.getindex(x, %380)::Float64 │ %382 = (%376 - %381)::Float64 │ %383 = Main.cos(%382)::Float64 │ %384 = (%366 * %371 * %383)::Float64 │ %385 = (%361 * %384)::Float64 │ %386 = Core.getfield(#self#, :br_b)::Dict{Int64, Float64} │ %387 = Base.getindex(%386, l@_39)::Float64 │ %388 = -%387::Float64 │ %389 = Core.getfield(#self#, :br_tr)::Dict{Int64, Float64} │ %390 = Base.getindex(%389, l@_39)::Float64 │ %391 = (%388 * %390)::Float64 │ %392 = Core.getfield(#self#, :br_g)::Dict{Int64, Float64} │ %393 = Base.getindex(%392, l@_39)::Float64 │ %394 = Core.getfield(#self#, :br_ti)::Dict{Int64, Float64} │ %395 = Base.getindex(%394, l@_39)::Float64 │ %396 = (%393 * %395)::Float64 │ %397 = (%391 + %396)::Float64 │ %398 = Core.getfield(#self#, :br_ttm)::Dict{Int64, Float64} │ %399 = Base.getindex(%398, l@_39)::Float64 │ %400 = (%397 / %399)::Float64 │ %401 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %402 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64} │ %403 = Base.getindex(%402, l@_39)::Int64 │ %404 = Base.getindex(%401, %403)::Int64 │ %405 = Base.getindex(x, %404)::Float64 │ %406 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %407 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64} │ %408 = Base.getindex(%407, l@_39)::Int64 │ %409 = Base.getindex(%406, %408)::Int64 │ %410 = Base.getindex(x, %409)::Float64 │ %411 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64} │ %412 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64} │ %413 = Base.getindex(%412, l@_39)::Int64 │ %414 = Base.getindex(%411, %413)::Int64 │ %415 = Base.getindex(x, %414)::Float64 │ %416 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64} │ %417 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64} │ %418 = Base.getindex(%417, l@_39)::Int64 │ %419 = Base.getindex(%416, %418)::Int64 │ %420 = Base.getindex(x, %419)::Float64 │ %421 = (%415 - %420)::Float64 │ %422 = Main.sin(%421)::Float64 │ %423 = (%405 * %410 * %422)::Float64 │ %424 = (%400 * %423)::Float64 │ %425 = (%346 + %385 + %424)::Float64 │ %426 = Core.getfield(#self#, :p_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64} │ %427 = Core.tuple(l@_39, i@_38, j@_37)::Tuple{Int64, Int64, Int64} │ %428 = Base.getindex(%426, %427)::Int64 │ %429 = Base.getindex(x, %428)::Float64 │ %430 = (%425 - %429)::Float64 │ %431 = (reti@_40 + offsetidx)::Int64 │ Base.setindex!(ret, %430, %431) │ (@_10 = Base.iterate(%311, %331)) │ %434 = (@_10 === nothing)::Bool │ %435 = Base.not_int(%434)::Bool └─── goto #16 if not %435 15 ─ goto #14 16 ┄ %438 = offsetidx::Int64 │ %439 = Core.getfield(#self#, :ref_arcs_to)::Vector{Tuple{Int64, Int64, Int64}} │ %440 = Main.length(%439)::Int64 │ (offsetidx = %438 + %440) │ %442 = Core.getfield(#self#, :ref_arcs_from)::Vector{Tuple{Int64, Int64, Int64}} │ %443 = Main.enumerate(%442)::Base.Iterators.Enumerate{Vector{Tuple{Int64, Int64, Int64}}} │ (@_9 = Base.iterate(%443)) │ %445 = (@_9 === nothing)::Bool │ %446 = Base.not_int(%445)::Bool └─── goto #19 if not %446 17 ┄ %448 = @_9::Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}} │ %449 = Core.getfield(%448, 1)::Tuple{Int64, Tuple{Int64, Int64, Int64}} │ %450 = Base.indexed_iterate(%449, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)]) │ (reti@_46 = Core.getfield(%450, 1)) │ (@_42 = Core.getfield(%450, 2)) │ %453 = Base.indexed_iterate(%449, 2, @_42::Core.Const(2))::Core.PartialStruct(Tuple{Tuple{Int64, Int64, Int64}, Int64}, Any[Tuple{Int64, Int64, Int64}, Core.Const(3)]) │ %454 = Core.getfield(%453, 1)::Tuple{Int64, Int64, Int64} │ %455 = Base.indexed_iterate(%454, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)]) │ (l@_45 = Core.getfield(%455, 1)) │ (@_41 = Core.getfield(%455, 2)) │ %458 = Base.indexed_iterate(%454, 2, @_41::Core.Const(2))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(3)]) │ (i@_44 = Core.getfield(%458, 1)) │ (@_41 = Core.getfield(%458, 2)) │ %461 = Base.indexed_iterate(%454, 3, @_41::Core.Const(3))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(4)]) │ (j@_43 = Core.getfield(%461, 1)) │ %463 = Core.getfield(%448, 2)::Tuple{Int64, Int64} │ %464 = Core.getfield(#self#, :br_b)::Dict{Int64, Float64} │ %465 = Base.getindex(%464, l@_45)::Float64 │ %466 = Core.getfield(#self#, :br_b_fr)::Dict{Int64, Float64} │ %467 = Base.getindex(%466, l@_45)::Float64 │ %468 = (%465 + %467)::Float64 │ %469 = -%468::Float64 │ %470 = Core.getfield(#self#, :br_ttm)::Dict{Int64, Float64} │ %471 = Base.getindex(%470, l@_45)::Float64 │ %472 = (%469 / %471)::Float64 │ %473 = Main.:^::Core.Const(^) │ %474 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %475 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64} │ %476 = Base.getindex(%475, l@_45)::Int64 │ %477 = Base.getindex(%474, %476)::Int64 │ %478 = Base.getindex(x, %477)::Float64 │ %479 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2}) │ %480 = (%479)()::Core.Const(Val{2}()) │ %481 = Base.literal_pow(%473, %478, %480)::Float64 │ %482 = (%472 * %481)::Float64 │ %483 = Core.getfield(#self#, :br_b)::Dict{Int64, Float64} │ %484 = Base.getindex(%483, l@_45)::Float64 │ %485 = -%484::Float64 │ %486 = Core.getfield(#self#, :br_tr)::Dict{Int64, Float64} │ %487 = Base.getindex(%486, l@_45)::Float64 │ %488 = (%485 * %487)::Float64 │ %489 = Core.getfield(#self#, :br_g)::Dict{Int64, Float64} │ %490 = Base.getindex(%489, l@_45)::Float64 │ %491 = Core.getfield(#self#, :br_ti)::Dict{Int64, Float64} │ %492 = Base.getindex(%491, l@_45)::Float64 │ %493 = (%490 * %492)::Float64 │ %494 = (%488 - %493)::Float64 │ %495 = Core.getfield(#self#, :br_ttm)::Dict{Int64, Float64} │ %496 = Base.getindex(%495, l@_45)::Float64 │ %497 = (%494 / %496)::Float64 │ %498 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %499 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64} │ %500 = Base.getindex(%499, l@_45)::Int64 │ %501 = Base.getindex(%498, %500)::Int64 │ %502 = Base.getindex(x, %501)::Float64 │ %503 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %504 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64} │ %505 = Base.getindex(%504, l@_45)::Int64 │ %506 = Base.getindex(%503, %505)::Int64 │ %507 = Base.getindex(x, %506)::Float64 │ %508 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64} │ %509 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64} │ %510 = Base.getindex(%509, l@_45)::Int64 │ %511 = Base.getindex(%508, %510)::Int64 │ %512 = Base.getindex(x, %511)::Float64 │ %513 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64} │ %514 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64} │ %515 = Base.getindex(%514, l@_45)::Int64 │ %516 = Base.getindex(%513, %515)::Int64 │ %517 = Base.getindex(x, %516)::Float64 │ %518 = (%512 - %517)::Float64 │ %519 = Main.cos(%518)::Float64 │ %520 = (%502 * %507 * %519)::Float64 │ %521 = (%497 * %520)::Float64 │ %522 = (%482 - %521)::Float64 │ %523 = Core.getfield(#self#, :br_g)::Dict{Int64, Float64} │ %524 = Base.getindex(%523, l@_45)::Float64 │ %525 = -%524::Float64 │ %526 = Core.getfield(#self#, :br_tr)::Dict{Int64, Float64} │ %527 = Base.getindex(%526, l@_45)::Float64 │ %528 = (%525 * %527)::Float64 │ %529 = Core.getfield(#self#, :br_b)::Dict{Int64, Float64} │ %530 = Base.getindex(%529, l@_45)::Float64 │ %531 = Core.getfield(#self#, :br_ti)::Dict{Int64, Float64} │ %532 = Base.getindex(%531, l@_45)::Float64 │ %533 = (%530 * %532)::Float64 │ %534 = (%528 + %533)::Float64 │ %535 = Core.getfield(#self#, :br_ttm)::Dict{Int64, Float64} │ %536 = Base.getindex(%535, l@_45)::Float64 │ %537 = (%534 / %536)::Float64 │ %538 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %539 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64} │ %540 = Base.getindex(%539, l@_45)::Int64 │ %541 = Base.getindex(%538, %540)::Int64 │ %542 = Base.getindex(x, %541)::Float64 │ %543 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %544 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64} │ %545 = Base.getindex(%544, l@_45)::Int64 │ %546 = Base.getindex(%543, %545)::Int64 │ %547 = Base.getindex(x, %546)::Float64 │ %548 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64} │ %549 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64} │ %550 = Base.getindex(%549, l@_45)::Int64 │ %551 = Base.getindex(%548, %550)::Int64 │ %552 = Base.getindex(x, %551)::Float64 │ %553 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64} │ %554 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64} │ %555 = Base.getindex(%554, l@_45)::Int64 │ %556 = Base.getindex(%553, %555)::Int64 │ %557 = Base.getindex(x, %556)::Float64 │ %558 = (%552 - %557)::Float64 │ %559 = Main.sin(%558)::Float64 │ %560 = (%542 * %547 * %559)::Float64 │ %561 = (%537 * %560)::Float64 │ %562 = (%522 + %561)::Float64 │ %563 = Core.getfield(#self#, :q_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64} │ %564 = Core.tuple(l@_45, i@_44, j@_43)::Tuple{Int64, Int64, Int64} │ %565 = Base.getindex(%563, %564)::Int64 │ %566 = Base.getindex(x, %565)::Float64 │ %567 = (%562 - %566)::Float64 │ %568 = (reti@_46 + offsetidx)::Int64 │ Base.setindex!(ret, %567, %568) │ (@_9 = Base.iterate(%443, %463)) │ %571 = (@_9 === nothing)::Bool │ %572 = Base.not_int(%571)::Bool └─── goto #19 if not %572 18 ─ goto #17 19 ┄ %575 = offsetidx::Int64 │ %576 = Core.getfield(#self#, :ref_arcs_from)::Vector{Tuple{Int64, Int64, Int64}} │ %577 = Main.length(%576)::Int64 │ (offsetidx = %575 + %577) │ %579 = Core.getfield(#self#, :ref_arcs_to)::Vector{Tuple{Int64, Int64, Int64}} │ %580 = Main.enumerate(%579)::Base.Iterators.Enumerate{Vector{Tuple{Int64, Int64, Int64}}} │ (@_8 = Base.iterate(%580)) │ %582 = (@_8 === nothing)::Bool │ %583 = Base.not_int(%582)::Bool └─── goto #22 if not %583 20 ┄ %585 = @_8::Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}} │ %586 = Core.getfield(%585, 1)::Tuple{Int64, Tuple{Int64, Int64, Int64}} │ %587 = Base.indexed_iterate(%586, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)]) │ (reti@_52 = Core.getfield(%587, 1)) │ (@_48 = Core.getfield(%587, 2)) │ %590 = Base.indexed_iterate(%586, 2, @_48::Core.Const(2))::Core.PartialStruct(Tuple{Tuple{Int64, Int64, Int64}, Int64}, Any[Tuple{Int64, Int64, Int64}, Core.Const(3)]) │ %591 = Core.getfield(%590, 1)::Tuple{Int64, Int64, Int64} │ %592 = Base.indexed_iterate(%591, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)]) │ (l@_51 = Core.getfield(%592, 1)) │ (@_47 = Core.getfield(%592, 2)) │ %595 = Base.indexed_iterate(%591, 2, @_47::Core.Const(2))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(3)]) │ (i@_50 = Core.getfield(%595, 1)) │ (@_47 = Core.getfield(%595, 2)) │ %598 = Base.indexed_iterate(%591, 3, @_47::Core.Const(3))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(4)]) │ (j@_49 = Core.getfield(%598, 1)) │ %600 = Core.getfield(%585, 2)::Tuple{Int64, Int64} │ %601 = Core.getfield(#self#, :br_b)::Dict{Int64, Float64} │ %602 = Base.getindex(%601, l@_51)::Float64 │ %603 = Core.getfield(#self#, :br_b_to)::Dict{Int64, Float64} │ %604 = Base.getindex(%603, l@_51)::Float64 │ %605 = (%602 + %604)::Float64 │ %606 = -%605::Float64 │ %607 = Main.:^::Core.Const(^) │ %608 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %609 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64} │ %610 = Base.getindex(%609, l@_51)::Int64 │ %611 = Base.getindex(%608, %610)::Int64 │ %612 = Base.getindex(x, %611)::Float64 │ %613 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2}) │ %614 = (%613)()::Core.Const(Val{2}()) │ %615 = Base.literal_pow(%607, %612, %614)::Float64 │ %616 = (%606 * %615)::Float64 │ %617 = Core.getfield(#self#, :br_b)::Dict{Int64, Float64} │ %618 = Base.getindex(%617, l@_51)::Float64 │ %619 = -%618::Float64 │ %620 = Core.getfield(#self#, :br_tr)::Dict{Int64, Float64} │ %621 = Base.getindex(%620, l@_51)::Float64 │ %622 = (%619 * %621)::Float64 │ %623 = Core.getfield(#self#, :br_g)::Dict{Int64, Float64} │ %624 = Base.getindex(%623, l@_51)::Float64 │ %625 = Core.getfield(#self#, :br_ti)::Dict{Int64, Float64} │ %626 = Base.getindex(%625, l@_51)::Float64 │ %627 = (%624 * %626)::Float64 │ %628 = (%622 + %627)::Float64 │ %629 = Core.getfield(#self#, :br_ttm)::Dict{Int64, Float64} │ %630 = Base.getindex(%629, l@_51)::Float64 │ %631 = (%628 / %630)::Float64 │ %632 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %633 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64} │ %634 = Base.getindex(%633, l@_51)::Int64 │ %635 = Base.getindex(%632, %634)::Int64 │ %636 = Base.getindex(x, %635)::Float64 │ %637 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %638 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64} │ %639 = Base.getindex(%638, l@_51)::Int64 │ %640 = Base.getindex(%637, %639)::Int64 │ %641 = Base.getindex(x, %640)::Float64 │ %642 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64} │ %643 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64} │ %644 = Base.getindex(%643, l@_51)::Int64 │ %645 = Base.getindex(%642, %644)::Int64 │ %646 = Base.getindex(x, %645)::Float64 │ %647 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64} │ %648 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64} │ %649 = Base.getindex(%648, l@_51)::Int64 │ %650 = Base.getindex(%647, %649)::Int64 │ %651 = Base.getindex(x, %650)::Float64 │ %652 = (%646 - %651)::Float64 │ %653 = Main.cos(%652)::Float64 │ %654 = (%636 * %641 * %653)::Float64 │ %655 = (%631 * %654)::Float64 │ %656 = (%616 - %655)::Float64 │ %657 = Core.getfield(#self#, :br_g)::Dict{Int64, Float64} │ %658 = Base.getindex(%657, l@_51)::Float64 │ %659 = -%658::Float64 │ %660 = Core.getfield(#self#, :br_tr)::Dict{Int64, Float64} │ %661 = Base.getindex(%660, l@_51)::Float64 │ %662 = (%659 * %661)::Float64 │ %663 = Core.getfield(#self#, :br_b)::Dict{Int64, Float64} │ %664 = Base.getindex(%663, l@_51)::Float64 │ %665 = Core.getfield(#self#, :br_ti)::Dict{Int64, Float64} │ %666 = Base.getindex(%665, l@_51)::Float64 │ %667 = (%664 * %666)::Float64 │ %668 = (%662 - %667)::Float64 │ %669 = Core.getfield(#self#, :br_ttm)::Dict{Int64, Float64} │ %670 = Base.getindex(%669, l@_51)::Float64 │ %671 = (%668 / %670)::Float64 │ %672 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %673 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64} │ %674 = Base.getindex(%673, l@_51)::Int64 │ %675 = Base.getindex(%672, %674)::Int64 │ %676 = Base.getindex(x, %675)::Float64 │ %677 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64} │ %678 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64} │ %679 = Base.getindex(%678, l@_51)::Int64 │ %680 = Base.getindex(%677, %679)::Int64 │ %681 = Base.getindex(x, %680)::Float64 │ %682 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64} │ %683 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64} │ %684 = Base.getindex(%683, l@_51)::Int64 │ %685 = Base.getindex(%682, %684)::Int64 │ %686 = Base.getindex(x, %685)::Float64 │ %687 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64} │ %688 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64} │ %689 = Base.getindex(%688, l@_51)::Int64 │ %690 = Base.getindex(%687, %689)::Int64 │ %691 = Base.getindex(x, %690)::Float64 │ %692 = (%686 - %691)::Float64 │ %693 = Main.sin(%692)::Float64 │ %694 = (%676 * %681 * %693)::Float64 │ %695 = (%671 * %694)::Float64 │ %696 = (%656 + %695)::Float64 │ %697 = Core.getfield(#self#, :q_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64} │ %698 = Core.tuple(l@_51, i@_50, j@_49)::Tuple{Int64, Int64, Int64} │ %699 = Base.getindex(%697, %698)::Int64 │ %700 = Base.getindex(x, %699)::Float64 │ %701 = (%696 - %700)::Float64 │ %702 = (reti@_52 + offsetidx)::Int64 │ Base.setindex!(ret, %701, %702) │ (@_8 = Base.iterate(%580, %600)) │ %705 = (@_8 === nothing)::Bool │ %706 = Base.not_int(%705)::Bool └─── goto #22 if not %706 21 ─ goto #20 22 ┄ %709 = offsetidx::Int64 │ %710 = Core.getfield(#self#, :ref_arcs_to)::Vector{Tuple{Int64, Int64, Int64}} │ %711 = Main.length(%710)::Int64 │ (offsetidx = %709 + %711) │ %713 = Core.getfield(#self#, :ref_arcs_from)::Vector{Tuple{Int64, Int64, Int64}} │ %714 = Main.enumerate(%713)::Base.Iterators.Enumerate{Vector{Tuple{Int64, Int64, Int64}}} │ (@_7 = Base.iterate(%714)) │ %716 = (@_7 === nothing)::Bool │ %717 = Base.not_int(%716)::Bool └─── goto #25 if not %717 23 ┄ %719 = @_7::Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}} │ %720 = Core.getfield(%719, 1)::Tuple{Int64, Tuple{Int64, Int64, Int64}} │ %721 = Base.indexed_iterate(%720, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)]) │ (reti@_58 = Core.getfield(%721, 1)) │ (@_54 = Core.getfield(%721, 2)) │ %724 = Base.indexed_iterate(%720, 2, @_54::Core.Const(2))::Core.PartialStruct(Tuple{Tuple{Int64, Int64, Int64}, Int64}, Any[Tuple{Int64, Int64, Int64}, Core.Const(3)]) │ %725 = Core.getfield(%724, 1)::Tuple{Int64, Int64, Int64} │ %726 = Base.indexed_iterate(%725, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)]) │ (l@_57 = Core.getfield(%726, 1)) │ (@_53 = Core.getfield(%726, 2)) │ %729 = Base.indexed_iterate(%725, 2, @_53::Core.Const(2))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(3)]) │ (i@_56 = Core.getfield(%729, 1)) │ (@_53 = Core.getfield(%729, 2)) │ %732 = Base.indexed_iterate(%725, 3, @_53::Core.Const(3))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(4)]) │ (j@_55 = Core.getfield(%732, 1)) │ %734 = Core.getfield(%719, 2)::Tuple{Int64, Int64} │ %735 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64} │ %736 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64} │ %737 = Base.getindex(%736, l@_57)::Int64 │ %738 = Base.getindex(%735, %737)::Int64 │ %739 = Base.getindex(x, %738)::Float64 │ %740 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64} │ %741 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64} │ %742 = Base.getindex(%741, l@_57)::Int64 │ %743 = Base.getindex(%740, %742)::Int64 │ %744 = Base.getindex(x, %743)::Float64 │ %745 = (%739 - %744)::Float64 │ %746 = (reti@_58 + offsetidx)::Int64 │ Base.setindex!(ret, %745, %746) │ (@_7 = Base.iterate(%714, %734)) │ %749 = (@_7 === nothing)::Bool │ %750 = Base.not_int(%749)::Bool └─── goto #25 if not %750 24 ─ goto #23 25 ┄ %753 = offsetidx::Int64 │ %754 = Core.getfield(#self#, :ref_arcs_from)::Vector{Tuple{Int64, Int64, Int64}} │ %755 = Main.length(%754)::Int64 │ (offsetidx = %753 + %755) │ %757 = Core.getfield(#self#, :ref_arcs_from)::Vector{Tuple{Int64, Int64, Int64}} │ %758 = Main.enumerate(%757)::Base.Iterators.Enumerate{Vector{Tuple{Int64, Int64, Int64}}} │ (@_6 = Base.iterate(%758)) │ %760 = (@_6 === nothing)::Bool │ %761 = Base.not_int(%760)::Bool └─── goto #28 if not %761 26 ┄ %763 = @_6::Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}} │ %764 = Core.getfield(%763, 1)::Tuple{Int64, Tuple{Int64, Int64, Int64}} │ %765 = Base.indexed_iterate(%764, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)]) │ (reti@_64 = Core.getfield(%765, 1)) │ (@_60 = Core.getfield(%765, 2)) │ %768 = Base.indexed_iterate(%764, 2, @_60::Core.Const(2))::Core.PartialStruct(Tuple{Tuple{Int64, Int64, Int64}, Int64}, Any[Tuple{Int64, Int64, Int64}, Core.Const(3)]) │ %769 = Core.getfield(%768, 1)::Tuple{Int64, Int64, Int64} │ %770 = Base.indexed_iterate(%769, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)]) │ (l@_63 = Core.getfield(%770, 1)) │ (@_59 = Core.getfield(%770, 2)) │ %773 = Base.indexed_iterate(%769, 2, @_59::Core.Const(2))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(3)]) │ (i@_62 = Core.getfield(%773, 1)) │ (@_59 = Core.getfield(%773, 2)) │ %776 = Base.indexed_iterate(%769, 3, @_59::Core.Const(3))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(4)]) │ (j@_61 = Core.getfield(%776, 1)) │ %778 = Core.getfield(%763, 2)::Tuple{Int64, Int64} │ %779 = Main.:^::Core.Const(^) │ %780 = Core.getfield(#self#, :p_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64} │ %781 = Core.tuple(l@_63, i@_62, j@_61)::Tuple{Int64, Int64, Int64} │ %782 = Base.getindex(%780, %781)::Int64 │ %783 = Base.getindex(x, %782)::Float64 │ %784 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2}) │ %785 = (%784)()::Core.Const(Val{2}()) │ %786 = Base.literal_pow(%779, %783, %785)::Float64 │ %787 = Main.:^::Core.Const(^) │ %788 = Core.getfield(#self#, :q_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64} │ %789 = Core.tuple(l@_63, i@_62, j@_61)::Tuple{Int64, Int64, Int64} │ %790 = Base.getindex(%788, %789)::Int64 │ %791 = Base.getindex(x, %790)::Float64 │ %792 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2}) │ %793 = (%792)()::Core.Const(Val{2}()) │ %794 = Base.literal_pow(%787, %791, %793)::Float64 │ %795 = (%786 + %794)::Float64 │ %796 = (reti@_64 + offsetidx)::Int64 │ Base.setindex!(ret, %795, %796) │ (@_6 = Base.iterate(%758, %778)) │ %799 = (@_6 === nothing)::Bool │ %800 = Base.not_int(%799)::Bool └─── goto #28 if not %800 27 ─ goto #26 28 ┄ %803 = offsetidx::Int64 │ %804 = Core.getfield(#self#, :ref_arcs_from)::Vector{Tuple{Int64, Int64, Int64}} │ %805 = Main.length(%804)::Int64 │ (offsetidx = %803 + %805) │ %807 = Core.getfield(#self#, :ref_arcs_to)::Vector{Tuple{Int64, Int64, Int64}} │ %808 = Main.enumerate(%807)::Base.Iterators.Enumerate{Vector{Tuple{Int64, Int64, Int64}}} │ (@_5 = Base.iterate(%808)) │ %810 = (@_5 === nothing)::Bool │ %811 = Base.not_int(%810)::Bool └─── goto #31 if not %811 29 ┄ %813 = @_5::Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}} │ %814 = Core.getfield(%813, 1)::Tuple{Int64, Tuple{Int64, Int64, Int64}} │ %815 = Base.indexed_iterate(%814, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)]) │ (reti@_70 = Core.getfield(%815, 1)) │ (@_66 = Core.getfield(%815, 2)) │ %818 = Base.indexed_iterate(%814, 2, @_66::Core.Const(2))::Core.PartialStruct(Tuple{Tuple{Int64, Int64, Int64}, Int64}, Any[Tuple{Int64, Int64, Int64}, Core.Const(3)]) │ %819 = Core.getfield(%818, 1)::Tuple{Int64, Int64, Int64} │ %820 = Base.indexed_iterate(%819, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)]) │ (l@_69 = Core.getfield(%820, 1)) │ (@_65 = Core.getfield(%820, 2)) │ %823 = Base.indexed_iterate(%819, 2, @_65::Core.Const(2))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(3)]) │ (i@_68 = Core.getfield(%823, 1)) │ (@_65 = Core.getfield(%823, 2)) │ %826 = Base.indexed_iterate(%819, 3, @_65::Core.Const(3))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(4)]) │ (j@_67 = Core.getfield(%826, 1)) │ %828 = Core.getfield(%813, 2)::Tuple{Int64, Int64} │ %829 = Main.:^::Core.Const(^) │ %830 = Core.getfield(#self#, :p_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64} │ %831 = Core.tuple(l@_69, i@_68, j@_67)::Tuple{Int64, Int64, Int64} │ %832 = Base.getindex(%830, %831)::Int64 │ %833 = Base.getindex(x, %832)::Float64 │ %834 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2}) │ %835 = (%834)()::Core.Const(Val{2}()) │ %836 = Base.literal_pow(%829, %833, %835)::Float64 │ %837 = Main.:^::Core.Const(^) │ %838 = Core.getfield(#self#, :q_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64} │ %839 = Core.tuple(l@_69, i@_68, j@_67)::Tuple{Int64, Int64, Int64} │ %840 = Base.getindex(%838, %839)::Int64 │ %841 = Base.getindex(x, %840)::Float64 │ %842 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2}) │ %843 = (%842)()::Core.Const(Val{2}()) │ %844 = Base.literal_pow(%837, %841, %843)::Float64 │ %845 = (%836 + %844)::Float64 │ %846 = (reti@_70 + offsetidx)::Int64 │ Base.setindex!(ret, %845, %846) │ (@_5 = Base.iterate(%808, %828)) │ %849 = (@_5 === nothing)::Bool │ %850 = Base.not_int(%849)::Bool └─── goto #31 if not %850 30 ─ goto #29 31 ┄ %853 = offsetidx::Int64 │ %854 = Core.getfield(#self#, :ref_arcs_to)::Vector{Tuple{Int64, Int64, Int64}} │ %855 = Main.length(%854)::Int64 │ (offsetidx = %853 + %855) │ %857 = offsetidx::Int64 │ %858 = Main.length(ret)::Int64 │ %859 = (%857 == %858)::Bool └─── goto #33 if not %859 32 ─ goto #34 33 ─ %862 = Base.AssertionError("offsetidx == length(ret)")::Any └─── Base.throw(%862) 34 ┄ return Main.nothing ``` In theory it should be possible to use Enzyme here now.
For now, I'd take the current ODE Bayesian Parameter estimation benchmarks offline and stop quoting them as up-to date evidence that Julia is currently 3-5 times faster than Stan for ODE problems. If I knew Julia better I'd fix them, but I don't, so here are the issues with them that I currently know:
parameters = sigma1.1, sigma1.2, theta_1, theta_2, theta_3, theta_4
for Stan andparameters = theta[1], theta[2], theta[3], theta[4], σ[1]
for Turing)adapt_delta=.85
(its default) while Turing uses "adapt_delta=.65
", which potentially lowers runtime but also ESSThe text was updated successfully, but these errors were encountered: