Python Gekko 整数规划的最大方程长度错误

问题描述 投票:0回答:1

我使用 Gekko 来解决 MILP 问题,我需要为每种产品选择最优价格,以最大化我的目标函数(总利润)。但是,我必须对数据帧进行切片,就好像我包含整个数据集一样,我得到了最大方程长度错误。有没有办法解决这个问题,将更大的数据帧输入到求解器中?我最初使用 PuLP 包,但对于较大的数据集,代码的执行时间过长。我在下面附上了我的代码。

# Preprocess data
price_matrix = []
profit_matrix = []
revenue_matrix = []
grevenue_matrix = []
num_prices_per_product = []

df = df_org[:200]

# Iterate over unique products
for product in df['Product'].unique():
    # Filter data for the current product
    product_data = df[df['Product'] == product]
    
    # Extract unique price points and sort in descending order
    price_points = np.sort(product_data['Sales Price'].unique())[::-1]
    num_prices = len(price_points)
    
    # Preallocate arrays
    product_profit_matrix = np.zeros(num_prices)
    product_revenue_matrix = np.zeros(num_prices)
    product_grevenue_matrix = np.zeros(num_prices)

    # Iterate over price points
    for i, price in enumerate(price_points):
        # Filter data for the current price point
        price_data = product_data[product_data['Sales Price'] == price]
        if not price_data.empty:
            # Assign values to matrices
            product_profit_matrix[i] = price_data['Profit Margin'].iloc[0]
            product_revenue_matrix[i] = price_data['Revenue'].iloc[0]
            product_grevenue_matrix[i] = price_data['Gross revenue'].iloc[0]

    # Append matrices and other information
    price_matrix.append(price_points)
    profit_matrix.append(product_profit_matrix)
    revenue_matrix.append(product_revenue_matrix)
    grevenue_matrix.append(product_grevenue_matrix)
    num_prices_per_product.append(num_prices)

start = time.time()

# Initialize gekko model
m = GEKKO(remote=False)

# Decision variables
x = {}
for i, product_name in enumerate(df['Product'].unique()):
    for j in range(max(num_prices_per_product)):
        x[(product_name, j)] = m.Var(value=0, lb=0, ub=1, integer=True)

# Objective function (maximize total profit)
total_profit = 0
for i, product_name in enumerate(df['Product'].unique()):
    for j in range(num_prices_per_product[i]):
        total_profit += profit_matrix[i][j] * x[(product_name, j)]
m.Maximize(total_profit)

# Constraint: Each product must have exactly one selected price
for i, product_name in enumerate(df['Product'].unique()):
    m.Equation(sum(x[(product_name, j)] for j in range(num_prices_per_product[i])) == 1)

# Discount Constraint
revenue_difference = 0
for i, product_name in enumerate(df['Product'].unique()):
    for j in range(num_prices_per_product[i]):
        revenue_difference += (grevenue_matrix[i][j] - revenue_matrix[i][j]) * x[(product_name, j)]
discount_constraint = 0.13 # Set your desired maximum discount
discount_tolerance = 0.01
total_gross_revenue = 0
for i, product_name in enumerate(df['Product'].unique()):
    for j in range(num_prices_per_product[i]):
        total_gross_revenue += grevenue_matrix[i][j] * x[(product_name, j)]
m.Equation(revenue_difference <= (discount_constraint + discount_tolerance) * total_gross_revenue)
m.Equation(revenue_difference >= (discount_constraint - discount_tolerance) * total_gross_revenue)

# Profit Constraint
profit_constraint = 6000
profit_tolerance = 0.05
m.Equation(total_profit <= profit_constraint + (profit_tolerance * profit_constraint))
m.Equation(total_profit >= profit_constraint - (profit_tolerance * profit_constraint))

# Solve the optimization problem
m.solve(disp=True)

end = time.time()
print("Optimization Time:", end - start)

# Print the results
print("Status:", m.options.SOLVESTATUS)
print("Total Profit ($):", total_profit)

# Print the selected prices
results_df = pd.DataFrame(selected_prices, columns=["Product", "Selected Price Point", "Value (AED)"])
print(tabulate(results_df, headers='keys', tablefmt='fancy_grid', showindex=False))

