使用 Scipy 的线性建模问题

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

我正在尝试设计一个线性模型,其三个特征是三种不同元素的每周价格。我需要将这些价格结合起来以获得每周最便宜的组合。 我使用了 Scipy,当我输入数据时,最后只有 NaN,我不明白为什么。

这是我尝试过的:

import numpy as np
from scipy.optimize import linprog

wprices = np.array([205.5,215,225])
cprices = np.array([216.5,214,219])
bprices = np.array([184.5,192,202])

# Minimum percentage limits for each product
wprice_min_percentage = 0.25
cprice_min_percentage = 0.25
bprice_min_percentage = 0.25

# Number of weeks
num_weeks = len(wprices)

# Objective function coefficients (negative as we want to minimize the cost)
c = np.array([-wprices, -cprices, -bprices]).T

# Constraint matrix
A = np.array([[1, 1, 1]])

# Lower bounds for the constraints
b = np.array([1])  # Total percentage should be 1 (100%)

# Upper bounds for the constraints
A_ub = np.array([[-wprice_min_percentage, -cprice_min_percentage, -bprice_min_percentage]])
b_ub = np.array([-1])  # Each product's percentage should be greater than or equal to the minimum

# Solve the linear programming problem for each week
optimal_percentages = []
for week in range(num_weeks):
    result = linprog(c[week], A_ub=A_ub, b_ub=b_ub, A_eq=A, b_eq=b)
    if result.success:
        optimal_percentages.append(result.x * 100)
    else:
        optimal_percentages.append([np.nan, np.nan, np.nan])
scipy linear-programming
1个回答
0
投票

这是我解决这个问题的方法。

我想知道的第一件事是为什么

result.success
是False。因此,我将打印出
result
对象。

for week in range(num_weeks):
    result = linprog(c[week], A_ub=A_ub, b_ub=b_ub, A_eq=A, b_eq=b)
    print(result)

这会产生以下输出:

       message: The problem is infeasible. (HiGHS Status 8: model_status is Infeasible; primal_status is At lower/fixed bound)
       success: False
        status: 2
           fun: None
             x: None
           nit: 0
         lower:  residual: None
                marginals: None
         upper:  residual: None
                marginals: None
         eqlin:  residual: None
                marginals: None
       ineqlin:  residual: None
                marginals: None

这意味着我们的一些限制是矛盾的。让我们仔细看看我们的限制。

我注意到的第一件事是:

# Lower bounds for the constraints
b = np.array([1])  # Total percentage should be 1 (100%)
# [...]
result = linprog(c[week], A_ub=A_ub, b_ub=b_ub, A_eq=A, b_eq=b)

评论说

b
用作下限。然而,它作为
A
矩阵的等式约束传递。我建议修复此评论。

我接下来看的是我们的不平等约束:

A_ub = np.array([[-wprice_min_percentage, -cprice_min_percentage, -bprice_min_percentage]])
b_ub = np.array([-1])  # Each product's percentage should be greater than or equal to the minimum
# [...]
result = linprog(c[week], A_ub=A_ub, b_ub=b_ub, A_eq=A, b_eq=b)

让我们将其重写为数学方程,以便更好地了解正在发生的事情:

-wprice_min_percentage * x[0] + -cprice_min_percentage * x[1] + -bprice_min_percentage * x[2] <= -1

让我们简化这个方程:

wprice_min_percentage * x[0] + cprice_min_percentage * x[1] + bprice_min_percentage * x[2] >= 1

这向我们展示了注释所说的功能与代码实际功能之间的不匹配。评论说它单独限制了每个产品。然而,这表达了对所有元素之和的约束。

第二个问题是

min_percentage
变量位于该等式的错误一侧。

让我们在这个方程中代入一些示例值来说明原因。

wprice_min_percentage * x[0] + cprice_min_percentage * x[1] + bprice_min_percentage * x[2] >= 1
# Replace min_percentage with 0.25
0.25 * x[0] + 0.25 * x[1] + 0.25 * x[2] >= 1
# Replace x values with 0.33
0.25 * 0.33 + 0.25 * 0.33 + 0.25 * 0.33 >= 1
# Simplify
0.2475 >= 1

要解决此问题,我建议将

A_ub
b_ub
替换为以下内容:

A_ub = np.diag([-1, -1, -1])
b_ub = np.array([-wprice_min_percentage, -cprice_min_percentage, -bprice_min_percentage])  # Each product's percentage should be greater than or equal to the minimum

(旁注:

bounds
linprog()
参数也可以用在这里,而且更容易使用。)

让我们尝试重新运行代码,看看会得到什么。

>>> print(optimal_percentages)
[array([25., 50., 25.]), array([50., 25., 25.]), array([50., 25., 25.])]

它是尽可能多地购买一种资源,并尽可能少地购买所有其他资源。如果目标是最小化成本,那么这看起来是合理的。让我们同时看看成本和百分比。

for week in range(num_weeks):
    print("week", week)
    print(optimal_percentages[week], c[week])

输出:

week 0
[25. 50. 25.] [-205.5 -216.5 -184.5]
week 1
[50. 25. 25.] [-215. -214. -192.]
week 2
[50. 25. 25.] [-225. -219. -202.]

似乎每周都会购买最昂贵的选择。要找出原因,让我们看看顶部的评论:

# Objective function coefficients (negative as we want to minimize the cost)
c = np.array([-wprices, -cprices, -bprices]).T

将其与 文档进行比较:

线性规划:最小化受线性等式和不等式约束的线性目标函数。

换句话说,linprog 已经最小化了目标函数。如果我们添加一个负号,它就会开始最大化价格。

修复方法是删除负号:

# Objective function coefficients (negative as we want to minimize the cost)
c = np.array([wprices, cprices, bprices]).T

最终完整代码:

import numpy as np
from scipy.optimize import linprog

wprices = np.array([205.5,215,225])
cprices = np.array([216.5,214,219])
bprices = np.array([184.5,192,202])

# Minimum percentage limits for each product
wprice_min_percentage = 0.25
cprice_min_percentage = 0.25
bprice_min_percentage = 0.25

# Number of weeks
num_weeks = len(wprices)

# Objective function coefficients (negative as we want to minimize the cost)
c = np.array([wprices, cprices, bprices]).T

# Constraint matrix
A = np.array([[1, 1, 1]])

# Equality constraints for A
b = np.array([1])  # Total percentage should be 1 (100%)

# Upper bounds for the constraints
A_ub = np.diag([-1, -1, -1])
b_ub = np.array([-wprice_min_percentage, -cprice_min_percentage, -bprice_min_percentage])  # Each product's percentage should be greater than or equal to the minimum

# Solve the linear programming problem for each week
optimal_percentages = []
for week in range(num_weeks):
    result = linprog(c[week], A_ub=A_ub, b_ub=b_ub, A_eq=A, b_eq=b)
    if result.success:
        optimal_percentages.append(result.x * 100)
    else:
        optimal_percentages.append([np.nan, np.nan, np.nan])
for week in range(num_weeks):
    print("week", week)
    print(optimal_percentages[week], c[week])
© www.soinside.com 2019 - 2024. All rights reserved.