Using conditionals in @defsim, and add_RV! for vectors

I am setting up a Monte Carlo simulation, but I have a lot of different cases where different components may or may not be included or set to vary.

My first thought was just to include conditional statements in the @defsim, but the macro does not appear to be able to handle these.

So, I have used add_RV!, and that works for most of my cases. The problem is for vectors of random variables, like

OMH_uniforms[:] = Uniform(0, 1)

It looks like I ought to be able to use a statement like

add_RV!(sim, :OMH_uniforms, ReshapedDistribution([dim_count(model, :time)], Uniform(0, 1)))

but doing so throws a MethodError: no method matching length(::ReshapedDistribution) error. What’s the right way to do this?

1 Like

Hi @jrising this is an excellent question that I also struggled with while working on the GIVE mcs specification, and the same as you ended up creating a (almost) blank SimulationDefinition and then used pairs of add_RV! and add_transform!. In this case I was almost always applying one RV per element, as opposed to many elements to the same RV, which can be done I a similar but slightly different way. I think you also are trying to do the former.

Our GIVE one is here: MimiGIVE.jl/main_mcs.jl at main · rffscghg/MimiGIVE.jl · GitHub but this is something I’m happy to talk about further since I know it’s complicated and I would like to improve this aspect of Mimi … @defsim is quite restrictive.

My general approach was to loop over the individual elements, which were sometimes countries (like this: MimiGIVE.jl/main_mcs.jl at eaa9413d70dab7ad339ade0beb8ec734eb27a741 · rffscghg/MimiGIVE.jl · GitHub) and sometimes years (like this: MimiGIVE.jl/main_mcs.jl at eaa9413d70dab7ad339ade0beb8ec734eb27a741 · rffscghg/MimiGIVE.jl · GitHub) or even both in horrid cases :slight_smile:

The important part there is that I’m assigning one RV per element, not every element to the same RV. That second one is an option too with similar techniques (like what happens inside the macro when we use these techniques: 3 Monte Carlo + SA · Mimi.jl - Assigning to array slices and Assigning a vector of distributions) but I don’t think that’s your intention.

Now I admit I did this about 6 months ago, and I am now very curious to know if that’s really the best way or more efficient way, so I am now going to look at the macro code to think about if there’s a better way which I am sure there is … I just need to dig into the Mimi code a bit and the way the macro splices teh calls out into calls of add_RV! and add_transform!.

ReshapedDistribution seems like a good alternative approach to me … a Mimi developer (not me) created that type in Mimi and probably just didn’t define length so it’s a method I’d think we could just define. I’m embarrassed to say I forgot about that type as an option but think it does look promising. I will dig into this more today. I recreated your error with the code below

using Mimi, Distributions

@defcomp mycomp begin
    p = Parameter(index=[countries])
    function run_timestep(p,v,d,t)
    end
end

m = Model()
set_dimension!(m, :time, 2000:2010)
set_dimension!(m, :countries, [:a, :b, :c, :d, :e])
add_comp!(m, mycomp)
update_param!(m, :mycomp, :p, fill(1., 5))

sd = @defsim begin end
Mimi.add_RV!(sd, :rv_p, ReshapedDistribution([10], Uniform(0,1)))
Mimi.add_transform!(sd, :mycomp, :p, :(=), :rv_p)

run(sd, m, 10)

and will dig into it, but my gut would say that type isn’t very robust to different use cases and it might be preferable to try to mirror the methods I used ie. use loops to add one RV and one transform per vector element for now, although there may be a more efficient way that I can absolutely look into!