考虑一个欠定的线性方程组Ax=b
。
我想找到一组向量x_1, ..., x_n
,使它们都解决Ax=b
,并且它们尽可能彼此不同。
第二部分实际上不太重要;我很满意每次调用它时返回Ax=b
随机解的算法。
我知道scipy.sparse.linalg.lsqr
和numpy.linalg.lstsq
会返回一个未确定的线性系统Ax=b
的稀疏解(就最小二乘方而言),但我不关心它的属性解;我只想要Ax=b
的任何解决方案,只要我能够生成一堆不同的解决方案。
事实上,scipy.sparse.linalg.lsqr
和numpy.linalg.lstsq
应该遵循从解决方案跳到另一个解决方案的迭代过程,直到找到一个似乎在最小二乘方面最小的解决方案。那么,是否有一个python模块可以让我在没有特定目标的情况下在解决方案之间跳转并返回它们?
答案 0 :(得分:1)
以下是我的评论中附带的代码。它使用Scipy Cookbook中的rank_nullspace.py
模块。
import numpy as np
from numpy.linalg import lstsq
from rank_nullspace import nullspace
# rank_nullspace from
# http://scipy-cookbook.readthedocs.io/items/RankNullspace.html
def randsol(A, b, num=1, check=False):
xLS, *_ = lstsq(A, b)
colsOfNullspace = nullspace(A)
nullrank = colsOfNullspace.shape[1]
if check:
assert(np.allclose(np.dot(A, xLS), b))
assert(np.allclose(np.dot(A, xLS + np.dot(colsOfNullspace,
np.random.randn(nullrank))),
b))
sols = xLS[:, np.newaxis] + np.dot(colsOfNullspace,
np.random.randn(nullrank, num))
return sols
A = np.random.randn(2, 10)
b = np.random.randn(2)
x = randsol(A, b, num=50, check=True)
assert(np.allclose(np.dot(A, x), b[:, np.newaxis]))
使用x
中的一系列解决方案,您可以选择彼此“不同”的解决方案,但是您定义的是“不同”。
答案 1 :(得分:1)
对于欠定系统 A
因此,如果您想对 A·x = b 的随机解决方案进行抽样,那么您可以以下内容:
np.linalg.lstsq
执行此操作,this previous question会找到最小化 x' 的L2规范的解决方案。sorted(list)
vs list.sort()
?。例如:
import numpy as np
from scipy.linalg import qr
def qr_null(A, tol=None):
"""Computes the null space of A using a rank-revealing QR decomposition"""
Q, R, P = qr(A.T, mode='full', pivoting=True)
tol = np.finfo(R.dtype).eps if tol is None else tol
rnk = min(A.shape) - np.abs(np.diag(R))[::-1].searchsorted(tol)
return Q[:, rnk:].conj()
# An underdetermined system with nullity 2
A = np.array([[1, 4, 9, 6, 9, 2, 7],
[6, 3, 8, 5, 2, 7, 6],
[7, 4, 5, 7, 6, 3, 2],
[5, 2, 7, 4, 7, 5, 4],
[9, 3, 8, 6, 7, 3, 1]])
b = np.array([0, 4, 1, 3, 2])
# Find an initial solution using `np.linalg.lstsq`
x_lstsq = np.linalg.lstsq(A, b)[0]
# Compute the null space of `A`
Z = qr_null(A)
nullity = Z.shape[1]
# Sample some random solutions
for _ in range(5):
x_rand = x_lstsq + Z.dot(np.random.rand(nullity))
# If `x_rand` is a solution then `||A·x_rand - b||` should be very small
print(np.linalg.norm(A.dot(x_rand) - b))
示例输出:
3.33066907388e-15
3.58036167305e-15
4.63775652864e-15
4.67877015036e-15
4.31132637123e-15
可能的 c 向量的空间是无限的 - 你必须做出一些选择,以便你如何对它们进行采样。