Wolfram Mathematica中的Sum []和Sequence []

时间:2013-12-13 21:11:55

标签: wolfram-mathematica

我需要评估可变数量集的笛卡尔积的和。假设f [...]是多变量函数,请定义

p[A__set] :=  Module[{Alist, args, iterators,it},
  Alist = {A};
  i = 1;
  iterators = {it[i++], Level[#1, 1]} & /@ Alist;
  args = Table[it[i], {i, Range[Length[Alist]]}];
  Sum[f@@ args, Sequence @@ iterators ]
]

但是

p[set[1, 2, 3], set[11, 12, 13]]

给出错误:     Sum::vloc: "The variable Sequence@@iterators cannot be localized so that it can be assigned to numerical values."

以下黑客有效:

p[A__set] :=  Module[{Alist, args, iterators,it,TmpSymbol},
  Alist = {A};
  i = 1;
  iterators = {it[i++], Level[#1, 1]} & /@ Alist;
  args = Table[it[i], {i, Range[Length[Alist]]}];
  Sum@@TmpSymbol[f @@ args, Sequence @@ iterators ]
]

然后

p[set[1, 2, 3], set[11, 12]]

给出我想要的东西:

f[1, 11] + f[1, 12] + f[2, 11] + f[2, 12] + f[3, 11] + f[3, 12]

我想知道为什么原件没有。

根据 belisarius ,有更优雅的方式来做到这一点:

p[A__set] := Total[Outer[f, A],Length[{A}]];

2 个答案:

答案 0 :(得分:4)

这与评估顺序有关。请参阅Tutorial: Evaluation作为参考。

Sum具有属性HoldAll

Attributes[Sum]
{HoldAll, Protected, ReadProtected}

由于这一点,只有EvaluateSequence等某些头的参数或带 upvalues的符号才会进行评估。你可能认为你的论证Sequence @@ iterators有头Sequence,但它实际上有头Apply

HoldForm @ FullForm[Sequence @@ iterators]
Apply[Sequence, iterators]

Sum期望文字参数与其声明的语法相匹配,因此您的代码失败。您可以通过多种不同方式强制进行评估。可以说最透明的是添加Evaluate

iterators = {{a, 1, 3}, {b, 5, 7}};

Sum[a^2/b, Evaluate[Sequence @@ iterators]]
107/15

更简洁地说,您可以利用FunctionSlotSequenceApply;由于默认情况下ApplyFunction都没有HoldAll,因此进行评估:

Sum[a^2/b, ##] & @@ iterators
107/15

然而,这两个都存在潜在问题:如果ab收到全局值,iterators定义中的符号将评估为此值,从而导致另一个错误:

a = 0;

Sum[a^2/b, ##] & @@ iterators
  

Sum :: itraw:原始对象0不能用作迭代器。 >>

相反,您可以将迭代器列表存储在Hold表达式中,并使用" injector pattern"插入这些值而不进行完整评估:

iterators = Hold[{a, 1, 3}, {b, 5, 7}];

iterators /. _[x__] :> Sum[a^2/b, x]
107/15

或者,您可以将iterators定义为 upvalue

Sum[args___, iterators] ^:= Sum[args, {a, 1, 3}, {b, 5, 7}]

现在简单地说:

Sum[a^2/b, iterators]
107/15

有关更多示例,请参阅Keep function range as a variable Mathematica.SE的答案,因为这个问题密切相关。具体请参阅我的第二个答案中的setSpec,它会自动创建 upvalue

答案 1 :(得分:1)

在Mathematica中有很多简单的方法:

Total[Outer[f, {1, 2, 3}, {11, 12}, {a, b}],3]
(*
f[1, 11, a] + f[1, 11, b] + f[1, 12, a] + f[1, 12, b] +
f[2, 11, a] + f[2, 11, b] + f[2, 12, a] + f[2, 12, b] + 
f[3, 11, a] + f[3, 11, b] + f[3, 12, a] + f[3, 12, b]
*)