订阅变量

时间:2011-03-30 02:27:23

标签: wolfram-mathematica

有没有办法强迫Mathematica独立于未订阅的对应方处理下标变量?进一步来说。说,我有以下定义:

Subscript[b, 1] = {{1, 2}}
Subscript[b, 2] = {{3, 4}}
b = Join[Subscript[b, 1], Subscript[b, 2]]

现在我使用

Subscript[b, 1] 

Mathematica将用

代替它
Subscript[{{1, 2}, {3, 4}},1]

当我希望这些是三个独立的值时,更改b不会影响下标[b,..]。有可能吗?

6 个答案:

答案 0 :(得分:13)

在对前一个SO问题的回答中,Mathematica Notation and syntax modstelefunkenvf14提到他是

  

希望使用Notations强制MMA   将下标变量视为符号

这就是这个问题的基本内容。

WReach指出Notation package只需使用Symbolize即可完成此操作

Needs["Notation`"];
Symbolize[ParsedBoxWrapper[SubscriptBox["_", "_"]]]

在(如Daniel的回答中)不要过于担心上面的Box结构,因为您可以使用Notation调色板更简单地输入这些内容。

检查一切是否正常工作:

In[3]:= Subscript[a, b]//Head
        a = 1
        Subscript[a, b]

Out[3]= Symbol
Out[4]= 1
Out[5]= Subscript[a, b]

In[6]:= Subscript[b, 1] = {{1, 2}}
        Subscript[b, 2] = {{3, 4}}
        b = Join[Subscript[b, 1], Subscript[b, 2]]
Out[6]= {{1, 2}}
Out[7]= {{3, 4}}
Out[8]= {{1, 2}, {3, 4}}

注意:以上所有代码均为copied as Input Text,因此排版SubscriptBox已转换为输入形式Subscript。但是,Symbolize在框级别工作,因此需要将测试转换回其二维形式。为此,请使用Cell菜单或convert it to standard form Ctrl-Shift-N选择代码(或单元格)和shortcut。具有上述所有代码的笔记本应该是这样的 screenshot

答案 1 :(得分:2)

如果您不想使用Notation包(请参阅Daniel'smy答案),但想要复制Symbolize的行为,那么它会获得有点棘手。

在我阅读SO answer之后,我开始这么做了,但遇到了麻烦而放弃了。我将这里的代码作为社区维基,以便其他人可以尝试完成它!

首先,您要拦截输入的下标框结构,并将其解释为“唯一”符号。以下代码

MakeExpression[SubscriptBox[x_String, i_String], form_] := 
 With[{name = StringJoin[{"$sUbsCript$", x, "$SPLIT$", i}]}, 
  Hold[Symbol[name]]]

使输入的x_i成为名为"$sUbsCript$x$SPLIT$i"的符号。不是一个保证唯一的符号名称......但它会是一个相当不寻常的名称! 注:
1)此代码不会获取FullForm中写的下标 2)这个定义只有在下标的两个部分都是“简单”时才会触发 - 没有空格,括号,运算符等......

接下来,因为这个符号名称是如此丑陋,所以这是一个可选的东西,以便在它被要求时更好(这可能应该改变)

Protect[$inSymbolName];
Unprotect[SymbolName];
SymbolName[symb_Symbol] := 
 Block[{$inSymbolName = True, result, s},
   result = If[StringMatchQ[s = SymbolName[symb], "$sUbsCript$" ~~ __],
     StringJoin@StringSplit[StringDrop[s, 11], "$SPLIT$"],
     s]] /; ! TrueQ[$inSymbolName]
Protect[SymbolName];

