下标变量

发布于 2024-10-28 08:33:40 字数 390 浏览 1 评论 0原文

有没有什么方法可以强制 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 不会影响 Subscript[b, ..]。是否可以?

Is there any way to force Mathematica to treat subscripted variables independently of their unsubscripted counterparts? More specifically. Say, I have the following definitions:

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

Now when I use

Subscript[b, 1] 

Mathematica will substitute it with

Subscript[{{1, 2}, {3, 4}},1]

when I want these to be three independent values, so changing b will not affect Subscript[b, ..]. Is it possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

请别遗忘我 2024-11-04 08:33:40

在对上一个SO问题的回答中,Mathematica 符号和语法模式telefunkenvf14提到他是

希望用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}}

注意:以上所有代码均已复制为输入文本,因此排版 SubscriptBox 已转换为输入表单 Subscript。但是,Symbolize 在框级别工作,因此测试需要转换回二维形式。为此,请选择代码(或单元格)并将其转换为标准形式 使用 Cell 菜单或快捷方式 Ctrl-Shift-N。包含上述所有代码的笔记本应该看起来像
截图

In an answer to a previous SO question, Mathematica Notation and syntax mods, telefunkenvf14 mentioned that he was

hoping to use Notations to force MMA
to treat subscripted variables as a symbol

which is essentially what this question is about.

WReach pointed out that the Notation package can do this quite simply using Symbolize

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

Where (as in Daniel's answer) don't worry too much about the Box structure above as you can use the Notation palette to enter this stuff in more simply.

Check that it all works as wanted:

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

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

and

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}}

Note: all of the above code has been copied as Input Text, so the typeset SubscriptBoxs have been converted to the input form Subscripts. However, the Symbolize works at the box level, so the tests need to be converted back to their 2d forms. To do this, select the code (or cells) and convert it to standard form by using the Cell menu or the shortcut Ctrl-Shift-N. The notebook with all the above code should look like
screenshot

写给空气的情书 2024-11-04 08:33:40

如果您不想使用 Notation 包(请参阅 Daniel 的我的答案),但想要复制 Symbolize 的行为,然后事情就变得有点棘手了。

在阅读此SO答案后,我尝试这样做,但是遇到麻烦就放弃了。我会将代码作为社区 wiki 放在这里,以便其他人可以尝试完成它!

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

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)只有当下标的两个部分都是“简单”时,这个定义才会触发 - 没有空格,括号,运算符等...

接下来,因为这个符号名称太难看了,这里有一个可选的东西,可以在被问到时让它变得更好for (这可能应该改变)

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 :(< br>
相反,我们将侵入 $PrePrint 来查找这些疯狂命名的符号并将它们作为下标写回:

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

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

一些测试 - 请注意,您必须将 Subscript 转换为实际的框才能使代码正常工作。通过转换为标准格式来完成此操作: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. >>

If you don't want to use the Notation package (see Daniel's and my answers) but want to copy the behaviour of Symbolize, then it gets a little tricky.

I had a go at doing this after I reading this SO answer but ran into troubles and gave up. I'll put the code here as community wiki so other people can try to finish it!

First you want to intercept an inputted subscript box structure and make it be interpreted as a "unique" symbol. The following code

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

makes an inputted x_i become a symbol named "$sUbsCript$x$SPLIT$i". Not a guaranteed unique symbol name... but it would a fairly unusual one!
Notes:
1) that this code will not pick up subscripts written in FullForm.
2) this definition only fires off if both parts of the subscript are "simple" - no spaces, brackets, operators, etc...

Next, because this symbol name is so ugly, here's an optional something to make it nicer when it's asked for (this probably should be changed)

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];

Finally, we want this subscript symbol to print out nicely. Normally we'd do this using a MakeBoxes definition -- but we can't in this case because Symbol has the attribute Locked :(
Instead, we'll hack in a $PrePrint to find these crazily named symbols and write them back as subscripts:

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

Finally the place where all of this falls down is if you try to assign something to a subscripted symbol. I haven't tried working around this yet!

Some tests - note that you'll have to convert the Subscripts to actual boxes for the code to work. Do this by converting to 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"}}

It doesn't work with Set or SetDelayed if they generate OwnValues and it doesn't work with 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. >>

It does work with definitions that produce 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. >>
月竹挽风 2024-11-04 08:33:40

这是我用来执行此操作的一些代码。它也应该适合你:

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 的命名约定,例如 FullDescriptiveCamelCase 变量名而不是下标变量。它最终将使您的代码更加可移植,并且最终会成为第二天性。

Here's some code I used to use to do this. It should work for you too:

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]]

With this, definitions like

f[Subscript[a, b] : _] := Sin[Subscript[a, b]]

are internally stored like this:

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

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

But they display as subscripts.

From a quick look I think this may be what Simon was aiming for.

If your application allows it, you may wish to consider adopting Mathematica-like naming conventions such as FullyDescriptiveCamelCase variable names instead of subscripted variables. It will make your code more portable in the end, and it does become second nature eventually.

卷耳 2024-11-04 08:33:40

可以使用同名包中的符号。

不要介意下面的代码,你没有弄清楚 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]]

输出[3]= {{1, 2}}

输出[4]= {{3, 4}}

输出[5]= {{1, 2}, {3, 4}}

Subscript[b, 1]

输出[6]= {{1 , 2}}

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

丹尼尔·利希布劳
沃尔夫勒姆研究公司

Could use Notation from the package of same name.

Don't mind the code below, you don't figure out that RowBox structure. Just use the palette template and type Subscript[b,j_] into the left side, and, say, bb[j_], into the right. So the "actual"variables are now bb[1] etc., and you can assign safely to 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}}

You'll probably get more accurate replies, this is the first I ever mucked with the Notation package.

Daniel Lichtblau
Wolfram Research

美羊羊 2024-11-04 08:33:40

符号是 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 包有办法规避默认行为。其他答案包含详细信息。

The symbol is b, and not Subscript[b, _].

When you define:

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

is like defining a downvalue for any function f. Like doing:

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

So, what you are doing is

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

Which of course assigns a value to the symbol b.

and now

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

As expected.

So, I guess the short answer is no. At least not in a straightforward way.

Edit

While the above is true (I believe), I wasn't aware that the Notation package has a way to circumvent the default behavior. Other answers contain the details.

╰沐子 2024-11-04 08:33:40

我通过将各种回复粘贴到 Mathematica 笔记本中来详细研究了下标变量的线程(并尝试使用版本 7 和 8)。然而,我发现在某些情况下,下标变量的显式表示为 Subscript[a,b] 并不能给出这些答案中包含的正确答案。然而,当我明确使用下标( a_b )的二维表示法时,答案正如预期的那样。难道当将下标符号粘贴到电子邮件中时,它们会被表示为
下标[a,b]。 (当然,我应该补充一点,对于每个单独的贡献,我在使用 Quit[ ] 之后重新启动了 Mathematica )。

I studied the thread on subscripted variables in detail by pasting the various replies into a Mathematica notebook (and tried it with version 7 and 8). However, what I found out that in some cases the explicit representation of subscripted variables as Subscript[a,b] does not give the correct answer as contained in these answers. However, when I used explicitly the 2d notation for subscript ( a_b ) the answer was as expected. Could it be that when pasting subscripted symbols into an email they are represented as
Subscript[a,b]. (Of course, I should add that for each individual contributions I started Mathematica fresh - after using Quit[ ] ).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文