Page 1 of 1

Speeding up constraint creation during compilation

Posted: Tue Jun 04, 2019 7:18 pm
by james82
Hi everyone

So I have a constraint like

Code: Select all

eq_uc_gen_minup(h,z,non_vre) .. sum(h_alias$(ord(h_alias) ge (ord(h) - gen_minup(non_vre)+1) and ord(h_alias) lt ord(h)),var_up_units(h_alias,z,non_vre)) =L= var_com_units(h,z,non_vre)



The parameter gen_minup(non_vre) is in the range of 2-24. Sets z and non_vre have 20 and 3 elements respectively.

The constraint is quite computationally expensive time wise during the compile step of my model. I'm guessing this is because h contains at a minimum 8760 elements. Have I missed anything in terms of set ordering in the variable that could speed this up? Or indeed anything else that could speed this up?

I note that in the full version of my model I already limit the creation of the constraint to the smallest number of z and non_vre combinations I can using $ subset.


Re: Speeding up constraint creation during compilation

Posted: Wed Jun 05, 2019 12:11 pm
by Fred

The crux is that you are making a lot of comparisons (in the range of card(h) x card(h)) in the equation body. Also, you are doing that for every z where the condition is completely independent from z.
It is faster to precompute a mapping set outside the equation body.
Basically you want for every pair (h,non_vre) from the quation domain, the corresponing elements of h_alias. So you could take the dollar condition from the equation to get a 3 dimensional mapping map(h,non_vre,h_alias):

version 1:

Code: Select all

set map1(h,non_vre,h);
map1(h,non_vre,h_alias) = ord(h_alias) ge (ord(h) - gen_minup(non_vre)+1) and ord(h_alias) lt ord(h);
eq_uc_gen_minup1(h,z,non_vre) .. sum(map1(h,non_vre,h_alias), var_up_units(h_alias,z,non_vre)) =L= var_com_units(h,z,non_vre);
While that speeds up the generation of the equation, calculatig the mapping map1 is expensive.
You can speed that up using some tricks in combination with lag and lead operators:

You mention that gen_minup(non_vre) takes at most a value of 24. That means for a particular h (let's say h100), you do not have to look at h_alias=h1...h8760 but only at the 24 preceeding elements h76...h99. This is a bit tricky but doable:

version 2:

Code: Select all

set map2(h,non_vre,h)
    hh(h) max minup hours / h1*h24 /;
map2(h,non_vre,h_alias+(ord(h)-gen_minup(non_vre)))$[hh(h_alias) and ord (h_alias)<gen_minup(non_vre)] = yes;
I attached an example, that generates some dummy models consisting only of that particular equation (plus a dummy objective). It allows easy experiments with the different formulations. I also enabled profiling ( ... SAOprofile) in this example. You don't say anything about the cardinality of sets z and non_vre. With cardinality 5 for both sets we get a the following profile summary

Code: Select all

--- Profile Summary (38 records processed)
   167.421   0.429GB        38 Equation   eq_uc_gen_minup (219000)
    27.141   0.017GB        22 Assignment map1 (463887)
     0.703   0.475GB        40 Equation   eq_uc_gen_minup1 (219000)
     0.703   0.491GB        42 Equation   eq_uc_gen_minup2 (219000)
Generating the original equation takes 167.421 seconds. This is reduced to 0.703 seconds with a precomputed mapping where computing the mapping like in version 1 takes 27.141 seconds while in version 2 this step takes about 0.1 seconds and is too fast to show up in the profile summary.

I hope this helps!


Re: Speeding up constraint creation during compilation

Posted: Mon Jun 10, 2019 1:09 pm
by james82
Hi Fred

Thank you very much for your response - this certainly solves the issue I was having with slow model generation. That is a nice trick for the map set creation, really good to know.

Thanks again.