我想实现条件期望运算符。我将使用大写epsilon E
来表示运算符。我期望至少以下输入(下划线表示下标)
E_2[a]
E_2[x_1]
E_2[x_1 + y_5]
E_1[3 a + b - 4 + 2 x_]
E_6[x_5 x_7]
E_t[x_t]
E_t[3 x_{t - 1} x_{t + 2}]
生成以下输出
a
x_1
E_2[y_5] + x_1
-4 + 3 a + b + 2 E_2[x_5]
E_6[x_7] x_5
x_t
3 E_t[x_{t + 2}] x_{t - 1}
上面的示例并不是我需要生成的唯一输入/输出对,而是作为我喜欢的语法的测试和说明。
我到目前为止。 ce
表示条件期望,其第三个组成部分是“期望传播”是否已完成(否则无限递归发生在产品规则中),mv
代表可衡量变量。
Notation[Subscript[E, t_][y_] ==> ce[y_, t_, False]];
Notation[Subscript[E, t_][y_] <== ce[y_, t_, _]];
Notation[Subscript[x_, t_] <==> mv[x_, t_]];
(* Atomic Elements and Measurable Variables *)
ce[x_, t_, _] := x /; (AtomQ[x] || Head[x] === mv && 0 <= t - x[[2]]);
(* Distribution over Addition *)
ce[x_ + y__, t_, s_] := ce[x, t, s] + Plus @@ (ce[#, t, s] & /@ {y});
(* Distribution over Product *)
ce[x__Times, t_, False] := Module[{v, m, n},
(* All Variables in the Product *)
v = List @@ x;
(* Measurable Among Them *)
m = Select[v, AtomQ[#] || Head[#] === mv && 0 <= t - #[[2]] &];
(* The Rest is not Measurable *)
n = Complement[v, m];
Times[Times @@ m, ce[Times @@ n, t, True]]
];
答案 0 :(得分:3)
我想我可以让你接近你想要的东西;不过,我不打算这么做,因为它可能很棘手,但我会指出你正确的方向。
首先,使用下标来表示不同的变量在Mathematica中很棘手,因为它将E
0
解释为Subscript[E,0]
和E
并保留Subscript
。 (正如Sjoerd所说,E = 2.718...
。)要让Mathematica将<anything>
<something>
识别为一个独特的符号,您需要通过{{1}加载Notations包}}。然后使用Notations Palette,<<Notations`
Symbolize
。 (请注意,如果不使用调色板正确设置代码,请不要尝试这样做,否则可能无效。)
根据需要对所有变量进行符号化后,需要设置相应的转换规则。前两个是最简单的,输入
Subscript[E,0]
规则3和4:
E_0[a] = a
E_0[x_0] = x_0
这些是容易的,接下来的三个需要不同类型的关联,Set
和SetDelayed
都不会在这里工作,因为被评估的外部符号是E_0[x_Plus]:=Distribute[E_0[x]]
E_0[x_Times]:=Distribute[E_0[x], Times]
,你可以不要将新规则与Protected
关联起来。但是,有两种方法可以将这些表达式与内部符号相关联:UpSet (^=)
(或UpSetDelayed (^:=)
)或TagSet (/:)
。我更喜欢使用Dt
,因为它更明确,但要么应该有效。
规则5和6:
TagSet
这也会让你接近规则7,但是在规则3和规则4的同时添加它会导致递归限制错误,因为它来回反弹并试图弄清楚如何评估它。相反,用
替换规则3和4E_0 /: Dt[ E_0[ x_ ], y_ ] := E_0[ Dt[x,y] ]
这对递归有明确的限制。就规则7而言,你得到了这个
E_0[x_ + y__]:= E_0[x] + Plus@@( E_0 /@ {y} )
E_0[x_ y__ ] := E_0[x] Times@@( E_0 /@ {y} )
这是E_0[D[x_1[t_1,q_0], t_1]] E_0[Dt[t_1, y_0]]
+ E_0[D[x_1[t_1,q_0], q_0]] E_0[Dt[q_0,y]]
规则和规则4的结果。要让Dt
不要分发E_0
和D
,请将其作为练习。
修改强>:
我想就您提供的解决方案代码发表一些意见。首先,巧妙地使用布尔来停止递归,它适用于您的Dt
。不过,我建议对您的产品分发进行一些更改。首先,我使用Notation
而不是条件(x__Times
),因为它更容易阅读,我相信(但尚未测试)它可能更快,即处理它的开销更少。其次,将/; Head[x] == Times
替换为Table
,其中List @@ x
,称为Apply
,将@@
替换为Times
,再次更容易阅读和写作。对于List
的定义,请考虑使用Complement
;我不知道它是否更快,但我更喜欢为这类事物设置理论结构。最后,除非您需要变量为reevaluated whenever it is used,否则请勿使用SetDelayed
(n
),请使用:=
(Set
)。通过使用=
,m被评估两次,v被评估3次!
优点和缺点:
这样做的主要原因是易用性和可读性。通过定义自己的对象及其行为,您可以为自己提供很大的灵活性并简化代码。仅此一点就值得。但是,我过去一直很难做到这一点,这样的设置可能是不安全的,我建议进行彻底的测试。其次,通过添加这些额外的层,您可能会减慢代码速度,因此如果要在关键任务应用程序中使用它,请务必小心。此外,每次使用时都必须包含:=
,调色板在某些时候会变得很烦人。虽然可以通过在加载Notation包之前设置Notation
来处理调色板。