pythonpyomolinear-optimization

Linear optimization with pyomo


I recently started to try and learn python in order to solve a linear optimization problem. I am trying to minimize the CO2-Emission for househould. The solver is supposed to choose between getting electricity from the grid (which includes a certain amount of co2) and the produced electricity from pv. Sadly I seem to be too stupid to get it right and the solver keeps calculating it 8 times (the amount of timesteps) for every of the 8 timesteps.

This is a test version with only 8 timesteps just in order to test if I am able to pull it out of an excel instead of manually typing the dictionary myself.

As said before the programm is supposed to always equal the demand by chosing between grid electricity ("Import") and PV-Electricity ("Eigenproduktion"). It is also supposed to do that over a duration of 8 hours.

data = pd.read_excel(Stromsimulation, skiprows = 1, usecols=('A:E'), index_col = 0)
df = pd.DataFrame(data)
daten = df.to_dict()
model = ConcreteModel()

model.n = RangeSet(1, 8)

model.verbrauch = Param(model.n, initialize = daten['Verbrauch'])
model.eigenproduktion = Param(model.n, initialize = daten['Eigenproduktion'])
model.stromimport = Param(model.n, initialize = daten['Import'])
model.emissionen = Param(model.n, initialize = daten['CO2-Emissionen'])

model.x = Var(model.n, within = NonNegativeReals)

def emissionsreduzierung(model, t):
  return sum(((model.x[t] * model.stromimport[t]) * model.emissionen[t] for t in model.n))
model.emissionsreduzierung = Objective(rule = emissionsreduzierung, sense = minimize)

def lastdeckung(model, t):
  return (sum(model.eigenproduktion[t] + (model.stromimport[t] * model.x[t]) for t in model.n) == model.verbrauch[t])
model.lastdeckung = Constraint(model.n, rule = lastdeckung)

For some reason it keeps doing this:

1 Objective Declarations
    emissionsreduzierung : Size=1, Index=None, Active=True
        Key  : Active : Sense    : Expression
        None :   True : minimize : 30.0*x[1] + 15.0*x[2] + 45.0*x[3] + 30.0*x[4] + 22.5*x[5] + 49.5*x[6] + 52.5*x[7] + 60.0*x[8]

1 Constraint Declarations
    lastdeckung : Size=8, Index=n, Active=True
        Key : Lower : Body                                                                                                                       : Upper : Active
          1 :  30.0 : 5 + 150*x[1] + 8 + 150*x[2] + 9 + 150*x[3] + 10 + 150*x[4] + 15 + 150*x[5] + 21 + 150*x[6] + 30 + 150*x[7] + 25 + 150*x[8] :  30.0 :   True
          2 :  25.0 : 5 + 150*x[1] + 8 + 150*x[2] + 9 + 150*x[3] + 10 + 150*x[4] + 15 + 150*x[5] + 21 + 150*x[6] + 30 + 150*x[7] + 25 + 150*x[8] :  25.0 :   True
          3 :  35.0 : 5 + 150*x[1] + 8 + 150*x[2] + 9 + 150*x[3] + 10 + 150*x[4] + 15 + 150*x[5] + 21 + 150*x[6] + 30 + 150*x[7] + 25 + 150*x[8] :  35.0 :   True
          4 :  61.0 : 5 + 150*x[1] + 8 + 150*x[2] + 9 + 150*x[3] + 10 + 150*x[4] + 15 + 150*x[5] + 21 + 150*x[6] + 30 + 150*x[7] + 25 + 150*x[8] :  61.0 :   True
          5 :  42.0 : 5 + 150*x[1] + 8 + 150*x[2] + 9 + 150*x[3] + 10 + 150*x[4] + 15 + 150*x[5] + 21 + 150*x[6] + 30 + 150*x[7] + 25 + 150*x[8] :  42.0 :   True
          6 :  31.0 : 5 + 150*x[1] + 8 + 150*x[2] + 9 + 150*x[3] + 10 + 150*x[4] + 15 + 150*x[5] + 21 + 150*x[6] + 30 + 150*x[7] + 25 + 150*x[8] :  31.0 :   True
          7 :  54.0 : 5 + 150*x[1] + 8 + 150*x[2] + 9 + 150*x[3] + 10 + 150*x[4] + 15 + 150*x[5] + 21 + 150*x[6] + 30 + 150*x[7] + 25 + 150*x[8] :  54.0 :   True
          8 :  32.0 : 5 + 150*x[1] + 8 + 150*x[2] + 9 + 150*x[3] + 10 + 150*x[4] + 15 + 150*x[5] + 21 + 150*x[6] + 30 + 150*x[7] + 25 + 150*x[8] :  32.0 :   True

Solution

  • Your main problem is the following: The lastdeckung constraint is constructed 8 times, since that's what happens when you call it like Constraint(model.n, rule = lastdeckung): This translates to "for each of the n (time slots), call the function lastdeckung". That's what you want, since the energy balance equation needs to hold during each hour. However, at the same time you are adding the energy terms of all time slots n: sum(... for t in model.n). That does not make sense. Instead, use the t which is passed to the function in order to define the constraint for that given time slot:

    def lastdeckung(model, t):
      return model.eigenproduktion[t] + (model.stromimport[t] * model.x[t]) == model.verbrauch[t]
    model.lastdeckung = Constraint(model.n, rule = lastdeckung)