【问题标题】:Solving this rectangular, nonlinear system with SciPy用 SciPy 求解这个矩形非线性系统
【发布时间】:2022-01-07 07:05:23
【问题描述】:

背景。

我正在尝试在 Math SE 上编写 this 答案的 实现。您可能会发现以下背景很有用。


问题

我有一个实验装置,由三 (3) 个接收器组成,它们的位置已知 [xi, yi, zi],以及一个发射器 unknown 位置 [x,y,z]已知处发射信号> 速度v。该信号在已知时间ti 到达接收器。发射时间,t未知

我希望找到到达角(即发射器的极坐标thetaphi),仅给出这些信息。

解决方案

不可能只用三 (3) 个接收器准确定位发射器,除了少数特殊情况(Math SE 中有几个很好的答案解释为什么会这样)。通常,至少需要四个(实际上是 >>4 个)接收器来唯一确定发射器的直角坐标。

然而,可以“可靠地”估计到发射器的方向。令vi 为表示接收器i 位置的向量,ti 为信号到达接收器i 的时间,n 为表示指向(近似)方向的单位向量的向量发射机,我们得到以下方程:

<n, vj - vi> = v(ti - tj)

(其中< > 表示标量积)

...对于所有索引对i,j。与|n| = 1 一起,系统一般有2 个解决方案,通过vi/vj/vk 在平面内反射对称。然后我们可以通过在极坐标中简单地写n来确定phitheta


实施。

我尝试使用fsolve 编写上述解决方案的 实现。

from dataclasses import dataclass
import scipy.optimize
import random
import math

c = 299792

@dataclass
class Vertexer:

        roc: list

        def fun(self, var, dat):
                (x,y,z) = var

                eqn_0 = (x * (self.roc[0][0] - self.roc[1][0])) + (y * (self.roc[0][1] - self.roc[1][1])) + (z * (self.roc[0][2] - self.roc[1][2])) - c * (dat[1] - dat[0])
                eqn_1 = (x * (self.roc[0][0] - self.roc[2][0])) + (y * (self.roc[0][1] - self.roc[2][1])) + (z * (self.roc[0][2] - self.roc[2][2])) - c * (dat[2] - dat[0])
                eqn_2 = (x * (self.roc[1][0] - self.roc[2][0])) + (y * (self.roc[1][1] - self.roc[2][1])) + (z * (self.roc[1][2] - self.roc[2][2])) - c * (dat[2] - dat[1])

                norm = math.sqrt(x**2 + y**2 + z**2) - 1

                return [eqn_0, eqn_1, eqn_2, norm]

        def find(self, dat):
                result = scipy.optimize.fsolve(self.fun, (0,0,0), args=dat)
                print('Solution ', result)

# Crude code to simulate a source, receivers at random locations

x0 = random.randrange(0,50); y0 = random.randrange(0,50); z0 = random.randrange(0,50)

x1 = random.randrange(0,50); x2 = random.randrange(0,50); x3 = random.randrange(0,50);
y1 = random.randrange(0,50); y2 = random.randrange(0,50); y3 = random.randrange(0,50);
z1 = random.randrange(0,50); z2 = random.randrange(0,50); z3 = random.randrange(0,50);

t1 = math.sqrt((x0-x1)**2 + (y0-y1)**2 + (z0-z1)**2)/c
t2 = math.sqrt((x0-x2)**2 + (y0-y2)**2 + (z0-z2)**2)/c
t3 = math.sqrt((x0-x3)**2 + (y0-y3)**2 + (z0-z3)**2)/c

print('Actual coordinates ', x0,y0,z0)

myVertexer = Vertexer([[x1,y1,z1], [x2,y2,z2], [x3,y3,z3]])
myVertexer.find([t1,t2,t3])

不幸的是,我在C/C++ 中使用GSL 解决此类问题的经验要多得多,而使用 等的经验有限。我收到了错误:

TypeError: fsolve: there is a mismatch between the input and output shape of the 'func' argument 'fun'.Shape should be (3,) but it is (4,).

...这似乎表明fsolve 需要一个正方形系统。

我该如何解决这个矩形系统?我似乎在 文档中找不到任何有用的东西。

如有必要,我愿意使用其他 (Python) 库。

【问题讨论】:

  • 你可以消除 eqn_2,因为 (eqn_0 = eqn_1 - eqn_2),你可以使用矩阵表示。

标签: python python scipy scipy scipy python math scipy mathematical-optimization scipy-optimize


【解决方案1】:

正如你已经提到的,fsolve 期望一个具有 N 个变量和 N 个方程的系统,即它找到函数 F 的根:R^N -> R^N。由于您有四个方程,您只需添加第四个变量。另请注意,fsolve 是一个遗留函数,建议改用root。最后但同样重要的是,请注意sqrt(x^2+y^2+z^2) = 1 等价于x^2+y^2+z^2=1,并且后者在逼近 F 的雅可比时更不容易受到由有限差分引起的舍入误差的影响。

长话短说,你的班级应该是这样的:

from scipy.optimize import root

@dataclass
class Vertexer:
        roc: list
        def fun(self, var, dat):
                x,y,z, *_ = var
                eqn_0 = (x * (self.roc[0][0] - self.roc[1][0])) + (y * (self.roc[0][1] - self.roc[1][1])) + (z * (self.roc[0][2] - self.roc[1][2])) - c * (dat[1] - dat[0])
                eqn_1 = (x * (self.roc[0][0] - self.roc[2][0])) + (y * (self.roc[0][1] - self.roc[2][1])) + (z * (self.roc[0][2] - self.roc[2][2])) - c * (dat[2] - dat[0])
                eqn_2 = (x * (self.roc[1][0] - self.roc[2][0])) + (y * (self.roc[1][1] - self.roc[2][1])) + (z * (self.roc[1][2] - self.roc[2][2])) - c * (dat[2] - dat[1])
                norm = x**2 + y**2 + z**2 - 1
                return [eqn_0, eqn_1, eqn_2, norm]

        def find(self, dat):
                result = root(self.fun, (0,0,0,0), args=dat)
                if result.success:
                        print('Solution ', result.x[:3])

【讨论】:

  • 感谢您查看此内容!我有一个问题。由于只有三个未知数——在数学上,这第四个变量的含义是什么(SciPy 给出了解决方案)?
  • 它没有特殊意义,因为你的方程都不依赖于第四个变量。话虽如此,让我们用 (x1*,x2*,x3*,x4*) 来表示解决方案。那么,任意a的每一个(x1*,x2*,x3*,a)都是系统的解。
猜你喜欢
  • 1970-01-01
  • 2018-01-17
  • 2019-01-15
  • 1970-01-01
  • 2013-11-14
  • 2019-01-21
  • 1970-01-01
  • 2021-12-06
  • 1970-01-01
相关资源
最近更新 更多