我尝试使用 Gekko 和 PuLP 来解决 MILP 问题,但在大型数据集上使用我的算法时遇到了问题。

python pulp gekko mixed-integer-programming
1个回答
0
投票

一个简单的问题展示了问题和潜在的解决方案。有

n
随机生成的产品,每个产品都有随机的
price
revenue
。目标是通过选择最好的 10 种产品来实现利润最大化。该解决方案选择利润率最高的 10 种产品。

from gekko import GEKKO
import numpy as np

# Random data
n=500
price = np.random.randn(n)
revenue = np.random.randn(n)

# Create Gekko model
m = GEKKO(remote=False)

# Decision variables
x = [None]*n
for i in range(n):
   x[i] = m.Var(value=0,lb=0,ub=1,integer=True)

# Select 10 products out of n
m.Equation(sum(x)==10)

# Maximize profit
profit = 0
for i in range(n):
   profit+=x[i]*(price[i]-revenue[i])
m.Maximize(profit)   

m.options.SOLVER=1
m.solve()

n>=413
时,出现符号表达式超过15,000个字符的错误。

 APM model error: string >       15000  characters
 Consider breaking up the line into multiple equations
 
 The may also be due to only using newline character CR
   instead of CR LF (for Windows) or LF (for MacOS/Linux) 
 To fix this problem, save APM file with appropriate newline characters
 
 STOPPING...

有两项更改可以解决长表达式问题。

  1. 使用
    m.sum()
    而不是
    sum()
    。这使用了
    gekko
    求和,需要更长的时间来编译,但不会生成可能违反 15,000 个字符限制的单个大表达式。
# Select 10 products out of n
m.Equation(m.sum(x)==10)
  1. 对于目标函数,尝试使用多个目标函数而不求和。
# Maximize profit
for i in range(n):
   m.Maximize(x[i]*(price[i]-revenue[i]))

现在模型可以使用

n=500
或更多产品来求解。

from gekko import GEKKO
import numpy as np

# Random data
n=5000
price = np.random.randn(n)
revenue = np.random.randn(n)

# Create Gekko model
m = GEKKO(remote=False)

# Decision variables
x = [None]*n
for i in range(n):
   x[i] = m.Var(value=0,lb=0,ub=1,integer=True)

# Select 10 products out of n
m.Equation(m.sum(x)==10)

# Maximize profit
for i in range(n):
   m.Maximize(x[i]*(price[i]-revenue[i]))

m.options.SOLVER=1
m.solve()

这是

n=5000
产品的解决方案。

 --------- APM Model Size ------------
 Each time step contains
   Objects      :            1
   Constants    :            0
   Variables    :         5001
   Intermediates:            0
   Connections  :         5001
   Equations    :         5001
   Residuals    :         5001
 
 Number of state variables:           5001
 Number of total equations: -            2
 Number of slack variables: -            0
 ---------------------------------------
 Degrees of freedom       :           4999
 
 ----------------------------------------------
 Steady State Optimization with APOPT Solver
 ----------------------------------------------
Iter: 1 I: 0 Tm: 0.02 NLPi: 3 Dpth: 0 Lvs: 0 Obj: -4.47E+01 Gap: 0.00E+00
 Successful solution
 
 ---------------------------------------------------
 Solver         :  APOPT (v1.0)
 Solution time  :   3.630000000703149E-002 sec
 Objective      :   -44.6851835859332     
 Successful solution
 ---------------------------------------------------

您可以检查临时运行文件夹

m._path
中的符号表达式或使用
m.open_folder()
打开该文件夹。打开文本文件
gk0_model.apm
以查看变量、方程和目标函数作为编译为字节码的存档。

具有许多二元决策变量的大规模问题可能解决得很慢。有 APOPT 求解器选项 可能有助于加快 MINLP 求解器的求解速度。如果问题是 MILP,则有一些很好的求解器,例如

CPLEX
Gurobi
,它们可能比使用
MINLP
求解器更有效。

© www.soinside.com 2019 - 2024. All rights reserved.