Wolfram mathematica 在Mathematica中求解向量方程

Wolfram mathematica 在Mathematica中求解向量方程,wolfram-mathematica,linear-algebra,Wolfram Mathematica,Linear Algebra,我想知道如何使用Mathematica来解方程组,其中一些变量和系数是向量。一个简单的例子如下 其中我知道AA,V和p的大小,我必须求解t和p的方向(基本上,给定两条射线A和B,我知道关于A的一切,但只知道B的原点和大小,计算出B的方向必须是什么,它与A相交。) 现在,我知道如何用手来解决这类问题,但这很慢而且容易出错,所以我希望我能用Mathematica来加快速度并检查我的错误。然而,我看不出如何让Mathematica符号化地解决涉及向量的方程,就像这样 我查看了VectorAnalys

我想知道如何使用Mathematica来解方程组,其中一些变量和系数是向量。一个简单的例子如下

其中我知道AAV和p的大小,我必须求解t和p的方向(基本上,给定两条射线A和B,我知道关于A的一切,但只知道B的原点和大小,计算出B的方向必须是什么,它与A相交。)

现在,我知道如何用手来解决这类问题,但这很慢而且容易出错,所以我希望我能用Mathematica来加快速度并检查我的错误。然而,我看不出如何让Mathematica符号化地解决涉及向量的方程,就像这样

