Handling variables and equations with different timesteps

Description of the issue

I have 2 sets i,j

i = m.addSet(name="j", records = ["January","February", "March"], description="months")
j = m.addSet(name="j", records=np.arange(1, 91), description="days in the 3 months") 

So I define a parameter over every day which is the daily demand.

Demand_param = m.addParameter("Demand_param" , j, records=Demand_list)    

Then I define a variable over the months which would be the capacity for the machinery. I do not want the variable to be defined over the hours’ set cause then it would be unrealistic.

Mach_cap= m.addVariable("Mach_capacity", "positive", i)

Then a variable about the production over the hours set.

Prod= m.addVariable("production", "positive", j)

Finally I need a constraint which will show the model that the production shall not exceed the capacity in an hourly basis. And that is where I have the most trouble. I tried this:

production_max= m.addEquation("produced_max",domain=[ i, j])
production_max[i,j]= (Mach_cap[i] >= Prod[j]) 

The thing is that with this way the model, will not “know” which hour (j), will correpsond to which monthly capacity (i).
I also tried mapping set i to j. The problem with that is that no element in gamspy (equations, variables etc.) can be defined over a multi-dimensional set apparently.
I do not want to sum up the whole monthly demand because then this would not gurantee that the demand is satisfied on a daily basis, but on a monthly.
Do you have any suggestions?

Hi,

You can set j as the days in the 3 months but you are referring to it as hours set. I couldn’t understand what you mean by that.

You can define parameters, variables, equations over multi-dimensional sets. Please see the documentation on Multi-dimensional sets

Muhammet

Hello,

Thank you for taking the time to answer. I did it by mistake it is indeed the days set which correpsonds to 3 months hence 90 elements in this set.
My main concern as I mentioned is for this specific constraint:

production_max= m.addEquation("produced_max",domain=[ i, j])
production_max[i,j]= (Mach_cap[i] >= Prod[j]) 

I can not find a way to specify that the first 30 elements of the set j correspond to the first element of the set i, the next 30 to the second element etc.

For the multisimensional sets, I wasn’t able to find an example of an equation or a variable that its domain has more than one dimensions, and everytime I try to implement such a thing on my code, it returns an error that says it was expecting for the domain to be 1 dimensional.

However multidimensional sets are not my main concern. My main concern remains the formulation of the constraint above in order to map correctly the elements of the set i to the ones of the set j.

There were more typos in code you shared. For example, you used the name “j” for set i and j. The name is not just something for nice printing but has a meaning in GAMSPy. In your case i and j were references to the same GAMSPy set “j” that contained the numbers 1…90. The content for the months was overwritten.

In any case, you can have a mapping (a two dimensional set) between month and days as follows:

import gamspy as gp

m = gp.Container()
i = m.addSet(name="i", records = ["January","February", "March"], description="months")
j = m.addSet(name="j", records=range(1, 91), description="days in the 3 months")
ijmap = m.addSet(name="ij", domain=[i,j], description="map between days and month")
ij = [ ('January', i) for i in range(1, 32) ]
ij = ij + [ ('February', i) for i in range(32, 61) ]
ij = ij + [ ('March', i) for i in range(61,91) ]
ijmap.setRecords(ij)

with that you can write your constraint like that

production_max[ijmap[i,j]]= (Mach_cap[i] >= Prod[j]) 

Hope this helps,
-Michael

Thanks for taking the time to respond Michael :slight_smile:

Yes you are correct, it was just a dummy code I created.

In any case I am new to GAMS and therefore I still face difficulties.
However I meant to share here for anyone else who might need it in the future the solution I found which is pretty similar.
Instead of putting the map set in the equation declaration, instead I incorporated it inside the definition of the equation like so.

production_max[i,j]= (Mach_cap[i] >= Prod[j]).where[ijmap[i,j]])

As you can see here I am using the map set you created and a conditional assignment. Nevertheless your solution is more elegant, thanks for pointing it out :slight_smile:

On a second note running this code you suggested:

import gamspy as gp

m = gp.Container()
i = m.addSet(name="i", records = ["January","February", "March"], description="months")
j = m.addSet(name="j", records=range(1, 91), description="days in the 3 months")
ijmap = m.addSet(name="ij", domain=[i,j], description="map between days and month")
ij = [ ('January', i) for i in range(1, 32) ]
ij = ij + [ ('February', i) for i in range(32, 61) ]
ij = ij + [ ('March', i) for i in range(61,91) ]
ijmap.setRecords(ij)

Mach_cap= m.addVariable("Mach_capacity", "positive", i)

Prod= m.addVariable("production", "positive", j)
production_max= m.addEquation("produced_max",domain=[ ijmap[i,j]])
production_max[ijmap[i,j]]= (Mach_cap[i] >= Prod[j])

I get back this error:
TypeError: All ‘domain’ elements must be type Set, Alias, UniverseAlias, or str

For the following equation:

production_max= m.addEquation("produced_max",domain=[ ijmap[i,j]])

Trying to avoid it I rewrite the last part of the code like so:

production_max= m.addEquation("produced_max",domain=[ ijmap])
production_max[ijmap]= (Mach_cap[i] >= Prod[j])

Which returns the error I initially mentioned:
ValueError: All linked ‘domain’ elements must have dimension == 1

I do not know if I am still doing something wrong or if my license (academic) has something to do with it. Nevertheless thank you for your time and if you find I am doing something wrong please let me know :slight_smile:

Your solution produces many trivial (and perhaps wrong equations in the case Mach_cap is not a positive variable). For all pairs i,j that are not in ijmap (e.g. March.1) this produces the equation production_max('March','1').. Mach_cap('March',1') =g= 0;. So having the set ijmap on “the left” is much better.

-Michael

Domain sets in GAMSPy are one-dimensional sets that help to find quickly typos in your code, e.g. if you type prod[j,i] but you meant prod[i,j]. They don’t help you to limit the possible pairs in some equation or in other parts of the code. So declare your equation over domain [i,j] and define your equation over set ijmap (or any other combination with sets or subsets of i and j).

Good luck,
-Michael