Подстрочные переменные

Есть ли способ заставить 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,..]. Возможно ли это?

Ответ 1

В ответе на предыдущий вопрос SO, Mathematica Notation и синтаксические моды, telefunkenvf14 что он был

надеясь использовать Обозначения, чтобы заставить MMA обрабатывать индексированные переменные как символ

по существу, этот вопрос.

WReach указал, что Notation package может сделать это довольно просто используя Symbolize

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

Где (как в ответе Даниэля) не слишком беспокоиться о структуре 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 s. Тем не менее, Symbolize работает на уровне ящика, поэтому тесты нужно преобразовать обратно в свои 2d-формы. Для этого выберите код (или ячейки) и преобразуйте его в стандартную форму с помощью меню Cell или shortcut Ctrl-Shift-N. Блокнот со всем вышеуказанным кодом должен выглядеть так: screenshot

Ответ 2

Если вы не хотите использовать пакет Notation (см. Daniel и мои ответы), но вы хотите скопировать поведение Symbolize, тогда он становится немного сложным.

Я проделал это после того, как прочитал этот SO ответ, но столкнулся с проблемами и сдался. Я положу код здесь как вики сообщества, чтобы другие люди могли его закончить!

Сначала вы хотите перехватить введенную структуру блока индексов и заставить ее интерпретироваться как "уникальный" символ. Следующий код

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$" ~~ __],
     [email protected][StringDrop[s, 11], "$SPLIT$"],
     s]] /; ! TrueQ[$inSymbolName]
Protect[SymbolName];

Наконец, мы хотим, чтобы этот символ нижнего индекса печатался красиво. Обычно мы будем делать это с помощью определения MakeBoxes, но мы не можем в этом случае, потому что Symbol имеет атрибут Locked:( Вместо этого мы взломаем $PrePrint, чтобы найти эти безумно названные символы и записать их как индексы:

$PrePrint = (# /. s_Symbol :> 
  Block[{$inSymbolName = True}, 
    If[StringMatchQ[SymbolName[s], "$sUbsCript$" ~~ __], 
       [email protected]@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"}}

Он не работает с Set или SetDelayed, если они генерируют 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. >>

Ответ 3

Вот какой код я использовал для этого. Он также должен работать для вас:

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]:= [email protected][f]

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

Но они отображаются как индексы.

С быстрым взглядом я думаю, что это может быть то, к чему стремился Саймон.

Если ваше приложение позволяет это, вы можете захотеть принять соглашения об именах, аналогичные Mathematica, такие как имена переменных FullyDescriptiveCamelCase вместо индексированных переменных. В конце концов, ваш код станет более переносимым, и в конце концов он станет второй натурой.

Ответ 4

Символ b, а не Subscript[b, _].

Когда вы определяете:

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

имеет значение, определяющее значение downvalue для любой функции 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]

Как и ожидалось.

Итак, я думаю, что короткий ответ - нет. По крайней мере, не в прямом смысле.

Edit

В то время как вышеизложенное верно (я считаю), я не знал, что пакет Notation имеет способ обойти поведение по умолчанию. Другие ответы содержат подробности.

Ответ 5

Может использоваться Обозначение из пакета с таким же именем.

Не обращайте внимания на приведенный ниже код, вы не понимаете, что это структура RowBox. Просто используйте шаблон палитры и введите подстрочный индекс [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}}

Вероятно, вы получите более точные ответы, это первый, который я когда-либо делал с пакетом нотации.

Даниэль Лихтблау Wolfram Research

Ответ 6

Я подробно изучил поток на индексированных переменных, вставив различные ответы в блокнот Mathematica (и попробовал его с версиями 7 и 8). Однако я обнаружил, что в некоторых случаях явное представление индексированных переменных как Subscript[a,b] не дает правильного ответа, содержащегося в этих ответах. Однако, когда я использовал явно 2d-нотацию для индекса (a_b), ответ был таким, как ожидалось. Может быть, при вставке индексированных символов в электронную почту они представлены как Subscript[a,b]. (Конечно, я должен добавить, что для каждого отдельного вклада я начал использовать Mathematica fresh - после использования Quit[ ]).