使用 numpy 求解一个未知数的线性系统?
Using numpy to solve a linear system with one uknown?
我正在尝试以编程方式解决一个非常简单的问题。
我有一个变量 t 必须同时满足 2 个方程如下:
x_v*t = (x_1 - x_2)
y_v*t = (y_1 - y_2)
我的第一反应是用右边除以左边的系数就解决了,但是那个系数不能保证不为0。
因此我们总是可以使用 RREF 算法并将系统表示为:
a | b
c | d
其中 a = x_v, b = (x_1 - x_2), c = y_v, d = (y_1 - y_2)
找到 RREF 后我们可以:
- 0矩阵(系统可解)
- 第一行有一个前导,第二行是 0(系统可用)
- 每一行都有前导 0 和非零尾随数字(系统不可解)
虽然我可以尝试自己编写上面的代码,但我想使用一个库来代替,我可以在其中设置系统并询问 api 是否存在解决方案,所以我使用了 numpy。
然而目前我什至无法设置非扩展矩阵不是正方形的系统。
这是可以实现的吗?
这是可以实现的。您可以使用函数 fsolve of the scipy 库。一个例子
import numpy as np
import scipy.optimize as so
def f(t, x_v, x_1, x_2, y_v, y_1, y_2):
return np.sum(np.abs([
x_v*t - (x_1 - x_2),
y_v*t - (y_1 - y_2),
]))
然后你会做
sol_object = so.fsolve(
func = f, # the function that returns the (scalar) 0 you want.
x0 = 1, # The starting estimate
args = (1, 2, 3, 1, 2, 3), # Other arguments of f, i.e. x_v, x_1, x_2, y_v, y_1, y_2
full_output = True
)
sol = sol_object[0]
message = sol_object[-1]
print(sol)
print(message)
输出
[-1.]
The solution converged.
正如 jdhesa 在评论中提到的,这可以使用线性参数求解方法来完成。我在上面使用的 先验 适用于任何类型的转换。
另一种方法是只执行除法。
如果 "sides" 均为零,则结果将为 NaN (0/0)。
如果 rhs 即 (x_1 - x_2) 不为零,则结果将为 inf.
# c1 is np.array([x_1, y_1, z_1, ...])
# c2 is np.array([x_2, y_2, z_2, ...])
c = c1 - c2
# Use this to supress numpy warnings
with np.warnings.catch_warnings():
np.warnings.filterwarnings('ignore', 'invalid value encountered in true_divide')
np.warnings.filterwarnings('ignore','divide by zero encountered in true_divide')
t = c / v
non_nan_t = t[~np.isnan(t)]
if np.isinf(t).any():
print('unsolvable because rhs is nonzero but v is zero')
elif not np.allclose(non_nan_t, non_nan_t[0]):
print('no solution because equations disagree')
else:
print('solution:', non_nan_t[0])
我正在尝试以编程方式解决一个非常简单的问题。
我有一个变量 t 必须同时满足 2 个方程如下:
x_v*t = (x_1 - x_2)
y_v*t = (y_1 - y_2)
我的第一反应是用右边除以左边的系数就解决了,但是那个系数不能保证不为0。
因此我们总是可以使用 RREF 算法并将系统表示为:
a | b
c | d
其中 a = x_v, b = (x_1 - x_2), c = y_v, d = (y_1 - y_2)
找到 RREF 后我们可以:
- 0矩阵(系统可解)
- 第一行有一个前导,第二行是 0(系统可用)
- 每一行都有前导 0 和非零尾随数字(系统不可解)
虽然我可以尝试自己编写上面的代码,但我想使用一个库来代替,我可以在其中设置系统并询问 api 是否存在解决方案,所以我使用了 numpy。
然而目前我什至无法设置非扩展矩阵不是正方形的系统。
这是可以实现的吗?
这是可以实现的。您可以使用函数 fsolve of the scipy 库。一个例子
import numpy as np
import scipy.optimize as so
def f(t, x_v, x_1, x_2, y_v, y_1, y_2):
return np.sum(np.abs([
x_v*t - (x_1 - x_2),
y_v*t - (y_1 - y_2),
]))
然后你会做
sol_object = so.fsolve(
func = f, # the function that returns the (scalar) 0 you want.
x0 = 1, # The starting estimate
args = (1, 2, 3, 1, 2, 3), # Other arguments of f, i.e. x_v, x_1, x_2, y_v, y_1, y_2
full_output = True
)
sol = sol_object[0]
message = sol_object[-1]
print(sol)
print(message)
输出
[-1.]
The solution converged.
正如 jdhesa 在评论中提到的,这可以使用线性参数求解方法来完成。我在上面使用的 先验 适用于任何类型的转换。
另一种方法是只执行除法。 如果 "sides" 均为零,则结果将为 NaN (0/0)。 如果 rhs 即 (x_1 - x_2) 不为零,则结果将为 inf.
# c1 is np.array([x_1, y_1, z_1, ...])
# c2 is np.array([x_2, y_2, z_2, ...])
c = c1 - c2
# Use this to supress numpy warnings
with np.warnings.catch_warnings():
np.warnings.filterwarnings('ignore', 'invalid value encountered in true_divide')
np.warnings.filterwarnings('ignore','divide by zero encountered in true_divide')
t = c / v
non_nan_t = t[~np.isnan(t)]
if np.isinf(t).any():
print('unsolvable because rhs is nonzero but v is zero')
elif not np.allclose(non_nan_t, non_nan_t[0]):
print('no solution because equations disagree')
else:
print('solution:', non_nan_t[0])