Algoritmo húngaro

El algoritmo Húngaro es un algoritmo de optimización el cual resuelve problemas de asignación en tiempo . La primera versión conocida del método Húngaro, fue inventado y publicado por Harold W. Kuhn en 1955. Este fue revisado por James Munkres en 1957, y ha sido conocido desde entonces como el algoritmo Húngaro, el algoritmo de la asignación de Munkres, o el algoritmo de Kuhn-Munkres.

El algoritmo desarrollado por Kuhn está basado fundamentalmente en los primeros trabajos de otros dos matemáticos Húngaros: Dénes Kőnig y Jenő Egerváry. La gran ventaja del método de Kuhn es que es fuertemente polinómico (ver Complejidad computacional para más detalles).

El algoritmo húngaro construye una solución del problema primal partiendo de una solución no admisible (que corresponde a una solución admisible del dual) haciéndola poco a poco más admisible.

Modelado editar

El algoritmo modela un problema de asignación como una matriz de costes n×m, donde cada elemento representa el coste de asignar el enésimo trabajador al emésimo trabajo. Por defecto, el algoritmo realiza la minimización de los elementos de la matriz; de ahí que en caso de ser un problema de minimización de costes, es suficiente con comenzar la eliminación de Gauss-Jordan para hacer ceros (al menos un cero por línea y por columna). Sin embargo, en caso de un problema de maximización del beneficio, el coste de la matriz necesita ser modificado para que la minimización de sus elementos lleve a una maximización de los valores de coste originales. En un problema de costes infinito, el coste inicial de la matriz puede ser remodelado restando a cada elemento de cada línea el valor máximo del elemento de esa línea (o análogamente columna ). En un problema de coste infinito, todos los elementos son restados por el valor máximo de la matriz entera. En la matriz se tiene que realizar un conjunto de operaciones que nos permitirán conocer con mejor eficacia el resultado final de la problemática planteada.

Algoritmo editar

  Dada la matriz de costes  , se construye   encontrando el valor mínimo de cada fila y restando ese valor a cada elemento de la fila.
 
  Se encuentra el valor mínimo de cada columna y se resta a cada elemento de la columna.
 
  A partir de   se considera "grafo de las igualdades" a   tal que   está constituido por todas las copias   tales que  . En otras palabras, verificamos si para todas las filas existe una columna con costo 0 que no ha sido asignada a otra fila.
Determinar sobre   un matching   de cardinalidad máxima.


si  
Si todas las filas tienen a lo menos una intersección con costo cero que no ha sido ocupada por otra fila, estamos en el óptimo. Termina el algoritmo.


  Considero   y se etiquetan las filas que no han sido acopladas o asignadas por el algoritmo de matching máximo.
  Se etiquetan en   las columnas que tienen los ceros en correspondencia o asignadas a las filas etiquetadas (con *).
  Etiquetar las filas que no han sido ya etiquetadas y acopladas o asignadas por el algoritmo de matching máximo con las columnas ya etiquetadas (con *).
  Repetir los pasos   y   hasta que no haya más filas o columnas que etiquetar.
  Borrar las filas NO etiquetadas y las columnas etiquetadas. Para esto puede trazar una línea recta en las columnas y filas borradas.
  Sea   el elemento de   de valor mínimo entre aquellos costos no borrados (o tarjados) en el paso anterior.
  Restar   a cada elemento no borrado y sumarlo a los elementos doblemente borrados (o donde haya intersección o cruces entre las líneas marcadas en el paso   )
  Volver al paso  .

Ejemplo editar

En un cierto punto del algoritmo tenemos el grafo   y la matriz  .

 
matching máximo del grafo de las igualdades.
 


En   tengo un arco   tengo un   en .


  es matching máximo pero no es perfecto, pues la fila 3 está sin asignar.   volvemos al paso   del algoritmo.


 
  
 
  


  El matching de las columnas   y   esta acopladas al de las filas   y  


 
  
 
  
 
 
  Resto   a los elementos no borrados de   y sumo   a los elementos doblemente borrados de  .


  


  Volvemos al paso  , para recrear el grafo de las igualdades y calcular de nuevo el matching máximo.

Ejemplo 2 Problema de minimización editar