最后,我们希望这个下标符号可以很好地打印出来。通常我们会使用MakeBoxes定义执行此操作 - 但在这种情况下我们不能因为Symbol具有属性Locked :(
相反,我们将在$PrePrint中找到这些疯狂命名的符号并将其作为下标写回来:

$PrePrint = (# /. s_Symbol :> 
  Block[{$inSymbolName = True}, 
    If[StringMatchQ[SymbolName[s], "$sUbsCript$" ~~ __], 
       Subscript@@StringSplit[StringDrop[SymbolName[s], 11], "$SPLIT$"], s]]
   )&;

最后,如果您尝试将某些内容分配给下标符号,那么所有这些都会失败的地方。我还没有尝试解决这个问题!

某些测试 - 请注意,您必须将Subscript转换为实际框才能使代码生效。通过转换为StandardForm来执行此操作:Ctrl-Shift-N。

symbs = {x, yy, Subscript[a, 3], Subscript[long, name]};

In[10]:= Head/@symbs
Out[10]= {Symbol, Symbol, Symbol, Symbol}

In[11]:= SymbolName/@symbs
Out[11]= {x, yy, a3, longname}

In[12]:= Block[{$inSymbolName=True},SymbolName/@symbs]
Out[12]= {x, yy, $sUbsCript$a$SPLIT$3, $sUbsCript$long$SPLIT$name}

In[13]:= f[x_Symbol] := Characters[SymbolName[x]]
In[14]:= {f["acb"], f[abc], f[Subscript[xx, 2]]}
Out[14]= {f["acb"], {"a", "b", "c"}, {"x", "x", "2"}}

如果SetSetDelayed生成OwnValues并且不能与Information

一起使用,则无效
In[15]:= Subscript[x, y] = 5
         ??Subscript[x, y]
During evaluation of In[4]:= Set::write: Tag Symbol in Symbol[$sUbsCript$x$SPLIT$y] is Protected. >>
Out[15]= 5
During evaluation of In[4]:= Information::nomatch: No symbol matching Symbol["$sUbsCript$x$SPLIT$y"] found. >>

它适用于生成DownValues

的定义
In[17]:= Subscript[x, z][z_]:=z^2
In[18]:= Subscript[x, z][2]
Out[18]= 4

In[19]:= ?Subscript[x, z]
Information::nomatch: No symbol matching Symbol["$sUbsCript$x$SPLIT$z"] found. >>

答案 2 :(得分:2)

以下是我过去用来执行此操作的一些代码。它也适合你:

SubscriptToProxySymbol[_] = Null;
MakeExpression[SubscriptBox[a_, b_], StandardForm] := 
 Module[{proxy, boxes = SubscriptBox[a, b]}, 
  proxy = SubscriptToProxySymbol[boxes];
  If[proxy === Null, proxy = ToString[Unique[ProxySymbol]];
   SubscriptToProxySymbol[boxes] = proxy;
   With[{n = Symbol[proxy]}, MakeBoxes[n, StandardForm] := boxes];];
  MakeExpression[RowBox[{proxy}], StandardForm]]

有了这个,像

这样的定义
f[Subscript[a, b] : _] := Sin[Subscript[a, b]]

内部存储如下:

In[11]:= InputForm@DownValues[f]

Out[11]//InputForm=
{HoldPattern[f[ProxySymbol$99_]] :> Sin[ProxySymbol$99]}

但它们显示为下标。

从快速看,我认为这可能是西蒙的目标。

如果您的应用程序允许,您可能希望考虑采用类似Mathematica的命名约定,例如FullyDescriptiveCamelCase变量名称而不是下标变量。它最终将使您的代码更具可移植性,并最终成为第二种性质。

答案 3 :(得分:1)

符号为b,而非Subscript[b, _]

定义时:

Subscript[b, 1] = {{1, 2}}

就像定义任何函数f的下限值。喜欢这样做:

f[b, 2] = {{1, 2}} 

所以,你正在做的是

f[b, 1] = {{1, 2}} 
f[b, 2] = {{3, 4}} 
b = Join[f[b, 1], f[b, 2]]

当然,这会给符号b赋值。

现在

f[b, 1]
->f[{{1, 2}, {3, 4}}, 1]

正如所料。

所以,我想简短的回答是否定的。至少不是一种直截了当的方式。

修改

虽然上述情况属实(我相信),但我并不知道Notation包有办法绕过默认行为。其他答案包含详细信息。

答案 4 :(得分:1)

可以使用同名包中的Notation。

不要介意下面的代码,你不要弄清楚RowBox的结构。只需使用调色板模板并在左侧键入Subscript [b,j_],然后在右侧键入bb [j_]。所以“实际”变量现在是bb [1]等,你可以安全地分配给b。

Needs["Notation`"]

Notation[ParsedBoxWrapper[
  RowBox[{"Subscript", "[", 
   RowBox[{"b", ",", "j_"}], "]"}]] \[DoubleLongRightArrow] 
   ParsedBoxWrapper[
  RowBox[{"bb", "[", "j_", "]"}]]]

Subscript[b, 1] = {{1, 2}}
Subscript[b, 2] = {{3, 4}}
b = Join[Subscript[b, 1], Subscript[b, 2]]

Out [3] = {{1,2}}

Out [4] = {{3,4}}

Out [5] = {{1,2},{3,4}}

Subscript[b, 1]

Out [6] = {{1,2}}

你可能会得到更准确的回复,这是我第一次使用Notation软件包。

Daniel Lichtblau Wolfram Research

答案 5 :(得分:0)

我通过将各种回复粘贴到Mathematica笔记本中来详细研究下标变量的线程(并使用版本7和8进行了尝试)。但是,我发现在某些情况下,作为Subscript[a,b]的下标变量的显式表示并未给出这些答案中包含的正确答案。但是,当我明确使用下标(a_b)的2d符号时,答案是预期的。可能是因为将下标符号粘贴到电子邮件中时,它们被表示为 Subscript[a,b]。 (当然,我应该补充说,对于每个人的贡献,我开始使用Mathematica新鲜 - 使用Quit[ ]后)。