2
$\begingroup$

So here is what I have thought:

Use ToString and StringLength in order to get the number of characters in the variable name.

If it is bigger than one, change variable name by putting everything but the first character as subscript.

Symbolize subscipt to avoid issues.

Example:

Going from $ux1 - i1$ to $u_{x1}-i_1$

$x$ is a variable but I do not want any interference with u_{x...}!

About the symbolization of subscripts I looked up and found this:

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

For the rest I have not been able to do it mainly because I do not manage to make the function go through an expression and change all the elements of it. I also tried to use Replace but failed.

$\endgroup$

2 Answers 2

3
$\begingroup$

It is not entirely clear to me what you are actually trying to accomplish. Using subscripts in Mathematica often needlessly complicates things. Since you are looking for an automated replacement I think you prefer not to enter subscripts manually which I think is wise. I believe it also means you are looking for a formatting function.

A basic approach is to work with strings. We may write:

ux1 - i1 /. s_Symbol /; Context[s] === $Context :>
  (Subscript[#, "" <> ##2] & @@ Characters @ SymbolName[s])

enter image description here

If string output is not acceptable we may wish to use HoldForm to keep elements from evaluating. This is important if for example x1 or i are Symbols with a value:

x1 = i = "Fail!";

ux1 - i1 /. s_Symbol /; Context[s] === $Context :>
 (HoldForm @@@ MakeExpression /@ Subscript[#, "" <> ##2] & @@ Characters @ SymbolName[s])

enter image description here

Additionally you may consider the case where these replacements must be done inside a held expression, where e.g. i1 has a global value. You will need Unevaluated and RuleCondition:

i1 = x1 = i = "Fail!";

Hold[ux1 - i1] /. s_Symbol /; Context[s] === $Context :> 
  RuleCondition[HoldForm @@@ MakeExpression /@ Subscript[#, "" <> ##2] & @@ 
     Characters @ SymbolName @ Unevaluated @ s]

enter image description here

If I am correct that you want this for formatting purposes you might make use of a formatting wrapper, which will allow you to extract the original unmodified expression, or define rules for function to work with that expression.

MakeBoxes[subscriptForm[expr_], fmt_] :=
 MakeBoxes[#, fmt] &[
  expr /. s_Symbol /; Context[s] === $Context :>
    RuleCondition[HoldForm @@@ MakeExpression /@ Subscript[#, "" <> ##2] & @@
      Characters @ SymbolName @ Unevaluated @ s]
 ]

Now:

expr = subscriptForm[Hold[ux1 - i1]]

enter image description here

First @ expr
Hold[ux1 - i1]
$\endgroup$
2
  • $\begingroup$ Waow I am going to take time to digest all of this, I will probably learn new things before being able to understand all this code. Thank you very much for this answer. $\endgroup$ Commented Aug 22, 2013 at 18:04
  • $\begingroup$ @Ouistiti You're welcome. Let me know if you need help understanding any of it; you're right, there's a lot there. I believe the only undocumented thing I used is RuleCondition which you can read about here. $\endgroup$
    – Mr.Wizard
    Commented Aug 23, 2013 at 2:26
2
$\begingroup$

You mean something like this?

f[x_] := If[Length[#] > 1 && MemberQ[Names[$Context <> "*"], ToString@x], 
    Subscript[ToExpression@First@#, ToExpression@StringJoin@Rest@#], x]&
    @ StringSplit[ToString[x], ""];

It first defines a pure function, where # is the unnamed argument. Then it applies it to the list of characters of x converted to a string. A simpler example of this method:

# Log[2, #] & @ 3

This is the same as 3 Log[2, 3].

Use the expression from above like this on general expressions:

Map[f, ux1 - i1, -1]

-Subscript[i, 1] + Subscript[u, x1]

It should work for simple expressions, but I can't guarantee it for more complex stuff. I always avoid ToExpression wherever I can (which is pretty much always). There are lots of opportunities for unforeseen side effects...

$\endgroup$
2
  • $\begingroup$ Yes but how to use it on whole expression such as my example: ux1-i1. If you have time I would also be very interested in understanding your function, especially the end of it, what is the part after the If[] doing ? $\endgroup$ Commented Aug 21, 2013 at 14:11
  • $\begingroup$ @Ouistiti See my edit $\endgroup$
    – Volker
    Commented Aug 21, 2013 at 14:38

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.