问题
I am trying to formulate some data into a PYOMO model for an optimization problem.
materials = ['steel', 'alum', 'carbon', 'cheese']
Each material has 2 properties - density and conductivity and their values are defined as follows.
density = { 'steel' : 1.2,
'alum' : 0.8,
'carbon': 1.8,
'cheese': 0.7}
conductivity = {'steel' : 6.4,
'alum' : 3.1,
'carbon': 4.4,
'cheese': 0.3}
The objective function calculates the weight of 2 rectangular plates as given below:
Objective function = Area_1 * thickness_1 * density_1 + Area_2 * thickness_2 * density_2
Where, the Area_1, thickness_1, and density_1 are area, thickness and density of plate 1.
Area and thickness are fixed for each plates. But the density value depends on the material chosen by the solver to get the best results. The model also have a constraint defined as follows:
(conductivity_1/thickness_1) + (conductivity_2/thickness_2) => 22
So, when the solver chooses a density value for a plate, it must also choose the conductivity value of the same material.
I would appreciate it if someone can help me with this problem. I also welcome if you have different ideas to solve this problem. Thank you.
回答1:
Here is an example model that I think meets all of your questions.
Once you set up the second index to be the plates P = {1, 2, 3}
in this case for 3 plates, then we need to double index our decision variable to represent the assignment of material m
to plate p
. In this example, 4 materials, 3 plates.
Many other variations of constraints are possible here, but the ones I added answer your question about conductivity in aggregate. Note that I have also added a constraint to ensure that 1 and only 1 material is assigned to each plate. You may/may not need this depending on other constraints in your model, but it is good insurance against bogus answers. This is also an example of the "for every" style of constraint using the function - rule combo in pyomo
.
The result... an aluminum and cheese sandwich... :)
# material selection model
import pyomo.environ as pyo
# data
materials = ['steel', 'alum', 'carbon', 'cheese']
density = { 'steel' : 1.2,
'alum' : 0.8,
'carbon': 1.8,
'cheese': 0.7}
conductivity = {'steel' : 40.8,
'alum' : 30.1,
'carbon': 42.4,
'cheese': 15.3}
price = { 'steel' : 2.3,
'alum' : 3.5,
'carbon': 5.8,
'cheese': 6.0}
# t area
plate_dims = { 1: (10, 150),
2: (12.5, 200),
3: (8, 125)}
mdl = pyo.ConcreteModel('material selector')
# SETS (used to index the decision variable and the parameters)
mdl.M = pyo.Set(initialize=materials)
mdl.P = pyo.Set(initialize=plate_dims.keys())
# VARIABLES
mdl.x = pyo.Var(mdl.M, mdl.P, domain=pyo.Binary) # select material M for plate P
# PARAMETERS
mdl.density = pyo.Param(mdl.M, initialize=density)
mdl.conductivity = pyo.Param(mdl.M, initialize=conductivity)
mdl.price = pyo.Param(mdl.M, initialize=price)
mdl.p_thickness = pyo.Param(mdl.P, initialize= {k:v[0] for k,v in plate_dims.items()})
mdl.p_area = pyo.Param(mdl.P, initialize= {k:v[1] for k,v in plate_dims.items()})
# OBJ (minimize total density)
mdl.obj = pyo.Objective(expr=sum(mdl.x[m, p] * mdl.p_thickness[p]
* mdl.p_area[p] * mdl.density[m]
for m in mdl.M for p in mdl.P))
# CONSTRAINTS
# minimum conductivity
mdl.c1 = pyo.Constraint(expr=sum(mdl.x[m, p] * mdl.conductivity[m]/mdl.p_thickness[p]
for m in mdl.M for p in mdl.P) >= 5.0)
# must populate all plates with 1 material
def c2(model, plate):
return sum(mdl.x[m, plate] for m in mdl.M) == 1
mdl.c2 = pyo.Constraint(mdl.P, rule=c2)
# solve it
solver = pyo.SolverFactory('glpk')
result = solver.solve(mdl)
mdl.display()
Yields:
Model material selector
Variables:
x : Size=12, Index=x_index
Key : Lower : Value : Upper : Fixed : Stale : Domain
('alum', 1) : 0 : 0.0 : 1 : False : False : Binary
('alum', 2) : 0 : 0.0 : 1 : False : False : Binary
('alum', 3) : 0 : 1.0 : 1 : False : False : Binary
('carbon', 1) : 0 : 0.0 : 1 : False : False : Binary
('carbon', 2) : 0 : 0.0 : 1 : False : False : Binary
('carbon', 3) : 0 : 0.0 : 1 : False : False : Binary
('cheese', 1) : 0 : 1.0 : 1 : False : False : Binary
('cheese', 2) : 0 : 1.0 : 1 : False : False : Binary
('cheese', 3) : 0 : 0.0 : 1 : False : False : Binary
('steel', 1) : 0 : 0.0 : 1 : False : False : Binary
('steel', 2) : 0 : 0.0 : 1 : False : False : Binary
('steel', 3) : 0 : 0.0 : 1 : False : False : Binary
Objectives:
obj : Size=1, Index=None, Active=True
Key : Active : Value
None : True : 3600.0
Constraints:
c1 : Size=1
Key : Lower : Body : Upper
None : 5.0 : 6.516500000000001 : None
c2 : Size=3
Key : Lower : Body : Upper
1 : 1.0 : 1.0 : 1.0
2 : 1.0 : 1.0 : 1.0
3 : 1.0 : 1.0 : 1.0
来源:https://stackoverflow.com/questions/65201147/pyomo-defining-dataset-using-sets-and-parameters-for-solving-an-optimization-pr