4

I am trying to creat a list of indexed variables (symbols) using the Notation package and Symbolize command.

As an example, suppose that I want to a creat a list of variables like ${x_1,...,x_{20}}$ but I want all of them to be symbols. How can I creat a list of symbolized indexed variables?

Hosein Rahnama
  • 1,727
  • 1
  • 15
  • 29
  • Perhaps you could clarify which part you find unexpected, so we can provide better answers. Perhaps we could start from here: Information (i.e. ??) is HoldAll so it won't evaluate Var[[1]] to its contents. You could try Information[Evaluate[Var[[1]]] instead. More in general, however, when you assign values to subscripted variables, the value is actually associated with the Subscript function, and not with the variable. – MarcoB Jan 23 '17 at 16:30
  • See perhaps (1005), (373). – MarcoB Jan 23 '17 at 16:33
  • @MarcoB: Ah! So my first question is answered!? :) What about the second one. :) – Hosein Rahnama Jan 23 '17 at 16:33
  • @MarcoB: Please note that if one uses the Symbolize command then there will be no problem for assigning. :) – Hosein Rahnama Jan 23 '17 at 16:35
  • I am not familiar enough with the Notation package to comment on those points. In general, though, I would suggest that you look into Indexed, or simply use e.g. x[1, 3] instead of $x_{1,3}$. See e.g. (114632) and links, and search this site for "alternatives to Subscript". – MarcoB Jan 23 '17 at 16:39
  • @MarcoB: Thanks for the guides. I edited the first question. would you please take a look at it. – Hosein Rahnama Jan 23 '17 at 17:16

3 Answers3

4

I used to do this with Notation`Symbolize, but it had some shortcomings like, if you save expressions on disk and later load into another notebook, then symbolization is not preserved automatically, and you end up with lots of names with \[UnderBracket] in them. Even more important, you cannot create a list of symbolized indexed variables by just using Table[Subscript[x, j], {j, 10}]. I found a different approach, and so far it serves my needs pretty well.

Mathematica allows many Unicode characters in symbol names, including subscript digits ₀₁₂₃₄₅₆₇₈₉. So, I create indexed variables using these digits in symbol names, but because they are not easy to enter and they look in notebooks slightly different than regular subscripts, I format them as regular subscripted expressions using MakeBoxes, and use Subscript to create them on demand from regular subscripts. When I save expressions containing symbols with subscripts on disk, in the worst case they will be loaded as regular symbols with Unicode subscript digits in their names (e.g. x₁₂) that is still pretty readable.

The following code will automatically symbolize all subscripted symbols in Global`‍ context:

With[{regular = CharacterRange["0", "9"], 
   subscripts = CharacterRange[8320, 8329]}, (* ₀₁₂₃₄₅₆₇₈₉ *)

  With[{pat = Alternatives[subscripts], 
    toSub = Thread[regular -> subscripts], 
    fromSub = Thread[subscripts -> regular]},

   $NewSymbol = Function[{name, ctx},
     If[ctx === "Global`" && StringEndsQ[name, pat],
      With[{len = StringPosition[name, pat][[1, 1]] - 1},
       With[{s = StringTake[name, len],
             index = StringReplace[StringDrop[name, len], fromSub]},
        With[{ex = MakeExpression["Global`" <> name, StandardForm]},
         ReleaseHold[Hold[
           MakeBoxes[ex, StandardForm] := 
             InterpretationBox[SubscriptBox[s, index], ex, 
               Editable -> True, AutoDelete -> True]]
                 /. HoldComplete[h_] :> h]]]]]];

   SetAttributes[Subscript, HoldFirst];
   Subscript[s_Symbol /; Context[Unevaluated[s]] === "Global`", j_Integer /; j >= 0] :=
     ToExpression["Global`" <> SymbolName[Unevaluated[s]]
       <> StringReplace[ToString[j], toSub]]]];

Please feel free to criticize or propose improvements.

Vladimir Reshetnikov
  • 7,213
  • 27
  • 75
  • 1
    (+1) Thanks Vladimir. :) – Hosein Rahnama May 22 '20 at 23:17
  • 1
    Nice alternative. I've been using NotationSymbolize, and a way to programmatically generate a list of pretty, symbolized, subscripted variables (where Table[Subscript[x, j], {j, 10}] doesn't work) is: X = ToExpression[SubscriptBox["x", ToString[#]]]&/@Range[10] (see Mr.Wizard's answer to my question here).

    One limitation of your approach: Functions with subscripted arguments don't seem to work.

    Also, how do you "undo" the approach above? (e.g. just Clear["Global*"]`?)

    – Sterling Jun 22 '20 at 17:44
  • @Sterling These are valid points. But usually they do not bother me much in my scenarios. To use a subscripted variable as an ad hoc function parameter I either pre-evaluate the subscripted variable and paste it where needed, or use input aliases for subscript digits: Scan[Notation`AddInputAlias, {"0" -> ParsedBoxWrapper["\:2080"], …}]. In most cases I generate those definitions by a program and create subscripted symbols and their formatting rules explicitly. – Vladimir Reshetnikov Jun 22 '20 at 20:20
  • @VladimirReshetnikov, thank you. What do you mean by pre-evaluate the subscripted variables? Before when I tried with your approach, I think using it as a function argument still produced an error even if I had evaluated the subscripted variables manually. I wasn't familiar with input aliases before, and that seems like a pretty reasonable approach. If I end up needing to save variables to disk and reload them or run into other limitations with the Symbolize package, I'll keep this approach in mind. Hopefully this is some useful discussion for others to decide as well. – Sterling Jun 24 '20 at 09:13
1

Perhaps you don't need to - you can use a pattern (e.g Subscript[x,_]) inside a Symbolize box. This will generate the symbols as required.

mikado
  • 16,741
  • 2
  • 20
  • 54
0

Here is as simple way to create a list of symbolized variables $x_1,x_2,\dots,x_{20}$ as follows

Clear["Global`*"]

Needs["Notation`"]

Do[Symbolize[ParsedBoxWrapper[SubscriptBox["x", ToString[i]]]], {i, 1,
   20}]

x = 1
(*1*)

Subscript[x, 1]
(*x_1*)
Hosein Rahnama
  • 1,727
  • 1
  • 15
  • 29
  • 1
    It's worth keeping in mind that this is just front-end magic. If you used GeneralUtilities`PrintDefinitionsLocal on Symbolize you find it just constructs a bunch of symbols looking like x\[UnderBracket]Subscript\[UnderBracket]i and then coerces the box representations with MakeExpression and MakeBoxes. It'll work for most simple usages, but it absolutely requires the front end and the Symbolize call to work. Another point of interest: if you want to get the information on such symbols all one needs to use is ?? "x\[UnderBracket]Subscript\[UnderBracket]*". – b3m2a1 Mar 08 '17 at 20:20
  • @MB1965: Thanks for the attention. What we see is clearly the front end notation so I find it useful to make use of these things for better readability of the code. :) Also getting information is not that much painful as you say. The keyboard entry is simply "? x crtl+_ 1". :) – Hosein Rahnama Mar 08 '17 at 20:31
  • yes, but if you want the definitions for all of the subscripted symbols you require that (I believe). Information takes a placeholder form with "*" to spit out all matching forms but this has to be a string. Similarly with Clear or Remove. – b3m2a1 Mar 08 '17 at 20:47