Tablas hash en MATLAB

92

¿MATLAB tiene algún soporte para tablas hash?


Algunos antecedentes

Estoy trabajando en un problema en Matlab que requiere una representación en el espacio de escala de una imagen. Para hacer esto, creo un filtro gaussiano 2-D con variación sigma*s^kpara ken algún rango, y luego uso cada uno a su vez para filtrar la imagen. Ahora, quiero algún tipo de mapeo de kla imagen filtrada.

Si ksiempre fuera un número entero, simplemente crearía una matriz 3D tal que:

arr[k] = <image filtered with k-th guassian>

Sin embargo, kno es necesariamente un número entero, por lo que no puedo hacer esto. Lo que pensé en hacer fue mantener una serie de ks tales que:

arr[find(array_of_ks_ = k)] = <image filtered with k-th guassian>

Lo que parece bastante bueno a primera vista, excepto que haré esta búsqueda potencialmente unos miles de veces con aproximadamente 20 o 30 valores de k , y me temo que esto afectará el rendimiento.

Me pregunto si no me serviría mejor haciendo esto con una tabla hash de algún tipo para tener un tiempo de búsqueda que sea O (1) en lugar de O (n).


Ahora, sé que no debería optimizar prematuramente, y es posible que no tenga este problema en absoluto, pero recuerde, esto es solo el fondo, y puede haber casos en los que esta sea realmente la mejor solución, independientemente de si es el la mejor solución para mi problema.

Nathan Fellman
fuente

Respuestas:

14

Matlab no tiene soporte para tablas hash. EDITAR Hasta r2010a, es decir; vea la respuesta de @Amro .

Para acelerar sus búsquedas, puede soltar findy usar INDEXACIÓN LÓGICA .

arr{array_of_ks==k} = <image filtered with k-th Gaussian>

o

arr(:,:,array_of_ks==k) = <image filtered with k-th Gaussian>

Sin embargo, en toda mi experiencia con Matlab, nunca he tenido una búsqueda como un cuello de botella.


Para acelerar su problema específico, le sugiero que utilice el filtrado incremental

arr{i} = GaussFilter(arr{i-1},sigma*s^(array_of_ks(i)) - sigma*s^(array_of_ks(i-1)))

asumiendo que array_of_ksestá ordenado en orden ascendente, y GaussFilter calcula el tamaño de la máscara de filtro en función de la varianza (y utiliza 2 filtros 1D, por supuesto), o puede filtrar en el espacio de Fourier, que es especialmente útil para imágenes grandes y si las variaciones son espaciados uniformemente (lo que probablemente no sea así).

Jonas
fuente
120

Considere usar la clase de mapa de MATLAB: contenedores.Map . Aquí hay una breve descripción:

  • Creación:

    >> keys = {'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', ...
      'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'Annual'};
    
    >> values = {327.2, 368.2, 197.6, 178.4, 100.0,  69.9, ...
      32.3,  37.3,  19.0,  37.0,  73.2, 110.9, 1551.0};
    
    >> rainfallMap = containers.Map(keys, values)
    
    rainfallMap = 
      containers.Map handle
      Package: containers
    
      Properties:
            Count: 13
          KeyType: 'char'
        ValueType: 'double'
      Methods, Events, Superclasses
  • Buscar:

    x = rainfallMap('Jan');
  • Asignar:

    rainfallMap('Jan') = 0;
  • Añadir:

    rainfallMap('Total') = 999;
  • Eliminar:

    rainfallMap.remove('Total')
  • Inspeccionar:

    values = rainfallMap.values;
    keys = rainfallMap.keys;
    sz = rainfallMap.size;
  • Comprobar clave:

    if rainfallMap.isKey('Today')
        ...
    end
Amro
fuente
7
¡Vaya, no sabía eso! +1. ¿Sabes si son mucho más rápidos que la indexación lógica?
Jonas
3
Containers.Map se agregó en MATLAB 7.7 (R2008b), consulte mathworks.com/access/helpdesk/help/techdoc/rn/brqyzax-1.html . Lo nuevo en R2010a es un constructor para especificar el tipo de clave y el tipo de valor. M = contenedores.Map ('KeyType', kType, 'ValueType', vType)
zellus
@Jonas: No los he usado mucho, sería interesante ver cómo se comparan con el uso de la indexación lógica para la búsqueda ..
Amro
9
@ zellus, @ amro: ¿No es molesto que no haya un historial de los comandos en Matlab?
Jonas
4
Búsqueda: rainMap ('Jan'); Asignar: rainMap ('Jan') = 'cero'; Inspeccionar: rainMap.values; rainMap.keys; rainMap.size; Compruebe la clave: rainMap.isKey ('Hoy');
Evgeni Sergeev
26

Los nuevos contenedores de Matlab R2008b (7.7). La clase Map es una versión Matlab reducida de la interfaz java.util.Map . Tiene el beneficio adicional de una integración perfecta con todos los tipos de Matlab ( Java Maps no puede manejar estructuras de Matlab, por ejemplo), así como la capacidad desde Matlab 7.10 (R2010a) para especificar tipos de datos. .

Las implementaciones serias de Matlab que requieren mapas / diccionarios de valores clave aún deben usar las clases de mapas de Java ( java.util.EnumMap , HashMap , TreeMap , LinkedHashMap o Hashtable ) para obtener acceso a su funcionalidad más amplia, si no al rendimiento. Las versiones de Matlab anteriores a R2008b no tienen alternativa real en ningún caso y deben usar las clases de Java.

Una posible limitación del uso de colecciones de Java es su incapacidad para contener tipos de Matlab no primitivos, como estructuras. Para superar esto, convierta los tipos (por ejemplo, usando struct2cell o programáticamente), o cree un objeto Java separado que contendrá su información y almacenará este objeto en la Colección Java.

También puede estar interesado en examinar una implementación Hashtable puramente orientada a objetos (basada en clases) de Matlab, que está disponible en File Exchange .

Yair Altman
fuente
1
Otra implementación basada en clases de Matlab publicada hoy: mathworks.com/matlabcentral/fileexchange/28586
Yair Altman
19

Podrías usar java para ello.

En matlab:

dict = java.util.Hashtable;
dict.put('a', 1);
dict.put('b', 2);
dict.put('c', 3);
dict.get('b')

Pero tendrías que hacer algunos perfiles para ver si te da una ganancia de velocidad, supongo ...

tauran
fuente
12

Es un poco complicado, pero me sorprende que nadie haya sugerido el uso de estructuras. Puede acceder a cualquier campo de estructura por nombre de variable, ya que struct.(var)dónde varpuede estar cualquier variable y se resolverá adecuadamente.

dict.a = 1;
dict.b = 2;

var = 'a';

display( dict.(var) ); % prints 1
Mark Elliot
fuente
1
Se rompería si usa un número como nombre de campo dict.('2'):: mathworks.com/access/helpdesk/help/techdoc/matlab_prog/…
Amro
Además, las variables tienen que ser enteros: dict.(['k',num2str(1)])funciona, pero dict.(['k',num2str(1.1)])falla, y si los valores son enteros, puedes usarlos para indexar directamente. De lo contrario, es una buena idea.
Jonas
@Amro, @Jonas, puntos justos, si las claves fueran enteros, no necesitaría usar este truco (una matriz tendría más sentido) ... si las claves son flotantes arbitrarios, esto es un poco más desafiante, pero yo prefijaría una letra y reemplazaría la .con una _.
Mark Elliot
6
Los problemas anteriores con el uso de estructuras se pueden evitar variabilizando las cadenas antes de agregar como nombres de campo:dict.(genvarname(['k',num2str(1.1)]))
foglerit