2011-05-31 15 views
7

Tengo una tabla muy grande en Mathematica ((dimcub-1)^3 elementos) proveniente de una FFT inversa. Necesito usar la interpolación periódica en esta tabla. Como la interpolación periódica requiere que los primeros elementos y los últimos elementos sean iguales, creo una nueva tabla de dim^3 elementos manualmente y la utilizo en mi interpolación. Funciona pero es feo/lento y debido a mi mesa intermedia superflua, llegué a la barrera de la memoria antes. ¿Puede alguien decirme cómo convertir mi vieja tabla en una tabla periódica de alguna manera al agregar elementos o usar mi tabla no periódica para hacer una función de interpolación periódica? Aquí está mi pieza de código actual:Mathematica tabla grande interpolación periódica

mr 1 es la nueva tabla:

mr1 = Table[ 0. , {i, 1, dimcub}, {j, 1, dimcub}, {k, 1, dimcub}]; 

Do[Do[ Do[ 
     mr1[[m, n, k]] = oldtable[[m, n, k]] ; , {m, 1, 
     dimcub - 1}]; , {n, 1, dimcub - 1}]; , {k, 1, dimcub - 1}]; 
Do[Do[  mr1[[m, n, dimcub]] = mr1[[m, n, 1]]; 
    mr1[[m, dimcub, n]] = mr1[[m, 1, n]]; 
    mr1[[dimcub, m, n]] = mr1[[1, m, n]];  , {m, 1, dimcub - 1}]; 
mr1[[n, dimcub, dimcub]] = mr1[[n, 1, 1]]; 
mr1[[dimcub, n, dimcub]] = mr1[[1, n, 1]]; 
mr1[[dimcub, dimcub, n]] = mr1[[1, 1, n]]; , {n, 1, dimcub - 1}]; 
mr1[[dimcub, dimcub, dimcub]] = mr1[[1, 1, 1]]; 

Remove[oldtable]; 

myinterpolatingfunction = 
ListInterpolation[mr1, {{1, dimcub}, {1, dimcub}, {1, dimcub}}, 
    InterpolationOrder -> 1, 
    PeriodicInterpolation -> True]; 

Remove[mr1]; 

myinterpolatingfunction tiene mucha menos memoria y funciona a la perfección una vez que eliminar las tablas de más edad. Cualquier ayuda será apreciada.

Respuesta

4

Gracias por todas las respuestas. Probé la sugerencia de leonid pero cuando imprimí mi tabla de edad, todavía estaba (dimcub -1)^3 dimensional. Se definieron nuevos elementos y puedo verlos individualmente, pero no aparecen como parte de la tabla antigua cuando imprimo toda la tabla. Así que terminé con algo similar que está haciendo exactamente lo que necesitaba:

oldtable= PadRight[oldtable, {dimcub, dimcub, dimcub}]; 
oldtable[[All, All, dimcub]] = oldtable[[All, All, 1]]; 
oldtable[[All, dimcub, All]] = oldtable[[All, 1, All]]; 
oldtable[[dimcub, All, All]] = oldtable[[1, All, All]]; 
oldtable[[All, dimcub, dimcub]] = oldtable[[All, 1, 1]]; 
oldtable[[dimcub, All, dimcub]] = oldtable[[1, All, 1]]; 
oldtable[[dimcub, dimcub, All]] = oldtable[[1, 1, All]]; 
oldtable[[dimcub, dimcub, dimcub]] = oldtable[[1, 1, 1]]; 

La respuesta del mago es demasiado avanzado para mi nivel de Mathematica ..

+0

Creo que todos nos perdimos el hecho de que querías que la nueva mesa fuera más grande que la anterior. Ver mi respuesta: Lo que sostuvo para la respuesta de Leonid también es válido para los suyos: las últimas cuatro líneas son superfluas. –

+0

Quería que la nueva tabla fuera más grande que la anterior en 1 en cada dimensión, ya que es la única forma en que podría tener una tabla con puntos finales coincidentes para ingresar a la interfaz de lista periódica. Si hay una manera de hacer una interpolación periódica sin este paso intermedio, preferiría usarlo. – Hsn

+0

¿podría modificar su solución para hacer periódicamente solo la segunda y tercera dimensiones y no la primera? [en mi caso las últimas 2 dimensiones son coordenadas espaciales y la primera es el tiempo] – Valerio

8

Se puede conseguir mucho más rápido y más memoria de forma eficiente mediante la modificación de la tabla original de la siguiente manera:

