10

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?

asked Mar 30, 2011 at 2:27

6 Answers 6

13

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

answered Mar 30, 2011 at 4:01
Sign up to request clarification or add additional context in comments.

Comments

2

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$SPLIT3,ドル $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. >>

Comments

2

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[ProxySymbol99ドル_]] :> Sin[ProxySymbol99ドル]}

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.

answered Mar 31, 2011 at 0:31

1 Comment

Hi Andrew - Just saw this. It works nicely and is much more sane than my approach. +1
1

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

answered Mar 30, 2011 at 3:06

7 Comments

@Daniel As it should be obvious from my answer, I never did. :)
Hi Daniel: The Notation package has a command called Symbolize that is designed to do what Max wanted. The full Notation command is not needed.
Potential issue with custom notation is that parsing mechanism for .nb and .m files is different. It definitely causes a problem for InfixNotation (groups.google.com/forum/#!msg/comp.soft-sys.math.mathematica/…), not sure about Symbolize
@Daniel I'm puzzled by your answer. If you input Subscript[b,1] you will indeed get {{1,2}} as output. But if you enter the same thing formatted as a subscript, ie. b+Control[-], you will obtain a nicely rendered result of Subscript[{{1,2},{3,4}},1] in return.
@David: Try using the command Notation[ParsedBoxWrapper[\(b\_j_\)] \[DoubleLongLeftRightArrow] ParsedBoxWrapper[\(bb[j_]\)]].
|
1

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.

answered Mar 30, 2011 at 2:59

5 Comments

Of course, I wonder what internal magic the Notation package actually uses to achieve what it does? For example what does Symbolize actually do?
@Simon ha! I posted and then deleted a similar comment on your answer. That kind of things makes me shudder :)
It wouldn't be so bad - except that Symbol is Locked - which prevents you from giving it extra MakeBoxes definitions. See the Community Wiki "answer" I posted below.
@Simon I think your answer is a very nice one, but I doubt about the robustness of the whole thing. When you want a calc done Mma is great, but the environment per se looks fragile, and the debug process (hard on its own) is usually more difficult each time you add a level of abstraction/redefinition.
The answer has serious problems - I only put it up so that other people can procrastinate by fixing it for me!
0

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[ ] ).

Simon
14.7k4 gold badges43 silver badges106 bronze badges
answered Aug 15, 2011 at 10:07

1 Comment

Hi Robert, welcome to Stack Overflow. Posting a new answer is not really the place for such a comment, but since you don't have enough reputation to comment, I guess there's not much else you could do to raise this valid point. Mathematica automatically converts the subscript boxes to full form when copying as input text, I think that everyone automatically converted the full form back to boxes when testing and no-one thought of mentioning this fact. I'll update my answer to reflect this concern.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.