在Mathematica中重新定义下标

4

我希望重新定义Subscript,使得“二项式树坐标”被翻译为“平面数组坐标”:

Unprotect[Subscript];
Subscript[x_, i_, j_] := x[[2 ^ i + j]];
Protect[Subscript];    

(* Binomial Tree *)
y = {.1, {.2, .3}} // Flatten;

Subscript[y, 1, 1]
Subscript[y, 1, 1] = .5;
Subscript[y, 1, 1]

我期望得到的是.3, .5,但实际上我收到了Set::write : Tag Subscript in {.1, .2, .3}_1,1 is Protected并且值没有被赋予。请给出建议。


欢迎来到StackOverflow,Mathematica用户。 - Mr.Wizard
1个回答

6
这里提供概念上最简单的解决方案 - 添加一个新的"Up"规则来处理赋值操作:
Unprotect[Subscript];
Subscript[x_, i_, j_] := x[[2^i + j]]
Set[Subscript[x_, i_, j_], v_] ^:= x[[2^i + j]] = v;
Protect[Subscript];

(*Binomial Tree*)
y = {.1, {.2, .3}} // Flatten

Subscript[y, 1, 1]
Subscript[y, 1, 1] = .5;
Subscript[y, 1, 1]

您需要为处理赋值操作(Set=)单独设置规则,否则在执行Subscript[y, 1, 1] = .5时会尝试将其分配给下标表达式本身。
虽然上述解决方案可以直接使用,但最好不要这样做,因为它会重新定义所有第一个参数类型的Subscript。这种重新定义可能是不安全的,它们可能会与其他可能需要使用Subscript的操作冲突。例如,在某个任意符号x上调用Subscript会导致错误消息和我们可能不想要的评估。
In[137]:= Subscript[x, 1, 2]

During evaluation of In[137]:= Part::partd: Part specification x[[4]] is 
longer than depth  of object.   >>

Out[137]= x[[4]]

一种更安全的替代方法是为想要重新定义 Subscript 的二叉树指定一些特殊头部(如标签),并使用模式来相应地限制这些重新定义的作用域。以下是示例代码:
Unprotect[btree, Subscript];
ClearAll[btree, Subscript];

Subscript[x_btree, i_, j_] := x[[1, 2^i + j]]

Set[Subscript[x_, i_, j_], v_] ^:= (x[[1, 2^i + j]] = v) /; Head[x] === btree;

Protect[btree, Subscript];

您可以将B树结构分配给变量,方法如下:

您可以像这样将B树结构分配给变量:

In[156]:= y = btree[{.1, .2, .3}]

Out[156]= btree[{0.1, 0.2, 0.3}]

那么,

In[157]:= Clear[x];
Subscript[y, 1, 1]
Subscript[y, 1, 1] = .5;
Subscript[y, 1, 1]
Subscript[x, 1, 1]

Out[158]= 0.3

Out[160]= 0.5

Out[161]= Subscript[x, 1, 1]

通过这种方式,我们减少了重新定义可能对其他代码(系统的其余部分)产生的不良影响。
回顾涉及“Set”的定义,需要注意的一点是,我们不能使用简单的模式,例如“Set[Subscript[x_btree,i_Integer,j_Integer],v_:= ...]”,因为变量(此处为“y”)在模式匹配时还没有计算出值,所以它不匹配。使用“Condition”(“/;”)只是一种将我们要分配的变量从“Set”中提取并使其计算的方法。因此,如果是“y”,则“Head[y]”将导致“y”计算 - 这是我们实际上想要评估表达式的头的情况。在像“x_btree”这样的模式中,在模式匹配尝试发生之前,我们不给“x”评估的机会,因此模式不匹配(因为它仍然是一个符号“y”)。
这里使用的附加规则称为“UpValue”。要创建此类规则,需要使用特殊语法(“^:=”运算符 - “UpSetDelayed”是创建“UpValues”的一种方法)。“UpValues”是“软”重载函数(包括系统函数)和创建自定义数据类型的重要机制。要了解有关它们的信息,请参阅此处

尽管我开始了这个答案,但绝大部分文本都是Leonid的。 - Mr.Wizard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接