【问题标题】:Solving system using linalg with constraints使用带约束的 linalg 求解系统
【发布时间】:2015-06-28 09:40:41
【问题描述】:

我想用linalg解一些矩阵形式的系统,但是得到的解应该总和为1。例如,假设有3个未知数,x,y,z。求解系统后,它们的值总和应为 1,例如 0.3、0.5、0.2。谁能告诉我我该怎么做?

目前,我正在使用result = linalg.solve(A, B) 之类的东西,其中AB 是矩阵。但这不会返回[0, 1] 范围内的解决方案。

【问题讨论】:

  • 根据文档,linalg.solve 用于计算完全确定的,即满秩线性矩阵方程 ax = b 的“精确”解 x。由于是线性的,最多只能有一种解决方案。如果您找到的解决方案总和不等于 1,那么添加额外的约束将不会产生任何解决方案。
  • 谢谢,我明白了,但是对于 linalg 是否有任何替代方案可以考虑这样的约束?

标签: python numpy matrix equation-solving


【解决方案1】:

Per the docs,

linalg.solve 用于计算“精确”解,x, 良好确定的,即满秩线性矩阵方程ax = b

存在 线性的,最多只能有一个解。如果您找到的解决方案没有 总和为 1,然后添加额外的约束将不会产生任何解决方案。

但是,您可以使用 scipy.optimize.minimize 在约束平面上找到最小化数量的点 ||Ax-b||^2:

def f(x):
    y = np.dot(A, x) - b
    return np.dot(y, y)

cons = ({'type': 'eq', 'fun': lambda x: x.sum() - 1})
res = optimize.minimize(f, [0, 0, 0], method='SLSQP', constraints=cons, 
                        options={'disp': False})

例如,给定这个方程组

import numpy as np
import numpy.linalg as LA
import scipy.optimize as optimize

A = np.array([[1, 3, 4], [5, 6, 9], [1, 2, 3]])
b = np.array([1, 2, 1])
x = LA.solve(A, b)

解加起来不等于1:

print(x)
# [-0.5 -1.5  1.5]

但是你可以尝试最小化f:

def f(x):
    y = np.dot(A, x) - b
    return np.dot(y, y)

受限于cons:

cons = ({'type': 'eq', 'fun': lambda x: x.sum() - 1})
res = optimize.minimize(f, [0, 0, 0], method='SLSQP', constraints=cons, 
                        options={'disp': False})
xbest = res['x']
# array([ 0.30000717,  1.89998823, -1.1999954 ])

xbest 和为 1:

print(xbest.sum())
1

A·xbest - b的区别是:

print(np.dot(A, xbest) - b)
# [ 0.19999026  0.10000663 -0.50000257]

差的平方和,(也可以计算为f(xbest))是:

print(res['fun'])
0.30000000014542572

在满足约束的同时,没有其他 x 值可以进一步最小化这个数量。

【讨论】:

  • 我的 A 值是一个元组列表。是否可以解释如何应用相同的方法但使用元组列表?谢谢
【解决方案2】:

您可以在 A 中添加一行,然后在 B 中添加一个。之后使用 结果 = linalg.lstsq(A, B)[0]

或者您可以将 A 的行之一替换为由 1 组成的行,也可以将 B 中的值替换为同一行中的一个。然后使用 结果 = linalg.solve(A, B)

【讨论】:

    【解决方案3】:

    作为替代方案,您可以将numpy.linalg.lstsqA 矩阵的新行结合使用:[1, 1, 1]B 矩阵[1]

    import numpy as np
    A = np.array([[1, 0, 1],
                  [0, 1, 1],
                  [1, 1, 0],
                  [1, 1, 1]]
    B = np.array([[0.5, 0.7, 0.8, 1.0]]).T
    x, _, _, _ = np.linalg.lstsq(A, B)
    

    这使x 成为[[0.3], [0.5], [0.2]]

    【讨论】:

      猜你喜欢
      • 2019-06-03
      • 2021-09-10
      • 2021-12-21
      • 1970-01-01
      • 1970-01-01
      • 2019-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多