2011-02-15 22 views
8

¿Cuál es la forma más simple de asignar una lista anidada arbitrariamente funky expr a una función unflatten de modo que [email protected]@[email protected]?Mathematica: reconstruir una lista anidada arbitraria después de Flatten

motivación: Compile sólo puede manejar matrices completas (algo que acaba de aprender - pero no del mensaje de error), por lo que la idea es utilizar unflatten junto con una versión compilada de la expresión aplanado:

fPrivate=Compile[{x,y},[email protected]@expr]; 
f[x_?NumericQ,y_?NumericQ]:[email protected]@fPrivate[x,y] 

Ejemplo de una solución a un problema menos general: Lo que en realidad lo que necesito hacer es calcular todas las derivadas de una función multivariable renunciado a algún orden. Para este caso, me hackeo mi camino a lo largo de esta manera:

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}}} & 

Esto funciona, pero no es ni elegante ni general.

Editar: Aquí está la versión "seguridad en el empleo" de la solución proporcionada por aaz:

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

Funciona a las mil maravillas:

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

No lo probé, pero la modificación de 'rearrangeAs' de Leonid Shifrin podría funcionar http://stackoverflow.com/questions/4811082/applying-transformation-of-gatherby-to-a-different-list/4811794# 4811794 –

+0

Gracias, Yaroslav: Eso ciertamente parece relacionado, pero es un poco difícil de asimilar :). Terminé haciendo algo yo mismo que publicaré si nadie muerde ... La misma historia siempre: 1) resuelve el problema para tu caso específico, 2) te das cuenta de que una solución más general podría ser divertida, 3) para evitar perder el tiempo en la tangente , publíquelo en SO para que otros realicen su trabajo tangencial, 4) hágalo usted mismo también. Suspiro – Janus

+0

Esta pregunta parece relacionada http://stackoverflow.com/questions/3807976/inverse-of-flatten-in-mathematica – dbjohn

Respuesta

6

Obviamente necesita guardar algo de información sobre la estructura de la lista, porque Flatten[{a,{b,c}}]==Flatten[{{a,b},c}].

Si ArrayQ[expr], la estructura de lista está dada por Dimensions[expr] y puede reconstruirla con Partition. P.ej.

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

    {2,3} 

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

(. La página Partition hombre tiene en realidad un ejemplo similar llamado unflatten)


Si expr no es una matriz, puede intentar esto:

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] 
+0

Sí, he usado el primero un par de veces, pero la segunda versión es lo que necesito, ¡y muy bien hecho! El uso de Slot [0] para la recursión anónima nunca se me ocurrió :) Gracias. – Janus

+0

Acabo de enterarme de 'Slot [0]' mientras escribo esto; está debajo de _Neat Examples_, obviamente :) – aaz

+0

¿Está 'Release' document? ¿Alguien puede guiarme a alguna información? Estoy usando Mma 7 (M. Trott, en 'Programación' dice que no está documentado, pero no da más información, por lo que puedo ver). – tomd

1

No estoy seguro de lo que está tratando para hacer con Compile. Se utiliza cuando desea evaluar expresiones de procedimiento o funcionales muy rápidamente en valores numéricos, por lo que no creo que vaya a ayudar aquí. Si los cálculos repetidos de D [f, ...] están impidiendo su rendimiento, puede precalcularlos y almacenarlos con algo como Table[d[k]=D[f,{{x,y},k}],{k,0,kk}];

Luego simplemente llame a d [k] para obtener la derivada kth.

+1

Gracias. Estoy completamente de acuerdo en que no necesitaría compilar para el caso de ejemplo, pero no creo que nadie me agradecería por publicar la verdadera expresión con la que estoy trabajando :) Mi pregunta es la primera oración, todo lo demás es fondo. – Janus

1

Sólo quería para actualizar las excelentes soluciones de aaz y Janus. Parece que, al menos en Mathematica 9.0.1.0 en Mac OS X, la asignación (ver la solución de aaz)

{i_Integer -> Slot[i]} 

falla. Sin embargo, si utilizamos

{i_Integer :> Slot[i]} 

, lo conseguimos. Lo mismo vale, por supuesto, para la llamada ReplaceAll en la versión de "seguridad laboral" de Janus.

Para una buena medida, incluyo mi propia función.

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] & 

Podría parecer un poco como una trampa de utilizar la expresión original en la función, pero como señala aaz, necesitamos alguna información de la expresión original. Si bien no lo necesita todo, para tener una única función que puede unflatten, todo es necesario.

Mi aplicación es similar a la de Janus: estoy paralelizando las llamadas a Simplify para un tensor. Usando ParallelTable puedo mejorar significativamente el rendimiento, pero arruino la estructura del tensor en el proceso. Esto me da una forma rápida de reconstruir mi tensor original, simplificado.

+0

El original sigue funcionando bien para mí en v9. El propósito de 'makeUnflatten' es exactamente almacenar la información sobre la estructura de' expr' en una función anónima de desempaquetado, por lo que no es necesario mantener la expresión original. – Janus

Cuestiones relacionadas