在 Mathematica 中求解向量方程

发布于 2024-08-19 04:21:48 字数 1300 浏览 3 评论 0原文

我试图弄清楚如何使用 Mathematica 来求解其中一些变量和系数是向量的方程组。一个简单的例子是

A + Vt = Pt

我知道 A< /strong>、VP 的大小,我必须求解 t方向 (基本上,给定两条射线 A 和 B,我知道 A 的一切,但只知道 B 的原点和大小,找出 B 的方向必须是这样,才能与 A 相交。)

现在,我知道如何手动解决这类问题,但这很慢而且容易出错,所以我希望可以使用 Mathematica 来加快速度并进行错误检查。但是,我不知道如何让 Mathematica 以符号方式求解涉及此类向量的方程。

我查看了 VectorAnalysis 包,但没有找到任何似乎相关的内容;同时,线性代数包似乎只有线性系统的求解器(这不是,因为我不知道tP,只是| 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 } 
     ]

但是吐出的“解决方案”是一大堆系数和拥塞。它还迫使我扩展我所提供的每个维度。

我想要的是在点积、叉积和规范方面有一个很好的符号解决方案:

alt text

但我不知道如何告诉 Solve 某些系数是向量而不是标量。

这可能吗? Mathematica 能给我向量的符号解吗?或者我应该坚持使用 No.2 Pencil 技术?

(需要明确的是,我对顶部特定方程的解不感兴趣——我问的是我是否可以使用 Mathematica 来解决这样的计算几何问题,而不必将所有内容表示为显式矩阵{Ax、Ay、Az} 等)

I'm trying to figure out how to use Mathematica to solve systems of equations where some of the variables and coefficients are vectors. A simple example would be something like

A + Vt = Pt

where I know A, V, and the magnitude of P, and I have to solve for t and the direction of P. (Basically, given two rays A and B, where I know everything about A but only the origin and magnitude of B, figure out what the direction of B must be such that it intersects A.)

Now, I know how to solve this sort of thing by hand, but that's slow and error-prone, so I was hoping I could use Mathematica to speed things along and error-check me. However, I can't see how to get Mathematica to symbolically solve equations involving vectors like this.

I've looked in the VectorAnalysis package, without finding anything there that seems relevant; meanwhile the Linear Algebra package only seems to have a solver for linear systems (which this isn't, since I don't know t or P, just |P|).

I tried doing the simpleminded thing: expanding the vectors into their components (pretend they're 3D) and solving them as if I were trying to equate two parametric functions,

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 } 
     ]

but the "solution" that spits out is a huge mess of coefficients and congestion. It also forces me to expand out each of the dimensions I feed it.

What I want is a nice symbolic solution in terms of dot products, cross products, and norms:

alt text

But I can't see how to tell Solve that some of the coefficients are vectors instead of scalars.

Is this possible? Can Mathematica give me symbolic solutions on vectors? Or should I just stick with No.2 Pencil technology?

(Just to be clear, I'm not interested in the solution to the particular equation at top -- I'm asking if I can use Mathematica to solve computational geometry problems like that generally without my having to express everything as an explicit matrix of {Ax, Ay, Az}, etc.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一梦浮鱼 2024-08-26 04:21:48

对于 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 = {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]

输出:

{{P[1] -> 1 + 4 t, P[2] -> 2 + 5 t, P[3] -> 3 (1 + 2 t)}}

矩阵向量内积:

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

输出:

{{x[1] -> 1/23 (-7 b[1] + 5 b[2]), x[2] -> 1/23 (6 b[1] - b[2])}}

矩阵乘法:

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

输出:

{{B[1, 1] -> -(2/23), B[2, 1] -> 28/23, B[1, 2] -> -(4/23), B[2, 2] -> 33/23}}

点积有一个内置的中缀表示法,只需使用句点作为点。

然而,我认为叉积不会。这就是使用 Notation 包来制作一个的方法。 “X”将成为十字的中缀形式。我建议使用 Notation、Symbolize 和 InfixNotation 教程中的示例。还可以使用符号调色板,它有助于抽象出一些 Box 语法。

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}