oldtable[[All, All, -1]] = oldtable[[All, All, 1]]; 
oldtable[[All, -1, All]] = oldtable[[All, 1, All]]; 
oldtable[[-1, All, All]] = oldtable[[1, All, All]]; 
oldtable[[All, -1, -1]] = oldtable[[All, 1, 1]]; 
oldtable[[-1, All, -1]] = oldtable[[1, All, 1]]; 
oldtable[[-1, -1, All]] = oldtable[[1, 1, All]]; 
oldtable[[-1, -1, -1]] = oldtable[[1, 1, 1]]; 

Estas asignaciones reemplazan bucles anidados y son mucho más rápidos, además de que no tienen memoria para almacenar la dupdo. Esto se basa en una funcionalidad vectorizada extendida del comando Part (matriz e indexación de expresión general), particularmente asignaciones vectorizadas. También es importante tener su matriz numérica en un formulario Packed array, que a menudo es el caso.

+0

Leonid, se queman en las listas esta semana . # 78 en StackOverflow! –

+0

Algo de redundancia allí; ver mi respuesta/comentario. –

+0

@ Mr.Wizard Wow, no esperaba eso. ¡Gracias por hacérmelo saber! Pero se olvidó de @belisarius y @yoda, están más arriba en esa lista. –

5

hecho de que sea un poco de una cabra, la solución de Leonid se puede escribir como:

a = {0, 1}~Tuples~3~SortBy~Tr // Rest; 

MapThread[ 
    (oldtable[[Sequence @@ #]] = oldtable[[Sequence @@ #2]]) &, 
    {-a, a} /. 0 -> All 
]; 
+0

+1, menos tipado general, por lo que es más fácil de extender. Daría otro +1, si pudiera, por la construcción de Infix doble de 'a'. – rcollyer

+0

Alguna redundancia allí; ver mi respuesta/comentario. –

+0

+1. Quería mostrar la correspondencia más cercana a la solución original basada en bucles, ya que es más fácil de entender. Tenía en mente agregar algo muy similar a lo que hiciste, pero ya era demasiado tarde :). ¡El infijo doble es realmente agradable! Pero ahora, eres responsable de la explicación de cómo funciona esto :). –

9

Tanto de las respuestas de Mr.Wizard Leonid y hacer demasiado trabajo. En el caso de Leonid, solo las primeras tres líneas son necesarias. Para mostrar esto que voy a cambiar los últimos 4 Set s a Equal s:

In[65]:= len = 4; oldtable = 
Partition[Partition[Range[len^3], len], len] 

Out[65]= {{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 
    16}}, {{17, 18, 19, 20}, {21, 22, 23, 24}, {25, 26, 27, 28}, {29, 
    30, 31, 32}}, {{33, 34, 35, 36}, {37, 38, 39, 40}, {41, 42, 43, 
    44}, {45, 46, 47, 48}}, {{49, 50, 51, 52}, {53, 54, 55, 56}, {57, 
    58, 59, 60}, {61, 62, 63, 64}}} 

In[66]:= oldtable[[All, All, -1]] = oldtable[[All, All, 1]]; 
oldtable[[All, -1, All]] = oldtable[[All, 1, All]]; 
oldtable[[-1, All, All]] = oldtable[[1, All, All]]; 
oldtable[[All, -1, -1]] == oldtable[[All, 1, 1]] 
oldtable[[-1, All, -1]] == oldtable[[1, All, 1]] 
oldtable[[-1, -1, All]] == oldtable[[1, 1, All]] 
oldtable[[-1, -1, -1]] == oldtable[[1, 1, 1]] 

Out[69]= True 

Out[70]= True 

Out[71]= True 

Out[72]= True 

Lo que hace Leonid se ilustra en las figuras siguientes. Las líneas 4-6 de su código hacen algo como se ilustra en el panel de la izquierda: copiar una línea (color más oscuro) de un avión ya copiado (colores claros). La línea 7 está ilustrada por el panel de la derecha. Esta es una copia de celda a celda de posiciones diagonales opuestas, y su operación no está incluida en ninguna de las primeras tres acciones de copia por separado, sino que es el resultado de su operación sucesiva.

enter image description here

+0

Gracias por la ilustración. Veo tu punto y estoy de acuerdo contigo. La forma en que Leonid hace la copia es algo que quedó de mi pregunta original en la que estaba creando una copia redundante de la tabla para aumentar el tamaño en 1. Deshacerme de la tabla intermedia redundante ya me había ahorrado suficiente memoria/tiempo. – Hsn

+2

@Sjoerd +1 para el análisis agradable y visual. –

+0

+1 para enchufar su bandera :) – abcd