Переписные переменные - PullRequest
       4

Переписные переменные

10 голосов
/ 30 марта 2011

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

Ответы [ 6 ]

13 голосов
/ 30 марта 2011

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

в надежде использовать нотации для форсирования ММА обрабатывать индексированные переменные как символ

В сущности, о чем этот вопрос.

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

2 голосов
/ 31 марта 2011

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

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, таких как имена переменных FullyDescriptiveCamelCaseвместо подписанных переменных.В конце концов, это сделает ваш код более переносимым, и со временем это станет второй натурой.

2 голосов
/ 30 марта 2011

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

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

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

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

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

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

Наконец, все, где все это рушится, - это если вы пытаетесь назначить что-то подписанному символу. Я еще не пытался обойти это!

Некоторые тесты - обратите внимание, что для работы кода вам нужно будет преобразовать Subscript s в фактические поля. Сделайте это путем преобразования в 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. >>
1 голос
/ 30 марта 2011

Можно использовать нотацию из пакета с тем же именем.

Не обращайте внимания на приведенный ниже код, вы не разберетесь в структуре 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]]

Out [3] = {{1, 2}}

Out [4] = {{3, 4}}

Out [5] = {{1, 2}, {3, 4}}

Subscript[b, 1]

Out [6] ={{1, 2}}

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

Daniel Lichtblau Wolfram Research

1 голос
/ 30 марта 2011

Символ 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 позволяет обойти поведение по умолчанию. Другие ответы содержат детали.

0 голосов
/ 15 августа 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...