wolfram tablas tabla multiplicacion matrices mathematica listas graficar despejar datos comandos arrays wolfram-mathematica

arrays - tablas - resolver matrices en wolfram mathematica



Uso de funciones de matriz y tabla en Mathematica. Que es mejor cuando (5)

He sido principalmente un usuario de funciones de tabla en matemática. Sin embargo, he notado que en varios ejemplos en los que usé Array en lugar de Tabla para expresar el mismo resultado, se ejecutó notablemente más rápido, especialmente a medida que la dimensión de la tabla creció.

Entonces mi pregunta es esta: cuando la velocidad de ejecución es la principal preocupación, ¿cuándo es más apropiado usar la tabla?

¿Qué explica esta diferencia?

Mi conjetura es que dado que Arrays asume una relación funcional entre los elementos de la lista, los almacena de manera más eficiente, por lo tanto, utiliza menos memoria, lo que facilita el almacenamiento y el procesamiento posterior.

¿Es lo que está pasando?


Michael Trott en Programación (pp 707 - 710) aborda el problema de las diferencias entre Array y Table y argumenta que como Table tiene el atributo HoldAll , calcula su argumento para cada llamada, mientras que Array "en la medida de lo posible" calcula su argumento solo en el principio. Esto puede conducir a diferencias en el comportamiento, así como la velocidad.

Attributes[Table]

{HoldAll, Protegido}

Attributes[Array]

{Protegido}

Michael Trott usa los siguientes ejemplos para ilustrar la diferencia en velocidad y comportamiento. Los tomo textualmente de su libro (disco). Espero no estar rompiendo ninguna regla al hacerlo.

Remove[a, i, j]; a = 0; Table[a = a + 1; ToExpression[StringJoin["a" <> ToString[a]]][i, j], {i, 3}, {j, 3}]

{{a1 [1, 1], a2 [1, 2], a3 [1, 3]}, {a4 [2, 1], a5 [2, 2], a6 [2, 3]}, {a7 [ 3, 1], a8 [3, 2], a9 [3, 3]}}

a = 0; Array[a = a + 1; ToExpression[StringJoin["a" <> ToString[a]]], {3, 3}]

{{a1 [1, 1], a1 [1, 2], a1 [1, 3]}, {a1 [2, 1], a1 [2, 2], a1 [2, 3]}, {a1 [ 3, 1], a1 [3, 2], a1 [3, 3]}}

(Note la diferencia de comportamiento)

Para ilustrar el efecto de precomputar el primer argumento, usa el siguiente ejemplo (nuevamente, literalmente, pág. 709).

o[a = 0; Table[a = a + 1; ToExpression[StringJoin["a" <> ToString[a]]][i, j], {i, 3}, {j, 3}], {2000}] // Timing Do[a = 0; Array[a = a + 1; ToExpression[ StringJoin["a" <> ToString[a]]], {3, 3}], {2000}] // Timing

{0.700173, nulo}

{0.102587, nulo}

(Estoy usando mma7 en una Mac. Mi copia de Programming usa v5.1. Puede que haya una actualización para esto)

Esta no es la única diferencia entre Array y Table discutida en Programación , por supuesto.

Veo otras respuestas, me interesará saber lo que otros piensan de este punto.


Sin dar algunos ejemplos concretos, es difícil responder a su pregunta correctamente.

Dado que Mathematica es un programa de código cerrado, las implementaciones exactas detrás de Table y Array no pueden ser conocidas, a menos que sean explicadas por personas que participaron en el desarrollo de Mathematica.

Estos factores dificultarán su capacidad de razonar qué estructura debe usar en qué circunstancias. La experimentación será su mejor apuesta, por lo que le sugiero que mantenga versiones paralelas de sus programas, una utilizando Table y la otra utilizando Array . De esta manera, podrás ver cuál es más rápido.

Aún mejor, podría escribir una función de envoltura que depende de una variable global. Esta función, según la variable, utilizará Table o Array como la implementación subyacente, por lo que podrá cambiar rápidamente de una versión a otra, sin hacer muchas modificaciones a su código.


Su declaración:

Sin embargo, he notado que en varios ejemplos en los que usé Array en lugar de Tabla para expresar el mismo resultado, se ejecutó notablemente más rápido, especialmente a medida que la dimensión de la tabla creció.

no suele ser cierto para matrices unidimensionales . Echar un vistazo:

