求解线性方程组和线性不等式
Solve a system of linear equations and linear inequalities
我必须得到线性表达式的最小和最大 y,受限于 python 中的一些线性不等式。
你可以在这里看到我输入 Desmos 的等式和不等式:
3x+12y = 1000
x > 30
x < 160
y < 60
y > 10
x + y > 180
我可以通过画出和划掉不等式来手工解决它们。但我不能在 Python 中这样做。
到目前为止,我在 Python 中尝试的是在 x=0 时得到 y=83.33;当y=0时x=333.33;
在获得最小和最大 x,y 之后,我然后将不等式 1 乘以 1。但是对于每个不等式,我都必须添加之前的不等式,并且还要检查 x 或 y 是否已经超过一定范围,到目前为止,它几乎是我肯定会错过一张支票。
我查看了 numpy 和 sympy,但不知道如何使用它们来解决这个问题。你能建议我如何使用以获得图片上白色箭头显示的范围吗?
按照评论中提供的提示,您可以使用 scipy.optimize.linprog 解决您的问题,如下所示...
In [1]: import numpy as np
In [2]: from scipy import optimize
In [3]: c = np.zeros(2)
In [4]: A_ub = np.array([[-1, -1]])
In [5]: b_ub = np.array([-180])
In [6]: A_eq = np.array([[3, 12]])
In [7]: b_eq = np.array([1000])
In [8]: bounds = [(30, 160), (10, 60)]
In [9]: optimize.linprog(c, A_ub, b_ub, A_eq, b_eq, bounds, method="simplex")
Out[11]:
fun: -0.0
message: 'Optimization terminated successfully.'
nit: 5
slack: array([ 31.11111111, 98.88888889, 0. , 41.11111111, 8.88888889])
status: 0
success: True
x: array([ 128.88888889, 51.11111111])
诀窍是要注意求解方程组可以表示为具有常数零 objective 函数的优化问题。这就是我在上面设置 c=np.zeros(2)
的原因。
您可以尝试 cvxpy。它是凸问题的求解器,因此对于您的需求来说可能有点矫枉过正。我喜欢用它来编码你的问题是多么容易。大多数其他库要求您将问题编码为多个矩阵。
你的问题是线性规划中的一个问题,你的等式和不等式是限制,你想最小化(然后最大化)表达式 y
。等式、不等式和表达式都是线性的,因此它是线性规划。 scipy
包,使用scipy.optimize.linprog
函数,可以做这种线性规划。
这里是注释代码,可以执行您想要的操作。请注意,所有不等式都略有变化以包括相等性,这对于具有最大值或最小值 y
是必要的。为了找到 y
的最大值,代码找到 -y
的最小值,然后打印它的加法逆函数,因为 linprog
最小化了 objective 函数。最后,不等式的限制一定是linprog
中的"less than or equal to",所以我把你的不等式x + y > 180
两边都乘以-1
得到一个,即-x + -y <= -180
。有问题就问。
from scipy.optimize import linprog
# Set up values relating to both minimum and maximum values of y
coefficients_inequalities = [[-1, -1]] # require -1*x + -1*y <= -180
constants_inequalities = [-180]
coefficients_equalities = [[3, 12]] # require 3*x + 12*y = 1000
constants_equalities = [1000]
bounds_x = (30, 160) # require 30 <= x <= 160
bounds_y = (10, 60) # require 10 <= y <= 60
# Find and print the minimal value of y
coefficients_min_y = [0, 1] # minimize 0*x + 1*y
res = linprog(coefficients_min_y,
A_ub=coefficients_inequalities,
b_ub=constants_inequalities,
A_eq=coefficients_equalities,
b_eq=constants_equalities,
bounds=(bounds_x, bounds_y))
print('Minimum value of y =', res.fun)
# Find and print the maximal value of y = minimal value of -y
coefficients_max_y = [0, -1] # minimize 0*x + -1*y
res = linprog(coefficients_max_y,
A_ub=coefficients_inequalities,
b_ub=constants_inequalities,
A_eq=coefficients_equalities,
b_eq=constants_equalities,
bounds=(bounds_x, bounds_y))
print('Maximum value of y =', -res.fun) # opposite of value of -y
该代码的打印输出是
Minimum value of y = 43.3333333333
Maximum value of y = 51.1111111111
在浮点精度内是正确的。如果你需要 x
的相应值,请参阅 res.x
的值,它是一个数组,在所需的点给出 x
和 y
的值--x
是 res.x[0]
而 y
是 res.x[1]
.
我必须得到线性表达式的最小和最大 y,受限于 python 中的一些线性不等式。
你可以在这里看到我输入 Desmos 的等式和不等式:
3x+12y = 1000
x > 30
x < 160
y < 60
y > 10
x + y > 180
我可以通过画出和划掉不等式来手工解决它们。但我不能在 Python 中这样做。 到目前为止,我在 Python 中尝试的是在 x=0 时得到 y=83.33;当y=0时x=333.33; 在获得最小和最大 x,y 之后,我然后将不等式 1 乘以 1。但是对于每个不等式,我都必须添加之前的不等式,并且还要检查 x 或 y 是否已经超过一定范围,到目前为止,它几乎是我肯定会错过一张支票。
我查看了 numpy 和 sympy,但不知道如何使用它们来解决这个问题。你能建议我如何使用以获得图片上白色箭头显示的范围吗?
按照评论中提供的提示,您可以使用 scipy.optimize.linprog 解决您的问题,如下所示...
In [1]: import numpy as np
In [2]: from scipy import optimize
In [3]: c = np.zeros(2)
In [4]: A_ub = np.array([[-1, -1]])
In [5]: b_ub = np.array([-180])
In [6]: A_eq = np.array([[3, 12]])
In [7]: b_eq = np.array([1000])
In [8]: bounds = [(30, 160), (10, 60)]
In [9]: optimize.linprog(c, A_ub, b_ub, A_eq, b_eq, bounds, method="simplex")
Out[11]:
fun: -0.0
message: 'Optimization terminated successfully.'
nit: 5
slack: array([ 31.11111111, 98.88888889, 0. , 41.11111111, 8.88888889])
status: 0
success: True
x: array([ 128.88888889, 51.11111111])
诀窍是要注意求解方程组可以表示为具有常数零 objective 函数的优化问题。这就是我在上面设置 c=np.zeros(2)
的原因。
您可以尝试 cvxpy。它是凸问题的求解器,因此对于您的需求来说可能有点矫枉过正。我喜欢用它来编码你的问题是多么容易。大多数其他库要求您将问题编码为多个矩阵。
你的问题是线性规划中的一个问题,你的等式和不等式是限制,你想最小化(然后最大化)表达式 y
。等式、不等式和表达式都是线性的,因此它是线性规划。 scipy
包,使用scipy.optimize.linprog
函数,可以做这种线性规划。
这里是注释代码,可以执行您想要的操作。请注意,所有不等式都略有变化以包括相等性,这对于具有最大值或最小值 y
是必要的。为了找到 y
的最大值,代码找到 -y
的最小值,然后打印它的加法逆函数,因为 linprog
最小化了 objective 函数。最后,不等式的限制一定是linprog
中的"less than or equal to",所以我把你的不等式x + y > 180
两边都乘以-1
得到一个,即-x + -y <= -180
。有问题就问。
from scipy.optimize import linprog
# Set up values relating to both minimum and maximum values of y
coefficients_inequalities = [[-1, -1]] # require -1*x + -1*y <= -180
constants_inequalities = [-180]
coefficients_equalities = [[3, 12]] # require 3*x + 12*y = 1000
constants_equalities = [1000]
bounds_x = (30, 160) # require 30 <= x <= 160
bounds_y = (10, 60) # require 10 <= y <= 60
# Find and print the minimal value of y
coefficients_min_y = [0, 1] # minimize 0*x + 1*y
res = linprog(coefficients_min_y,
A_ub=coefficients_inequalities,
b_ub=constants_inequalities,
A_eq=coefficients_equalities,
b_eq=constants_equalities,
bounds=(bounds_x, bounds_y))
print('Minimum value of y =', res.fun)
# Find and print the maximal value of y = minimal value of -y
coefficients_max_y = [0, -1] # minimize 0*x + -1*y
res = linprog(coefficients_max_y,
A_ub=coefficients_inequalities,
b_ub=constants_inequalities,
A_eq=coefficients_equalities,
b_eq=constants_equalities,
bounds=(bounds_x, bounds_y))
print('Maximum value of y =', -res.fun) # opposite of value of -y
该代码的打印输出是
Minimum value of y = 43.3333333333
Maximum value of y = 51.1111111111
在浮点精度内是正确的。如果你需要 x
的相应值,请参阅 res.x
的值,它是一个数组,在所需的点给出 x
和 y
的值--x
是 res.x[0]
而 y
是 res.x[1]
.