I am trying to get the same result than Excel using 2 python solvers : Gekko and Pyomo. This is a non linear pricing model from the Practical_Management Science (Christian Albright)book, page 350. The solution provided by Excel is to sell my item 93.31 dollars, for a 9323 dollars profit.
However, entering the same problem in Gekko and Pyomo leads to a 80 dollars selling price and 9000 dollars of profit. I wonder if there is any param I forgot to get the same result than Excel ?
Pyomo Code :
import pyomo.environ as pyo
import sys
solvername='ipopt'
solverpath_folder='C:\\ipopt' #does not need to be directly on c drive
solverpath_exe='C:\\ipopt\\bin\\ipopt' #does not need to be directly on c drive
sys.path.append(solverpath_folder)
model = pyo.ConcreteModel()
model.item = pyo.Var(within=pyo.PositiveReals, bounds=(0, 100000), initialize=1)
model.OBJ = pyo.Objective(expr = ((model.item - 50) * (1100 - 10 * model.item)), sense=pyo.maximize)
results = pyo.SolverFactory(solvername,executable=solverpath_exe).solve(model)
print("item=", pyo.value(model.item))
print("objective=", pyo.value(model.OBJ))
print(results)
Gekko code :
from gekko import GEKKO
m = GEKKO(remote=False) # Initialize gekko
m.options.SOLVER = 1
p1 = m.Var(integer=False)
x1 = m.Var(integer=False)
m.Equation(x1 == 1100 - 10 * p1)
m.Maximize((p1 - 50) * (1100 - 10 * p1))
m.options.IMODE = 3 # Steady state optimization
m.solve() # Solve
print('Solution')
print('x1: ' + str(p1.value))
print('Objective: ' + str(m.options.objfcnval))
Both python solvers = same result = 80 dollars pricing and 9000 dollars profit, instead of 93.31 dollars pricing and 9323 profit using the Excel non linear Grg solver.
I am using the linear demand function (y = -10x+ 1100) instead of the constant elasticy curve , like what they did in the book and in their Excel result, I wonder if the problem is this ?
( The problem is that I don't know what 4E is in the constant elasticity curve, so I can't type it in Python)
Here is the solution in Python Gekko:
from gekko import GEKKO
m = GEKKO()
p = m.Var(lb=50) # price
d = m.Var(lb=100) # demand
m.Equation(d == 3.777178e6*p**(-2.154))
m.Maximize((p-50)*d)
m.solve()
print('Solution')
price = p.value[0]
obj = -m.options.objfcnval
print(f'Price: {price:0.2f}')
print(f'Profit: {obj:0.2f}')
# view profit versus price solution
import numpy as np
import matplotlib.pyplot as plt
px = np.linspace(55,110)
dx = 3.777178e6*px**(-2.154)
profit = (px-50)*dx
plt.plot(px,profit)
plt.plot(price,obj,'o',markersize=10,color='orange')
plt.grid(); plt.xlabel('Price'); plt.ylabel('Profit')
plt.show()
You are correct that the linear function was the source of the difference. The 4E+06
is scientific notation for 4000000
but Excel rounds the number from 3777178
. If you use more digits for 2.154xxx
, it will likely get exactly the same answer as Excel.
---------------------------------------------------
Solver : IPOPT (v3.12)
Solution time : 9.999999994761311E-003 sec
Objective : -9343.94630932932
Successful solution
---------------------------------------------------
Solution
Price: 93.327556326
Profit: 9343.9463093