输出:

{-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中使用符号包时遇到了一些怪癖,所以要小心。


With 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]

outputs:

{{P1 -> 1 + 4 t, P2 -> 2 + 5 t, P3 -> 3 (1 + 2 t)}}

Typing out P = {P1, P2, P3} can be annoying if the array or matrix is large.

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

outputs:

{{P[1] -> 1 + 4 t, P[2] -> 2 + 5 t, P[3] -> 3 (1 + 2 t)}}

Matrix vector inner product:

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

outputs:

{{x[1] -> 1/23 (-7 b[1] + 5 b[2]), x[2] -> 1/23 (6 b[1] - b[2])}}

Matrix multiplication:

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

outputs:

{{B[1, 1] -> -(2/23), B[2, 1] -> 28/23, B[1, 2] -> -(4/23), B[2, 2] -> 33/23}}

The dot product has an infix notation built in just use a period for the dot.

I do not think the cross product does however. This is how you use the Notation package to make one. "X" will become our infix form of Cross. I suggest coping the example from the Notation, Symbolize and InfixNotation tutorial. Also use the Notation Palette which helps abstract away some of the Box syntax.

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}

outputs:

{-c y + b z, c x - a z, -b x + a y}

The above looks horrible but when using the Notation Palette it looks like:

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

I have run into some quirks using the notation package in the past versions of mathematica so be careful.

凉城 2024-08-26 04:21:48

无论如何,我都没有为您提供通用的解决方案(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};

这些规则将简化向量范数和点积的关系(叉积对于读者来说可能是一个痛苦的练习)。 编辑: 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)}

就像我说的,这不是通过任何方式解决此类问题的完整方法,但如果从模式匹配和规则替换的角度来看,如果您小心地将问题转化为易于处理的术语,那么您可以走得很远。

I don't have a general solution for you by any means (MathForum may be the better way to go), but there are some tips that I can offer you. The first is to do the expansion of your vectors into components in a more systematic way. For instance, I would solve the equation you wrote as follows.

rawSol = With[{coords = {x, y, z}},
  Solve[
    Flatten[
     {A[#] + V[#] t == P[#] t & /@ coords,
     Total[P[#]^2 & /@ coords] == P^2}],
    Flatten[{t, P /@ coords}]]];

Then you can work with the rawSol variable more easily. Next, because you are referring the vector components in a uniform way (always matching the Mathematica pattern v_[x|y|z]), you can define rules that will aid in simplifying them. I played around a bit before coming up with the following rules:

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};

These rules will simplify the relationships for vector norms and dot products (cross-products are left as a likely painful exercise for the reader). EDIT: rcollyer pointed out that you can make c optional in the rule for dot products, so you only need two rules for norms and dot products.

With these rules, I was immediately able to simplify the solution for t into a form very close to yours:

  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)}

Like I said, it's not a complete way of solving these kinds of problems by any means, but if you're careful about casting the problem into terms that are easy to work with from a pattern-matching and rule-replacement standpoint, you can go pretty far.

紅太極 2024-08-26 04:21:48

我对这个问题采取了一些不同的方法。我做了一些返回此输出的定义:
vExpand 示例
已知向量的模式可以使用 vec[_] 指定,模式具有 OverVector[]OverHat[] 包装器(带有矢量或帽子的符号)默认被假定为矢量。

这些定义是实验性的,应该被视为实验性的,但它们似乎运作良好。我希望随着时间的推移会对此进行补充。

以下是定义。需要粘贴到 Mathematica Notebook 单元格中并转换为 StandardForm 才能正确查看它们。

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];

I've taken a somewhat different approach to this issue. I've made some definitions that return this output:
vExpand examples
Patterns that are known to be vector quantities may be specified using vec[_], patterns that have an OverVector[] or OverHat[] wrapper (symbols with a vector or hat over them) are assumed to be vectors by default.

The definitions are experimental and should be treated as such, but they seem to work well. I expect to add to this over time.

Here are the definitions. The need to be pasted into a Mathematica Notebook cell and converted to StandardForm to see them properly.

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];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文