Right way to define a constraint

I am having difficulty in defining a constraint efficiently that is based on a matrix of decision variables. A MWE is given below but as you will see it creates a number of intermediate expressions, so it is not the best approach.

I think I am complicating it unnecessarily in the code below. Could this constraint be simplified?

rate = [0.02,0.025,0.03,0.035]
pd = [5.0,6.5,8.0,9.3,10.0,11.1,9.0,6.5,5.0,6.5]
id = [2.0,1.5,3.0,4.3,4.0,6.1,5.0,3.5,2.0,3.5]

model = Model()
@variable(model,p[i=1:4,j=1:10]>=0)
@expression(model,ex1[i=1:4,j=1:10],sum(p[i,t] for t in j:10))
@expression(model,ex2,rate .* ex1)
@expression(model,ex3[i=1:4,j=1:10],ex2[i,j]+p[i,j])
@constraint(model,constraint[j=1:10],sum(ex3[i,j] for i in 1:4)  <= pd[j] + id[j])

The constraint is based on a set of rules:
(1): I define a matrix of decision variables p[i=1:4,j=1:10]
(2): Create a matrix expression ex1 that calculates the cumulative sum of the decision variables by adding together elements to the right, ie. sum(p[i,t] for t in j:10)
(3): Multiply a vector containing data (rate) with ex1 and add the variable p[i,j]. This gives the expression ex3.
(4): Constraint is given by sum across the rows for each column in ex3 should be less than or equal to certain values.

but as you will see it creates a number of intermediate expressions, so it is not the best approach

Is the time to build the problem a bottleneck in your problem? If not, write the model that is the most readable to you. Only try improving performance if it the limiting factor.

Is there any reason not to write it just as:

model = Model()
@variable(model, p[1:4, 1:10] >= 0)
@expression(model, ex1[i=1:4, j=1:10], sum(p[i, t] for t in j:10))
@constraint(
    model,
    [j=1:10],
    sum(rate[i] * ex1[i, j] + p[i, j] for i in 1:4)  <= pd[j] + id[j],
)

In general, I wouldn’t expect the performance to be too different between the two approaches.

1 Like

Thank you.

Time to build the problem was not a bottleneck, but clarity was an issue. I thought I was creating too many intermediate expressions and code can be made concise. The answer you have provided is perfect.

1 Like