Search code examples
pythonpyomo

Defining specific set of values for 2 variables in PYOMO


I am trying to assign material property using multiple variables. For example; density and conductivity are two decision variables for material_1, material_2 and material_3.

I have to input the following information:

density of material_1 = 1000
density of material_2 = 2000
density of material_3 = 1500

conductivity of material_1 = 250
conductivity of material_2 = 400
conductivity of material_3 = 100

The standard format for defining variables in Pyomo is given below:

model.variable_1 = Var(bounds=(800,2000))

The above code means variable_1 is a variable with lower bound = 800, and upper bound = 2000.

But how can we define a variable with a specific set of values instead of a bound?

The idea is to input data values into the optimizer such that when it chooses a density value, it should also choose the conductivity value from the same material.

How can we impose such a condition into pyomo framework? Can someone please help me with this?


Solution

  • So if you are just selecting one of many options, you can set this up as an Integer Linear Program. The basic gist is that we let a binary variable x in the example below represent the act of selecting material i, where i is a member of the set of materials.

    In your question above, you seem to be struggling with the concept of separating the parameters in the model (price, density, conductivity, etc.) which are fixed in value from the variables which are the decisions you want to model.

    A slightly more advanced model than below might be a mixing model, where you can take proportions of various materials within some constraints, etc. which would require changing the domain of x to be non-negative real numbers. This one just models the binary action of selection. Of course in a model as trivial as this, you could just solve it with list/dictionary comprehensions or a filter, so using algebraic modeling is really overkill, but it is an example to differentiate the concepts you asked about.

    # 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' : 6.4,
                    'alum'  : 3.1,
                    'carbon': 4.4,
                    'cheese': 0.3}
    
    price =     {   'steel' : 2.3,
                    'alum'  : 3.5,
                    'carbon': 5.8,
                    'cheese': 6.0}
    
    m = pyo.ConcreteModel('material selector')
    
    # SETS (used to index the decision variable and the parameters)
    m.matl = pyo.Set(initialize=materials)
    
    # VARIABLES
    m.x = pyo.Var(m.matl, domain=pyo.Binary)   # a binary decision variable representing the selection of matl
    
    # PARAMETERS
    m.density = pyo.Param(m.matl, initialize=density)
    m.conductivity = pyo.Param(m.matl, initialize=conductivity)
    m.price = pyo.Param(m.matl, initialize=price)
    
    
    # OBJ (minimize price)
    m.obj = pyo.Objective(expr=sum(m.x[i] * m.price[i] for i in m.matl))
    
    # Constraints
    m.c1 = pyo.Constraint(expr=(sum(m.x[i] * m.density[i] for i in m.matl) >= 1.0))     # min density
    m.c2 = pyo.Constraint(expr=(sum(m.x[i] * m.conductivity[i] for i in m.matl) <= 5.0)) # max cond.
    
    # solve it
    solver = pyo.SolverFactory('glpk')
    result = solver.solve(m)
    m.display()
    

    Yields:

    Model material selector
    
      Variables:
        x : Size=4, Index=matl
            Key    : Lower : Value : Upper : Fixed : Stale : Domain
              alum :     0 :   0.0 :     1 : False : False : Binary
            carbon :     0 :   1.0 :     1 : False : False : Binary
            cheese :     0 :   0.0 :     1 : False : False : Binary
             steel :     0 :   0.0 :     1 : False : False : Binary
    
      Objectives:
        obj : Size=1, Index=None, Active=True
            Key  : Active : Value
            None :   True :   5.8
    
      Constraints:
        c1 : Size=1
            Key  : Lower : Body : Upper
            None :   1.0 :  1.8 :  None
        c2 : Size=1
            Key  : Lower : Body : Upper
            None :  None :  4.4 :   5.0