Compute objective function in CPLEX

122 Views Asked by At

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.

1

There are 1 best solutions below

0
Alex Fleischer On BEST ANSWER

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