Cl; Needs["PlotLegends`"] $HistoryLength = 0; a = 10^8; arr = {}; tab = {}; Do[( arr = {First@Timing@Array[# &, a], arr}; tab = {First@Timing@Table[i, {i, a}], tab}; ), {10}]; ListLinePlot[{Flatten@arr, Flatten@tab}, AxesLabel -> {Style["Iteration", 14], Style["Time", 14]}, PlotLegend -> {Style["Array", 14], Style["Table", 14]}, PlotRange -> {{0, 10}, {1.6, 2}}]


Una razón por la que Array puede ser más rápida es que a menudo compila mejor su primer argumento.

En Mathematica 7:

In[1]:= SystemOptions[CompileOptions -> ArrayCompileLength] Out[1]= {"CompileOptions" -> {"ArrayCompileLength" -> 250}}

y

In[2]:= SystemOptions[CompileOptions -> TableCompileLength] Out[2]= {"CompileOptions" -> {"TableCompileLength" -> 250}}

Entonces, uno puede inferir que Array y Table deberían compilarse en el mismo punto.

Pero intentémoslo. timeAvg función timeAvg de Timo :

n = 15; Array[Mod[#^2, 5]*(1 + #2) &, {n, n}] // timeAvg Table[Mod[i^2, 5]*(1 + j), {i, n}, {j, n}] // timeAvg (* Out = 0.00034496 *) (* Out = 0.00030016 *) n = 16; Array[Mod[#^2, 5]*(1 + #2) &, {n, n}] // timeAvg Table[Mod[i^2, 5]*(1 + j), {i, n}, {j, n}] // timeAvg (* Out = 0.000060032 *) (* Out = 0.0005008 *)

Lo que vemos es que Array puede compilar Mod[#^2, 5]*(1 + #2) & mientras que Table no puede compilar Mod[i^2, 5]*(1 + j) y por lo tanto para Array vuelve más rápida cuando se alcanza CompileLength. Muchas funciones no son tan favorables. Si simplemente cambia la multiplicación a la división en la función, lo que resulta en un resultado racional en lugar de entero, entonces esta compilación automática no ocurre, y la Table es más rápida:

n = 15; Array[Mod[#^2, 5]/(1 + #2) &, {n, n}] // timeAvg Table[Mod[i^2, 5]/(1 + j), {i, n}, {j, n}] // timeAvg (* Out = 0.000576 *) (* Out = 0.00042496 *) n = 16; Array[Mod[#^2, 5]/(1 + #2) &, {n, n}] // timeAvg Table[Mod[i^2, 5]/(1 + j), {i, n}, {j, n}] // timeAvg (* Out = 0.0005744 *) (* Out = 0.0004352 *)

¿Pero qué pasa si podemos hacer esta compilación también? Si usamos números de punto flotante, comenzando con 1. , obtendremos una salida Real , que se puede compilar:

n = 15; Array[Mod[#^2, 5]/(1 + #2) &, {n, n}, 1.] // timeAvg Table[Mod[i^2, 5]/(1 + j), {i, 1., n}, {j, 1., n}] // timeAvg (* Out = 0.0006256 *) (* Out = 0.00047488 *) n = 16; Array[Mod[#^2, 5]/(1 + #2) &, {n, n}, 1.] // timeAvg Table[Mod[i^2, 5]/(1 + j), {i, 1., n}, {j, 1., n}] // timeAvg (* Out = 0.00010528 *) (* Out = 0.00053472 *)

Y una vez más, Array es más rápido en la matriz de dimensión más grande.


Array no tiene ventajas de rendimiento sobre la Table . Hay diferencias entre ellos que hacen que uno prefiera a otro.

EDITAR Se notó por varias personas que Table es más lento en arreglos multidimensionales. Todos ellos utilizaron variables para mantener el tamaño de la tabla. Table tiene atributos HoldAll y solo auto-evalúa el límite de interacción más externo. Debido a que los iteradores internos permanecen sin evaluar, el elemento de la tabla no se compila. Usando números explícitos o With con resultado en auto compilación:

In[2]:= With[{b = 10^4, c = 10^4}, {Timing@(#[[1, 1]] &[ar = Array[(# + #2) &, {b, c}]]) , Timing@(#[[1, 1]] &[ta = Table[(i + j), {i, b}, {j, c}]])} ] Out[2]= {{4.93, 2}, {4.742, 2}} In[3]:= Attributes[Table] Out[3]= {HoldAll, Protected} La Array permite crear una matriz de valores de función tanto como la Table . Toman diferentes argumentos. Array tiene una función:

In[34]:= Array[Function[{i, j}, a[i, j]], {3, 3}] Out[34]= {{a[1, 1], a[1, 2], a[1, 3]}, {a[2, 1], a[2, 2], a[2, 3]}, {a[3, 1], a[3, 2], a[3, 3]}}

while table toma una forma explícita:

In[35]:= Table[a[i, j], {i, 3}, {j, 3}] Out[35]= {{a[1, 1], a[1, 2], a[1, 3]}, {a[2, 1], a[2, 2], a[2, 3]}, {a[3, 1], a[3, 2], a[3, 3]}}

Array solo puede revisar matrices normales, mientras que Table puede realizar iteraciones arbitrarias en la lista:

In[36]:= Table[a[i, j], {i, {2, 3, 5, 7, 11}}, {j, {13, 17, 19}}] Out[36]= {{a[2, 13], a[2, 17], a[2, 19]}, {a[3, 13], a[3, 17], a[3, 19]}, {a[5, 13], a[5, 17], a[5, 19]}, {a[7, 13], a[7, 17], a[7, 19]}, {a[11, 13], a[11, 17], a[11, 19]}}

A veces la Array puede ser más sucinta. Compara la tabla de multiplicar:

In[37]:= Array[Times, {5, 5}] Out[37]= {{1, 2, 3, 4, 5}, {2, 4, 6, 8, 10}, {3, 6, 9, 12, 15}, {4, 8, 12, 16, 20}, {5, 10, 15, 20, 25}}

versus

In[38]:= Table[i j, {i, 5}, {j, 5}] Out[38]= {{1, 2, 3, 4, 5}, {2, 4, 6, 8, 10}, {3, 6, 9, 12, 15}, {4, 8, 12, 16, 20}, {5, 10, 15, 20, 25}}

Array permite construir expresiones con cualquier encabezado, no solo en la lista:

In[39]:= Array[a, {3, 3}, {1, 1}, h] Out[39]= h[h[a[1, 1], a[1, 2], a[1, 3]], h[a[2, 1], a[2, 2], a[2, 3]], h[a[3, 1], a[3, 2], a[3, 3]]]

Por defecto, el encabezado h se elige para que sea la List da como resultado la creación de la matriz regular. La tabla no tiene esta flexibilidad.