2012-06-27 23 views
6

¿Es posible calcular una matriz que depende de los valores pasados ​​(es decir, índices menores) en Repa? Parte (s) inicial (es) de la matriz (por ejemplo, a[0]) se proporciona. (Tenga en cuenta que estoy usando una notación tipo C para indicar un elemento de matriz; no lo confunda)¿Cómo se calcula a [i] = f (a [i-1]) en Repa?

Leí el tutorial y comprobé rápidamente el hackage pero no pude encontrar una función para hacerlo.

(supongo que hacer este tipo de cálculo en serie 1D no tiene sence en Repa porque no se puede paralelizar él. Pero creo que se puede paralelizar que en el caso de 2 dimensiones o más.)

EDITAR: Probablemente debería ser más específico sobre qué tipo de f quiero usar. Como no hay forma de paralelizar en el caso a[i] es un escalar, centrémonos en el caso a[i] es un vector N dim. No necesito que a[i] sea más dimensional (como la matriz) porque puede "desenrollarlo" en un vector. Entonces, f es una función que mapea R^N a R^N.

La mayor parte del caso, es de esta manera:

b = M a[i-1] 
a[i][j] = g(b)[j] 

donde b es un N dim vector, M es una matriz N por N (no suposición de poca densidad), y g es alguna función no lineal. Y quiero calcularlo para i=1,..N-1 dado a[0], g y M. Mi esperanza es que haya alguna forma genérica para (1) paralelizar este tipo de cálculo y (2) hacer que la asignación de variables intermedias, como b sea eficiente (en lenguaje C, puede reutilizarlo, sería bueno si Repa o una biblioteca similar puede hacerlo como una magia sin romper la pureza).

+0

Para el 'f' asociativo, se puede paralelizar y se denomina" exploración ". http://en.wikipedia.org/wiki/Prefix_sum No pude encontrar el escaneo en la documentación de Repa. – Heatsink

+0

Puede hacerlo con una plantilla de reparación, http://hackage.haskell.org/packages/archive/repa/2.0.2.1/doc/html/Data-Array-Repa-Stencil.html. Pero vea también http://stackoverflow.com/questions/6170008/how-to-take-an-array-slice-with-repa-over-a-range –

+1

@Heatsink ¿No necesitaría un escáner una serie como entrada? Para mí, esto se parece más a un [despliegue] (http://en.wikipedia.org/wiki/Anamorphism). – phg

Respuesta

1

Editar: En realidad, creo que malinterpreté la pregunta. Dejaré mi respuesta aquí, en caso de que sea útil para alguien más ...

Usted puede utilizar traversehttp://hackage.haskell.org/packages/archive/repa/3.2.1.1/doc/html/Data-Array-Repa.html#v:traverse:

Prelude Data.Array.Repa R> let x = fromListUnboxed (Z :. 10 :: DIM1) [1..10] 
Prelude Data.Array.Repa R> R.computeUnboxedS $ R.traverse x (\ (Z :. i) -> (Z :. (i - 1))) (\f (Z :. i) -> f (Z :. (i + 1)) - f (Z :. i)) 
AUnboxed (Z :. 9) (fromList [1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0]) 

disección:

R.computeUnboxedS $       -- force the vector to be "real" 
    R.traverse x         -- traverse the vector 
    (\ (Z :. i) -> (Z :. (i - 1)))     -- function to get the shape of the result 
    (\f (Z :. i) -> f (Z :. (i + 1)) - f (Z :. i)) -- actual "stencil" 

extendiéndola a multi- matriz dimensional debe ser trivial.

+0

Está calculando la matriz de resultados basada únicamente en la matriz fuente. Lo que quiero calcular es una matriz cuyo elemento depende de su paso anterior. Puede pensar que el 'i' en el título es del tamaño de la matriz. Quise decir el índice. – tkf

+0

¿Qué hay de usar una combinación de 'Data.Vector.Unboxed.scanl1'' y' Repa.toUnboxed'? Por ejemplo, 'cumsum' sería:' R.fromUnboxed (R.extent y) $ U.scanl1 '(+) $ (R.toUnboxed y) '. [Feo como el infierno, y probablemente no extensible a las dimensiones más altas.] – lbolla

+0

cumsum sigue siendo el cálculo de la matriz de origen a la matriz de destino. Depende de la parte anterior de la matriz * fuente *, no del objetivo. Como Heatsink y phg mencionados en los comentarios anteriores, desplegar es lo que necesito. Me gustaría saber cómo hacerlo en Repa (o en cualquier otra biblioteca orientada a arreglos en Haskell). – tkf

3

No puedo ver una manera Repa de hacer esto. Pero hay para Vector: Data.Vector.iterateN construye el vector que desea. Luego Data.Array.Repa.fromUnboxed para convertirlo de Vector a Repa.

iterateN :: Int -> (a -> a) -> a -> Vector aSource 

O (n) Aplicar la función n veces para valor. Zeroth elemento es el valor original.

+0

Gracias. Esto debería ser suficiente al hacer el cálculo 1D. Probablemente no necesite preocuparme por Repa. Solo quiero algo comparable a C (no optimizado) en términos de velocidad en Haskell. ¿Puede ser esto multidimensional? (¿Puede 'a' ser otro vector?) Y si es así, ¿puede ser paralelizado? – tkf

+0

Bueno, depende de qué tipo de generalización multidimensional está preguntando. En el caso de 1D, es obviamente imposible de paralelizar, ya que la función en sí es bastante inherentemente secuencial. ¿Puedes ser más específico acerca de cómo se vería la generalización multidimensional sobre la que preguntas? –

+0

Claro. Digamos que 'a [i] 'es un vector (entonces' a' es una matriz 2D) y quiero calcular 'a [i] = M a [i-1]' dado un valor inicial 'a [0]' y una matriz 'M', hasta' i = N-1'. Usando la notación que usé para el título, es 'f (x) = M x' donde' f' está vectorizado ahora. Puedes pensar en cualquier tipo de 'f', pero básicamente solo usa el valor de un paso anterior. – tkf