我查看了VectorAnalysis软件包,没有发现任何相关的内容;同时,线性代数包似乎只有一个线性系统的解算器(这不是,因为我不知道t或P,只是|P

我试着做一件简单的事情:将向量展开成它们的组件(假装它们是3D的),然后解决它们,就像我试图将两个参数函数相等一样

Solve[ 
      { Function[t, {Bx + Vx*t, By + Vy*t, Bz + Vz*t}][t] == 
          Function[t, {Px*t, Py*t, Pz*t}][t],
        Px^2 + Py^2 + Pz^2 == Q^2 } , 
      { t, Px, Py, Pz } 
     ]
但“解决方案”是系数和拥塞的巨大混乱。它还迫使我扩展我提供给它的每个维度

我想要的是一个很好的符号解决方案,包括点积、交叉积和规范:

但是我看不出如何告诉
Solve
一些系数是向量而不是标量

这可能吗?Mathematica能给我向量的符号解吗?还是我应该坚持使用2号铅笔技术


(说得清楚一点,我对上面这个特殊方程的解不感兴趣——我想问的是,我是否可以用Mathematica来解决这样的计算几何问题,而不必把所有问题都表示为
{Ax,Ay,Az}
等的显式矩阵。)

我没有一个通用的解(MathForum可能是更好的方法),但我可以给你一些提示。首先是以更系统的方式将向量展开为分量。例如,我会解你写的方程,如下所示

rawSol = With[{coords = {x, y, z}},
  Solve[
    Flatten[
     {A[#] + V[#] t == P[#] t & /@ coords,
     Total[P[#]^2 & /@ coords] == P^2}],
    Flatten[{t, P /@ coords}]]];
然后,您可以更轻松地使用
rawSol
变量。接下来,因为您以统一的方式引用向量分量(始终匹配Mathematica模式
v|[x | y | z]
),所以您可以定义有助于简化它们的规则。在提出以下规则之前,我进行了一些讨论:

vectorRules =
  {forms___ + vec_[x]^2 + vec_[y]^2 + vec_[z]^2 :> forms + vec^2,
   forms___ + c_. v1_[x]*v2_[x] + c_. v1_[y]*v2_[y] + c_. v1_[z]*v2_[z] :>
     forms + c v1\[CenterDot]v2};
这些规则将简化向量范数和点积的关系(交叉积对于读者来说可能是一个痛苦的练习)。EDIT:rcollyer指出,你可以在点积规则中选择
c
,因此你只需要两条范数和点积规则

有了这些规则,我可以立即将
t
的解决方案简化为与您非常相似的形式:

  In[3] := t /. rawSol //. vectorRules // Simplify // InputForm
  Out[3] = {(A \[CenterDot] V - Sqrt[A^2*(P^2 - V^2) + 
                                   (A \[CenterDot] V)^2])/(P^2 - V^2), 
            (A \[CenterDot] V + Sqrt[A^2*(P^2 - V^2) + 
                                   (A \[CenterDot] V)^2])/(P^2 - V^2)}
正如我所说,这并不是通过任何方式解决这类问题的完整方法,但如果您从模式匹配和规则替换的角度小心地将问题转化为易于处理的术语,您可以走得很远。


使用Mathematica 7.0.1.0

Clear[A, V, P];
A = {1, 2, 3};
V = {4, 5, 6};
P = {P1, P2, P3};
Solve[A + V t == P, P]
产出:

{{P1 -> 1 + 4 t, P2 -> 2 + 5 t, P3 -> 3 (1 + 2 t)}}
{{P[1] -> 1 + 4 t, P[2] -> 2 + 5 t, P[3] -> 3 (1 + 2 t)}}
{{x[1] -> 1/23 (-7 b[1] + 5 b[2]), x[2] -> 1/23 (6 b[1] - b[2])}}
{{B[1, 1] -> -(2/23), B[2, 1] -> 28/23, B[1, 2] -> -(4/23), B[2, 2] -> 33/23}}
{-c y + b z, c x - a z, -b x + a y}
如果数组或矩阵很大,键入p={P1,P2,P3}可能会让人恼火

Clear[A, V, PP, P];
A = {1, 2, 3};
V = {4, 5, 6};
PP = Array[P, 3];
Solve[A + V t == PP, PP]
产出:

{{P1 -> 1 + 4 t, P2 -> 2 + 5 t, P3 -> 3 (1 + 2 t)}}
{{P[1] -> 1 + 4 t, P[2] -> 2 + 5 t, P[3] -> 3 (1 + 2 t)}}
{{x[1] -> 1/23 (-7 b[1] + 5 b[2]), x[2] -> 1/23 (6 b[1] - b[2])}}
{{B[1, 1] -> -(2/23), B[2, 1] -> 28/23, B[1, 2] -> -(4/23), B[2, 2] -> 33/23}}
{-c y + b z, c x - a z, -b x + a y}
矩阵向量内积:

Clear[A, xx, bb];
A = {{1, 5}, {6, 7}};
xx = Array[x, 2];
bb = Array[b, 2];
Solve[A.xx == bb, xx]
产出:

{{P1 -> 1 + 4 t, P2 -> 2 + 5 t, P3 -> 3 (1 + 2 t)}}
{{P[1] -> 1 + 4 t, P[2] -> 2 + 5 t, P[3] -> 3 (1 + 2 t)}}
{{x[1] -> 1/23 (-7 b[1] + 5 b[2]), x[2] -> 1/23 (6 b[1] - b[2])}}
{{B[1, 1] -> -(2/23), B[2, 1] -> 28/23, B[1, 2] -> -(4/23), B[2, 2] -> 33/23}}
{-c y + b z, c x - a z, -b x + a y}
矩阵乘法:

Clear[A, BB, d];
A = {{1, 5}, {6, 7}};
BB = Array[B, {2, 2}];
d = {{6, 7}, {8, 9}};
Solve[A.BB == d]
产出:

{{P1 -> 1 + 4 t, P2 -> 2 + 5 t, P3 -> 3 (1 + 2 t)}}
{{P[1] -> 1 + 4 t, P[2] -> 2 + 5 t, P[3] -> 3 (1 + 2 t)}}
{{x[1] -> 1/23 (-7 b[1] + 5 b[2]), x[2] -> 1/23 (6 b[1] - b[2])}}
{{B[1, 1] -> -(2/23), B[2, 1] -> 28/23, B[1, 2] -> -(4/23), B[2, 2] -> 33/23}}
{-c y + b z, c x - a z, -b x + a y}
点积有一个内置的中缀符号,只需为点使用一个句点

然而,我不认为叉积是这样。这是您使用符号包制作叉的方式。“X”将成为我们的叉的中缀形式。我建议从符号、符号和中缀符号教程中学习这个例子。还可以使用符号调色板,这有助于抽象出一些方框语法

Clear[X]
Needs["Notation`"]
Notation[x_ X y_\[DoubleLongLeftRightArrow]Cross[x_, y_]]
Notation[NotationTemplateTag[
  RowBox[{x_,  , X,  , y_,  }]] \[DoubleLongLeftRightArrow] 
  NotationTemplateTag[RowBox[{ , 
RowBox[{Cross, [, 
RowBox[{x_, ,, y_}], ]}]}]]]
{a, b, c} X {x, y, z}
产出:

{{P1 -> 1 + 4 t, P2 -> 2 + 5 t, P3 -> 3 (1 + 2 t)}}
{{P[1] -> 1 + 4 t, P[2] -> 2 + 5 t, P[3] -> 3 (1 + 2 t)}}
{{x[1] -> 1/23 (-7 b[1] + 5 b[2]), x[2] -> 1/23 (6 b[1] - b[2])}}
{{B[1, 1] -> -(2/23), B[2, 1] -> 28/23, B[1, 2] -> -(4/23), B[2, 2] -> 33/23}}
{-c y + b z, c x - a z, -b x + a y}
上面看起来很糟糕,但使用符号调色板时,它看起来像:

Clear[X]
Needs["Notation`"]
Notation[x_ X y_\[DoubleLongLeftRightArrow]Cross[x_, y_]]
{a, b, c} X {x, y, z}

在过去版本的mathematica中,我在使用符号包时遇到了一些怪癖,因此请小心。

我对这个问题采取了一些不同的方法。我给出了一些返回此输出的定义: 已知为矢量量的图案可以使用
vec[\u]
指定,默认情况下,具有
OverVector[]
OverHat[]
包装器(带有矢量或帽子的符号)的图案被假定为矢量

这些定义是实验性的,应该被视为实验性的,但它们似乎很有效。我希望随着时间的推移,能够补充这一点

以下是定义。需要将这些定义粘贴到Mathematica笔记本单元格中,并转换为标准格式才能正确查看它们

Unprotect[vExpand,vExpand$,Cross,Plus,Times,CenterDot];

(* vec[pat] determines if pat is a vector quantity.
vec[pat] can be used to define patterns that should be treated as vectors.
Default: Patterns are assumed to be scalar unless otherwise defined *)
vec[_]:=False;

(* Symbols with a vector hat, or vector operations on vectors are assumed to be vectors *)
vec[OverVector[_]]:=True;
vec[OverHat[_]]:=True;

vec[u_?vec+v_?vec]:=True;
vec[u_?vec-v_?vec]:=True;
vec[u_?vec\[Cross]v_?vec]:=True;
vec[u_?VectorQ]:=True;

(* Placeholder for matrix types *)
mat[a_]:=False;

(* Anything not defined as a vector or matrix is a scalar *)
scal[x_]:=!(vec[x]\[Or]mat[x]);
scal[x_?scal+y_?scal]:=True;scal[x_?scal y_?scal]:=True;

(* Scalars times vectors are vectors *)
vec[a_?scal u_?vec]:=True;
mat[a_?scal m_?mat]:=True;

vExpand$[u_?vec\[Cross](v_?vec+w_?vec)]:=vExpand$[u\[Cross]v]+vExpand$[u\[Cross]w];
vExpand$[(u_?vec+v_?vec)\[Cross]w_?vec]:=vExpand$[u\[Cross]w]+vExpand$[v\[Cross]w];
vExpand$[u_?vec\[CenterDot](v_?vec+w_?vec)]:=vExpand$[u\[CenterDot]v]+vExpand$[u\[CenterDot]w];
vExpand$[(u_?vec+v_?vec)\[CenterDot]w_?vec]:=vExpand$[u\[CenterDot]w]+vExpand$[v\[CenterDot]w];

vExpand$[s_?scal (u_?vec\[Cross]v_?vec)]:=Expand[s] vExpand$[u\[Cross]v];
vExpand$[s_?scal (u_?vec\[CenterDot]v_?vec)]:=Expand[s] vExpand$[u\[CenterDot]v];

vExpand$[Plus[x__]]:=vExpand$/@Plus[x];
vExpand$[s_?scal,Plus[x__]]:=Expand[s](vExpand$/@Plus[x]);
vExpand$[Times[x__]]:=vExpand$/@Times[x];

vExpand[e_]:=e//.e:>Expand[vExpand$[e]]

(* Some simplification rules *)
(u_?vec\[Cross]u_?vec):=\!\(\*OverscriptBox["0", "\[RightVector]"]\);
(u_?vec+\!\(\*OverscriptBox["0", "\[RightVector]"]\)):=u;
0v_?vec:=\!\(\*OverscriptBox["0", "\[RightVector]"]\);

\!\(\*OverscriptBox["0", "\[RightVector]"]\)\[CenterDot]v_?vec:=0;
v_?vec\[CenterDot]\!\(\*OverscriptBox["0", "\[RightVector]"]\):=0;

(a_?scal u_?vec)\[Cross]v_?vec :=a u\[Cross]v;u_?vec\[Cross](a_?scal v_?vec ):=a u\[Cross]v;
(a_?scal u_?vec)\[CenterDot]v_?vec :=a u\[CenterDot]v;
u_?vec\[CenterDot](a_?scal v_?vec) :=a u\[CenterDot]v;

(* Stealing behavior from Dot *)
Attributes[CenterDot]=Attributes[Dot];

Protect[vExpand,vExpand$,Cross,Plus,Times,CenterDot];

也许你也值得花时间问Mathematica的人这个问题。他们可能比我们更了解自己的软件。我会尝试在MathGroup论坛()上发帖。这看起来不像是简单的邮寄support@wolfram.com将提供有用的结果。但令人惊讶的是,信噪比的频率(以及整个系统)在这里比在“老式”邮件列表/论坛/新闻组中更好。两个点积规则可以合并为一个,方法是将第一个规则中的
c
替换为
c.
c:1
,其中句点告诉Mathematica使用标准默认值进行乘法[A+V t==P,P]您错过了
t
相乘
P
。您用
键入了叉积:esc:cross:esc:
@rcollyer我的错误,应该可以与加法一起使用。@KennyTM感谢您指出这一点。