Создание настроенных InputForm и ShortInputForm - PullRequest
4 голосов
/ 03 июня 2011

Я часто хочу видеть внутреннее представление графических объектов Mathematica не в FullForm, а в гораздо более удобочитаемом InputForm, имеющем возможность выбирать части кода двойным щелчком мыши на нем и легко скопировать этот код на новый вход Cell. Но значение по умолчанию InputForm не позволяет этого, поскольку InputForm отображается по умолчанию как String, а не как Mathematica код. Есть ли способ отобразить InputForm как Mathematica код?

Я также часто хочу видеть сокращенную версию такого InputForm, где все длинные списки координат отображаются в качестве первой координаты, за которой следует число пропущенных значений координат, заключенных в Skeleton, все пустые Lists удалены и все номера также сокращены для отображения не более 6 цифр. Было бы даже лучше использовать 6 цифр только для координат, но для цветовых директив, таких как Hue, отображаются только 2 значащие цифры. Например,

Plot[{Sin[x], .5 Sin[2 x]}, {x, 0, 2 \[Pi]}, 
  Filling -> {1 -> {2}}] // ShortInputForm

должно дать:

Graphics[GraphicsComplex[{{1.28228`*^-7, 1.28228*^-7}, <<1133>>}, 
    {{{EdgeForm[], Directive[{Opacity[0.2], Hue[0.67, 0.6, 0.6]}], 
          GraphicsGroup[{Polygon[{{1133, <<578>>}}]}]}, 
        {EdgeForm[], Directive[{Opacity[0.2], Hue[0.67, 0.6, 0.6]}],              
     GraphicsGroup[{Polygon[{{432, <<556>>}}]}]}}, {{Hue[0.67, 0.6, 
      0.6], Line[{1, <<431>>}]}, {Hue[0.91, 0.6, 0.6], 
          Line[{432, <<701>>}]}}}], {AspectRatio -> GoldenRatio^(-1), 
  Axes -> True, AxesOrigin -> {0, 0}, 
    Method -> {"AxesInFront" -> True}, 
  PlotRange -> {{0, 2*Pi}, {-1., 1}}, 
    PlotRangeClipping -> True, 
  PlotRangePadding -> {Scaled[0.02], Scaled[0.02]}}]

(обратите внимание, что -0.9999998592131705 преобразуется в -1., 1.2822827157509358*^-7 преобразуется в 1.28228*^-7 и Hue[0.9060679774997897, 0.6, 0.6] преобразуется в Hue[0.91, 0.6, 0.6]).

Таким образом, я хочу получить вывод InputForm в виде кода Mathematica , а также функцию ShortInputForm, которая даст сокращенную версию этого кода. Кто-нибудь может мне помочь?


Что касается первой части вопроса, я нашел один способ достичь того, чего я хочу:

Plot[{Sin[x], .5 Sin[2 x]}, {x, 0, 2 \[Pi]}, Filling -> {1 -> {2}}] //
   InputForm // StandardForm

Ответы [ 2 ]

7 голосов
/ 03 июня 2011

UPDATE

Самую последнюю версию функции shortInputForm можно найти здесь .


Оригинальный пост

Вот еще одно, еще лучшее решение (совместимо с Mathematica 5):

myInputForm[expr_] := 
 Block[{oldContexts, output, interpretation, skeleton},
  output = ToString[expr, InputForm];
  oldContexts = {$Context, $ContextPath};
  $Context = "myTemp`"; $ContextPath = {$Context};
  output = DisplayForm@ToBoxes[ToExpression[output] /.
      {myTemp`interpretation -> If[$VersionNumber >= 6,
         System`Interpretation, System`First@{#} &],
       myTemp`Row -> System`Row,
       myTemp`skeleton -> System`Skeleton,
       myTemp`sequence :> (System`Sequence @@ # &)}, StandardForm];
  {$Context, $ContextPath} = oldContexts; output]
shortInputForm[expr_] := myInputForm[expr /. {{} -> Sequence[],
    lst : {x_ /; VectorQ[x, NumberQ], y__} /;
      (MatrixQ[lst, NumberQ] && Length[lst] > 3) :>
     {x /. v : {a_, b__} /; Length[v] > 3 :>
        {a, interpretation[skeleton[Length[{b}]], sequence@{b}]},
      interpretation[skeleton[Length[{y}]], sequence@{y}]},
    lst : {x_, y__} /; VectorQ[lst, NumberQ] && Length[lst] > 3 :>
     {x, interpretation[skeleton[Length[{y}]], sequence@{y}]}}]

Как это работает

Это решение основано на простой идее: нам нужно заблокировать преобразование таких вещей, как Graphics, Point и других в набранные выражения , чтобы они отображались во внутренней форме (как выражения, подходящие для ввода). К счастью, если мы сделаем это, результирующий вывод StandardForm окажется просто отформатированным (двумерным) InputForm исходного выражения. Это как раз то, что нужно!

Но как это сделать? Прежде всего, это преобразование выполняется с помощью FormatValues, определенного для Symbol s, например Graphics, Point и т. Д. Полный список таких Symbol s можно получить, оценивая следующее:

list = Symbol /@ 
  Select[DeleteCases[Names["*"], "I" | "Infinity"], 
   ToExpression[#, InputForm, 
     Function[symbol, Length[FormatValues@symbol] > 0, HoldAll]] &]

Моей первой идеей было просто Block все эти Symbol с (и это работает!):

myInputForm[expr_] := 
 With[{list = list}, Block[list, RawBoxes@MakeBoxes@expr]]

Но этот метод приводит к оценке всех этих Symbol с, а также оценивает все FormatValues для всех Symbol с в $ContextPath. Я думаю, что этого следует избегать.

Другой способ заблокировать эти FormatValues - просто удалить контекст "System`" из $ContextPath. Но это работает, только если эти Symbol еще не разрешены в контексте "System`". Поэтому нам нужно сначала преобразовать наше выражение в String, затем удалить контекст "System`" из $ContextPath и, наконец, преобразовать строку обратно в исходное выражение. Тогда все новые Symbol будут связаны с текущими $ContextGraphics, Point и т. Д. - тоже, поскольку их нет в $ContextPath). Для предотвращения конфликтов затенения контекста и засорения контекста "Global`" я переключаю $Context на "myTemp`", который может быть легко очищен при необходимости.

Вот как myInputForm работает.

Теперь о shortInputForm. Идея состоит не только в том, чтобы отобразить сокращенную версию myInputForm, но и в том, чтобы сохранить возможность выбирать и копировать части сокращенного кода в новую входную ячейку и использовать этот код, поскольку он будет полным кодом без сокращений. В версии 6 и выше можно достичь последнего с Interpretation. Для совместимости с до-6 версиями Mathematica я добавил фрагмент кода, который удаляет эту способность, если $VersionNumber меньше 6.

Единственная проблема, с которой я столкнулся при работе с Interpretation, заключается в том, что у него нет атрибута SequenceHold, поэтому мы не можем просто указать Sequence в качестве второго аргумента для Interpretation. Но этой проблемы легко избежать, добавив последовательность в List и затем Apply ing Sequence к ней:

System`Sequence @@ # &

Обратите внимание, что мне нужно указать точный контекст для всех встроенных Symbol s, которые я использую, потому что в момент их вызова контекст "System`" отсутствует в $ContextPath.

На этом заканчиваются нестандартные решения, принятые мной при разработке этих функций. Предложения и комментарии приветствуются!

enter image description here

0 голосов
/ 03 июня 2011

На данный момент я пришел к следующему решению:

round[x_, n_] := (10^-n*Round[10^n*MantissaExponent[x]]) /.
   {m_, e_} :> N[m*10^e];
ShortInputForm[expr_] := ((expr /.
       {{} -> Sequence[],
        lst : {x_ /; VectorQ[x, NumberQ], y__} /;
          (MatrixQ[lst, NumberQ] && Length[lst] > 2) :>
         {x, Skeleton[Length[{y}]]},
        lst : {x_, y__} /; VectorQ[lst, NumberQ] && Length[lst] > 2 :>
         {x, Skeleton[Length[{y}]]}} /.
      {exp : Except[List | Point][x__] /; 
         VectorQ[{x}, MachineNumberQ] :>
        (round[#, 2] & /@ exp), 
       x_Real /; MachineNumberQ[x] :> round[x, 6]})
    // InputForm // StandardForm)

Сейчас:

screenshot

...