Mathematica: восстановление произвольного вложенного списка после сглаживания

каков самый простой способ отображения произвольно фанки вложенного списка expr функции unflatten, так что expr==unflatten@@Flatten@expr?

мотивация: Compile может обрабатывать только полные массивы (что-то, что я только что узнал, но не из сообщения об ошибке), поэтому идея заключается в использовании unflatten вместе со скомпилированной версией сплющенного выражения:

fPrivate=Compile[{x,y},Evaluate@Flatten@expr];
f[x_?NumericQ,y_?NumericQ]:=unflatten@@fPrivate[x,y] 

пример решения общей проблемы: Что мне действительно нужно сделать, так это вычислите все производные для данной многомерной функции до некоторого порядка. Для этого случая я прорубаю себе путь так:

expr=Table[D[x^2 y+y^3,{{x,y},k}],{k,0,2}];
unflatten=Module[{f,x,y,a,b,sslot,tt},
  tt=Table[D[f[x,y],{{x,y},k}],{k,0,2}] /. 
    {Derivative[a_,b_][_][__]-> x[a,b], f[__]-> x[0,0]};
  (Evaluate[tt/.MapIndexed[#1->sslot[#2[[1]]]&, 
            Flatten[tt]]/. sslot-> Slot]&) ] 

Out[1]= {x^2 y + y^3, {2 x y, x^2 + 3 y^2}, {{2 y, 2 x}, {2 x, 6 y}}}
Out[2]= {#1, {#2, #3}, {{#4, #5}, {#5, #7}}} &

это работает, но это ни элегантно, ни вообще.

Edit: вот" безопасность работы " версия решения, предоставляемого aaz:

makeUnflatten[expr_List]:=Module[{i=1},
    Function@Evaluate@ReplaceAll[
        If[ListQ[#1],Map[#0,#1],i++]&@expr,
        i_Integer-> Slot[i]]]

это работает Шарм:

In[2]= makeUnflatten[expr]
Out[2]= {#1,{#2,#3},{{#4,#5},{#6,#7}}}&

3 ответов


Вам, очевидно, нужно сохранить некоторую информацию о структуре списка, потому что Flatten[{a,{b,c}}]==Flatten[{{a,b},c}].

если ArrayQ[expr], тогда структура списка определяется Dimensions[expr] и вы можете восстановить его с Partition. Е. Г.

expr = {{a, b, c}, {d, e, f}};
dimensions = Dimensions[expr]

  {2,3}

unflatten = Fold[Partition, #1, Reverse[Drop[dimensions, 1]]]&;
expr == unflatten @ Flatten[expr]

(том Partition man page на самом деле имеет аналогичный пример под названием unflatten.)


если expr не является массивом, вы можете попробовать следующее:

expr = {a, {b, c}};
indexes = Module[{i=0}, If[ListQ[#1], Map[#0, #1], ++i]& @expr]

  {1, {2, 3}}

slots = indexes /. {i_Integer -> Slot[i]}

  {#1, {#2, #3}}

unflatten = Function[Release[slots]]

  {#1, {#2, #3}} &

expr == unflatten @@ Flatten[expr]

Я не уверен, что вы пытаетесь сделать с компиляции. Он используется, когда вы хотите очень быстро оценить процедурные или функциональные выражения на числовых значениях, поэтому я не думаю, что это поможет здесь. Если повторные вычисления D[f,...] препятствуют вашей производительности, вы можете предварительно вычислить и сохранить их с чем - то вроде Table[d[k]=D[f,{{x,y},k}],{k,0,kk}];

затем просто вызовите d[k], чтобы получить K-ю производную.


Я просто хотел обновить отличные решения aaz и Janus. Кажется, что, по крайней мере, в Mathematica 9.0.1.0 на Mac OSX, назначение (см. решение aaz)

{i_Integer -> Slot[i]}

не удается. Если, однако, мы используем

{i_Integer :> Slot[i]}

вместо этого мы добьемся успеха. То же самое, конечно, относится и к ReplaceAll вызов в "безопасности" Янус "дело" версии.

для хорошей меры я включаю свою собственную функцию.

unflatten[ex_List, exOriginal_List] := 
  Module[
   {indexes, slots, unflat},
   indexes = 
     Module[
       {i = 0}, 
       If[ListQ[#1], Map[#0, #1], ++i] &@exOriginal
       ];
   slots = indexes /. {i_Integer :> Slot[i]};
   unflat = Function[Release[slots]];
   unflat @@ ex
   ];

(* example *)
expr = {a, {b, c}};
expr // Flatten // unflatten[#, expr] &

это может показаться немного как чит использовать оригинальное выражение в функции, но, как указывает aaz, нам нужно некоторые информация из исходного выражения. Пока вам это не нужно все, чтобы один функция, которая может unflatten, все необходимые.

мое приложение похоже на приложение Януса: я распараллеливаю вызовы Simplify для тензора. Используя ParallelTable Я могу значительно улучшить производительность, но я разрушаю тензорную структуру в процессе. Это дает мне быстрый способ восстановить мой оригинальный тензор, упрощенный.