自定义简化(规则和模式)

Custom simplification (rules and patterns)

您好,我是 maxima 的新手。 我怎样才能注意到并简化点积之类的东西?

尝试 1:

tellsimpafter(a[1]*b[1]+a[2]*b[2], dot(a,b));

适用于 a[1]*b[1]+a[2]*b[2] 但不适用于 v[1]*w[1]+v[2]*w[2]w[2]*v[2]+123+v[1]*w[1]

尝试 2:

matchdeclare(a, lambda([x], length(x)=2));
matchdeclare(b, lambda([x], length(x)=2));
tellsimpafter(a[1]*b[1]+a[2]*b[2], dot(a,b));

甚至不适用于 a[1]*b[1]+a[2]*b[2]

这是一个可能的解决方案。假设您知道数组的名称,提取内积很简单。然后用所有可能的数组名称循环它,通过查看表达式中的下标变量来确定。

/* solution for  */

/* try all combinations of potential arrays in succession */

contract_inner_products (e) :=
 (for S in powerset (subscripted_variables(e), 2)
    do block ([%xx: first(S), %yy: second(S)],
              e: apply1 (e, rule_contract_inner_product)),
  e);

/* extract potential arrays */

subscripted_variables (e) :=
  setify (map (op, sublist (listofvars(e), subvarp)));

/* contract inner product, assuming arrays have been identified */

matchdeclare (aa, lambda([e], freeof(%xx, e) or freeof(%yy, e)),
              bb, lambda([e], freeof(%xx, e) and freeof(%yy, e)),
              xx, lambda([e], e = %xx), yy, lambda([e], e = %yy));

defrule (rule_contract_inner_product, aa + bb*xx[1]*yy[1] + bb*xx[2]*yy[2], aa + bb*dot(xx, yy));

这里有一些例子。

(%i3) dotgh: g[1]*h[1] + g[2]*h[2] $
(%i4) dotab: a[1]*b[1] + a[2]*b[2] $
(%i5) dotxy: x[1]*y[1] + x[2]*y[2] $
(%i6) contract_inner_products (dotgh);
(%o6)                       dot(g, h)
(%i7) contract_inner_products (dotgh + dotxy);
(%o7)                 dot(x, y) + dot(g, h)
(%i8) contract_inner_products (dotgh - dotxy);
(%o8)                 dot(g, h) - dot(x, y)
(%i9) contract_inner_products (dotgh - 2*dotxy);
(%o9)                dot(g, h) - 2 dot(x, y)
(%i10) contract_inner_products (n/2*dotgh - 2*dotxy);
                    dot(g, h) n
(%o10)              ----------- - 2 dot(x, y)
                         2
(%i11) contract_inner_products (n/2*dotgh - 2*dotxy - 6*%pi^2);
                               dot(g, h) n        2
(%o11)       (- 2 dot(x, y)) + ----------- - 6 %pi
                                    2

它似乎适用于 dot(x, y) + dot(x, z) 形式的内容。

(%i12) contract_inner_products (dotgh + g[1]*f[1] + g[2]*f[2]);
(%o12)                dot(g, h) + dot(f, g)
(%i13) contract_inner_products (dotgh + g[1]*f[1] + g[2]*f[2] + 123);
(%o13)             dot(g, h) + dot(f, g) + 123
(%i14) contract_inner_products (dotgh + g[1]*x[1] + g[2]*x[2] + 123);
(%o14)             dot(g, x) + dot(g, h) + 123
(%i15) contract_inner_products (dotgh + h[1]*x[1] + h[2]*x[2] + 123);
(%o15)             dot(h, x) + dot(g, h) + 123

我真的没想到它对 dot(x, y) + dot(x, z) 有效,但无论如何这很好。

如果您在其他示例中尝试使用它,您可能会发现此方法无法识别的一些情况。

编辑:请注意,可能的点积不必位于表达式的顶层。它也在子表达式中寻找潜在的内积。

(%i11) 1/(1 - dotab/4);
                                1
(%o11)                  -----------------
                            a  b  + a  b
                             2  2    1  1
                        1 - -------------
                                  4
(%i12) contract_inner_products(%);
                                1
(%o12)                    -------------
                              dot(a, b)
                          1 - ---------
                                  4
(%i13) expand (%o11);
                                1
(%o13)                ---------------------
                         a  b     a  b
                          2  2     1  1
                      (- -----) - ----- + 1
                           4        4
(%i14) contract_inner_products(%);
                                1
(%o14)                    -------------
                              dot(a, b)
                          1 - ---------
                                  4