自定义简化(规则和模式)
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
您好,我是 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