pythonlinear-programmingcplexdocplexobjective-function

Compute objective function in CPLEX


I am trying to solve the supplier diversification problem by minimizing the costs. I basically have a list of pricing for an item from different suppliers. The suppliers are willing to give me some discounts if I order in large quantities. I am trying to solve this problem in Python using CPLEX.

However, I do not know how to write the objective function of this problem. So, for example, I have these pricings

price_list=[{(0, 5): 5, (5, 10): 4},
 {(0, 5): 6, (5, 10): 5, (10, 15): 4, (15, 20): 3},
 {(0, 2): 3, (2, 3): 2},
 {(0, 2): 4, (2, 3): 3, (3, 4): 2}]

whereby if I order from the first supplier 3 items, the unit price of these items is 5. But if I buy 7 items, the unit price becomes 4.

My demand is large enough that I need to buy from different suppliers to meet it.

I am very new to this, can anyone please help?

I did try to write a function that checks to which pricing range the demanded quantity belongs. I wanted the code to be something like this:

def get_cost(ordered_quantity,supplier_index):
    for i in price_list[supplier_index]: #loop through the price range of the given supplier
        if ordered_quantity>=i[0] and ordered_quantity<=i[1]: # check if the demand quantity is within this range
            return price_list[supplier_index][i]*ordered_quantity # computer and return cost of demand

But this can;t work because the demand quantity is a variable in my model and I can't figure out how to get its value to compute the objective function when the model is executing.


Solution

  • You should use piecewise linear function. See example https://github.com/AlexFleischerParis/zoodocplex/blob/master/zoopiecewise.py

    from docplex.mp.model import Model
    
    mdl = Model(name='buses')
    nbbus40 = mdl.integer_var(name='nbBus40')
    nbbus30 = mdl.integer_var(name='nbBus30')
    mdl.add_constraint(nbbus40*40 + nbbus30*30 >= 300, 'kids')
    
    #after 4 buses, additional buses of a given size are cheaper
    f=mdl.piecewise(0, [(0, 0),(4,4)], 0.8)
    
    mdl.minimize(f(nbbus40)*500 + f(nbbus30)*400)
    
    mdl.solve()
    
    for v in mdl.iter_integer_vars():
        print(v," = ",v.solution_value)
    

    And with your values

    price_list=[{(0, 5): 5, (5, 10): 4},
     {(0, 5): 6, (5, 10): 5, (10, 15): 4, (15, 20): 3},
     {(0, 2): 3, (2, 3): 2},
     {(0, 2): 4, (2, 3): 3, (3, 4): 2}]
    
    def get_cost(ordered_quantity,supplier_index):
        for i in price_list[supplier_index]: #loop through the price range of the given supplier
            if ordered_quantity>=i[0] and ordered_quantity<=i[1]: # check if the demand quantity is within this range
                return price_list[supplier_index][i]*ordered_quantity # computer and return cost of demand
    q=4
    
    from docplex.mp.model import Model
    
    mdl = Model(name='test')
    q1 = mdl.integer_var(name='q1')
    cost1 = mdl.integer_var(name='cost')
    
    
    
    costfunction1=mdl.piecewise(0, [(0, 0),(4,20),(5,20),(10,40)], 1000000)
    
    
    mdl.add(cost1==costfunction1(q1))
    
    mdl.add(q1==q)
    
    
    mdl.solve()
    
    for v in mdl.iter_integer_vars():
        print(v," = ",v.solution_value)
    
    print("cost=",get_cost(q,0))   
    

    which gives

    q1  =  4.0
    cost  =  20.0
    cost= 20