Enunciado del problema: En una empresa existen N tareas a realizar y N personas que pueden realizarlas. Tenemos una matriz N×N que contiene el coste de asignar a cada trabajador en cada tarea, en el presente caso, se supone que existen cuatro operarios (a, b, c y d) y cuatro tareas a realizar (1,2,3 y 4). El problema estriba en encontrar que tarea debemos asignar a cada trabajador para que el coste total sea mínimo. En primer lugar debemos partir de una matriz como la siguiente:

 

Donde a, b, c y d son los trabajadores que deben ejecutar las distintas tareas 1, 2, 3 y 4. En la matriz a1 representa el coste en que se incurre si el trabajador A, desarrolla la tarea 1, a2, a3, a4 muestra el coste en que se incurre cuando el trabajador A ejecuta las tareas 2, 3, 4 respectivamente. De la misma forma sucede para el resto de los trabajadores. La matriz es cuadrada de manera que cada trabajador puede ejecutar solo una tarea.

Se comienza a operar con la matriz.

  • Para hacer esto, se toma el menor valor de todos los que se encuentran en la primera fila ai (i se encuentra entre 1-4) y es restado de los otros elementos de esa fila.
  • Se repite este procedimiento para todas las filas.
  • Esto nos lleva a que en cada fila haya al menos un cero (Pueden existir varios ceros en una fila, cuando hay dos casillas que tienen valores iguales y son a la vez los valores mínimos de esas filas).
  • Ahora disponemos de una matriz donde al menos existe un cero en cada fila.
  • Tratamos de asignar a los trabajadores, de manera que cada empleado solo realice una tarea y que el coste en cada caso sea cero.

Esto se muestra en la siguiente matriz, donde los ceros son las tareas asignadas:

0 a2' 0' a4'
b1' b2' b3' 0'
0' c2' c3' c4'
d1' 0' d3' d4'

En algunos casos puede resultar que la matriz anterior no puede ser utilizada para asignar.

0 a2' a3' a4'
b1' b2' b3' 0'
0 c2' c3' c4'
d1' 0 d3' d4'

Efectivamente en el caso de la matriz anterior no se puede realizar una asignación completa, la tarea 1 es realizada de manera eficiente por los empleados A y C (Existen dos ceros en la columna 1). Ambos no pueden ser asignados a la misma tarea, también debemos advertir que nadie puede realizar la tarea 3 de manera eficiente. Para superar esto, debemos repetir el procedimiento anterior de restar el menor, para todas las columnas y entonces comprobamos si es posible la asignación.

En la mayoría de los casos esto nos dará el resultado, pero si todavía no es posible la asignación, entonces se debe seguir el siguiente procedimiento:

  • En primer lugar asigna tantas tareas como sean posible y después se debe hacer lo siguiente (asignar tareas en las filas 2, 3 y 4)
0 a2' a3' a4'
b1' b2' b3' 0'
0' c2' c3' c4'
d1' 0' d3' d4'
  • Marca todas las filas que no tengan asignación (fila 1).
  • Marca todas las columnas que tengan ceros en esa fila (columna 1).
  • Marca todas las filas que tengan asignación en la columna dada (fila 3).
  • Marca todas las columnas que tengan asignaciones en la fila dada.
  • Repetir este proceso hasta que se obtenga un circuito cerrado.
×
0 a2' a3' a4' ×
b1' b2' b3' 0'
0' c2' c3' c4' ×
d1' 0' d3' d4'

Una vez realizado todo esto se trazan líneas (casillas color gris) sobre todas las columnas marcadas y todas las filas sin marcar.

×
0 a2' a3' a4' ×
b1' b2' b3' 0'
0' c2' c3' c4' ×
d1' 0' d3' d4'

De los elementos que están sin tachar (en blanco), se busca el valor más bajo, se resta este de todos los elementos que no están señalados o tachados y se le suma a los elementos que se encuentran en la intersección de dos líneas. Los demás elementos se dejan sin cambiar. Ahora se asigna las tareas usando las reglas de arriba. Repite el procedimiento hasta que sea posible la asignación. Básicamente se encuentra el segundo coste mínimo entre dos filas. El procedimiento es repetido hasta que seas capaz de distinguir entre los trabajadores en términos de menor coste.

Bibliografía editar

Enlaces externos editar

Implementaciones editar