1

I am trying to use linprog in order to optimise the following problem (uploaded in Google Drive). The dataset itself is uploaded here

So far I have the written the following implementation in Python:

import pandas as pd
import numpy as np

df = pd.read_csv('Supplier Specs.csv')
from scipy.optimize import linprog

def fromPandas(dataframe, colName):
    return dataframe[[colName]].values.reshape(1,11)[0]

## A_ub * x <= b_ub
## A_eq * x == b_eq

A_eq = [1.0]*11
u_eq = [600.0] # demand

## reading the actual numbers from the pandas dataframe and then converting them to vectors

BAR = fromPandas(df, 'Brix / Acid Ratio')
acid = fromPandas(df, 'Acid (%)')
astringency = fromPandas(df, 'Astringency (1-10 Scale)')
color = fromPandas(df, 'Color (1-10 Scale)')
price = fromPandas(df, 'Price (per 1K Gallons)')
shipping = fromPandas(df, 'Shipping (per 1K Gallons)')
upperBounds = fromPandas(df, 'Qty Available (1,000 Gallons)')

lowerBounds = [0]*len(upperBounds) # list with length 11 and value 0
lowerBounds[2] = 0.4*u_eq[0] # adding the Florida tax bound

bnds = [(0,0)]*len(upperBounds) # bounds
for i in range(0,len(upperBounds)):
    bnds[i] = (lowerBounds[i], upperBounds[i])

c = price + shipping # objective function coefficients

print("------------------------------------- Debugging Output ------------------------------------- \n")
print("Objective function coefficients: ", c)
print("Bounds: ", bnds)
print("Equality coefficients: ", A_eq)
print("BAR coefficients: ", BAR)
print("Astringency coefficients: ", astringency)
print("Color coefficients: ", color)
print("Acid coefficients: ", acid)
print("\n")

A_ub = [BAR, acid, astringency, color, -BAR, -acid, -astringency, -color] # coefficients for inequalities
b_ub = np.array([12.5, 1.0, 4.0, 5.5, -11.5, -0.75, 0, -4.5]) # limits for the inequalities

b_ub = b_ub * u_eq[0] # scaling the limits with the demand

xOptimized = linprog(c, A_ub, b_ub, [A_eq], u_eq, bounds=(bnds))

print(xOptimized) # the amounts of juice which we need to buy from each supplier

The optimisation method returns that cannot find a feasible starting point. I believe that I have a principal error in working with the method but so far I couldn't understand it.

Some help ?

Thanks in advance!

EDIT: the expected value of the objective function is 371724

the expected solution vector [0,0,240,0,15.8,0,0,0,126.3,109.7,108.2]

Vasil Yordanov
  • 417
  • 3
  • 14
  • From [scipy documentation](https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.linprog.html#scipy.optimize.linprog): "A_eq : 2-D array which, when matrix-multiplied by x, gives the values of the equality constraints at x." Your `A_eq` is one dimensional , but you suppressed an error message with `[A_eq]`. – Mr. T Jan 14 '18 at 15:06
  • How should I write the 2-D array when I have only 1 equality constraint ? – Vasil Yordanov Jan 14 '18 at 15:17

1 Answers1

1

That was indeed a premature guess from me. [A_eq] is of course two-dimensional with 1xn. That your script works in principle shows the example, when you remove all your negative constraints from

A_ub = [BAR, acid, astringency, color, -BAR, -acid, -astringency, -color] # coefficients for inequalities
b_ub = np.array([12.5, 1.0, 4.0, 5.5, -11.5, -0.75, 0, -4.5]) # limits for the inequalities

And this seems to be the crux of the problem. Since A_ub * x <= b_ub, you look for a solution for
BAR * x <= 12.5
and
-BAR * x <= -11.5, i.e.
11.5 <= BAR * x <= 12.5 That obviously fails to produce any results. You are actually looking for

A_ub = [BAR, acid, astringency, color, -BAR, -acid, -astringency, -color] # coefficients for inequalities
b_ub = np.array([12.5, 1.0, 4.0, 5.5, 11.5, 0.75, 0, 4.5]) # limits for the inequalities

This converges now, but gives a different result from your expected solution, you published now in your edit. Obviously, you have to re-evaluate your inequality parameters, which you haven't specified in your question.

Mr. T
  • 11,960
  • 10
  • 32
  • 54
  • Thanks! Really helped me a lot. However I don't understand why I shouldn't switch the signs of my last 4 b_ub values ? A_ub * x >= b_ub is equivalent to -A_ub * x <= -b_ub isn't it ? – Vasil Yordanov Jan 14 '18 at 16:55
  • Yes, it is. I don't know, why the solutions differ. The function minimum is calculated as 368507, which is lower than your posted solution. Why? I don't kow. I would add some code to test, that all equality and inequality parameters are met indeed as expected and that the calculated function indeed gives the value you got back from scipy. I assume, you made sure, that the sample solution is correct. – Mr. T Jan 14 '18 at 17:03
  • I got my error ... the acid limits are not 0.75 and 1.0 but 0.0075 and 0.01 – Vasil Yordanov Jan 14 '18 at 17:35
  • when I update he acid values and switch the sign of my last 4 b_ub to negative it works perfectly – Vasil Yordanov Jan 14 '18 at 17:41
  • Go team! Congrats. And stay away from Excel, especially their stats and regression modules are abysmal. – Mr. T Jan 14 '18 at 18:00