<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Problema de asignación archivos &#187; Ingenieria Industrial Online</title>
	<atom:link href="https://ingenieriaindustrialonline.com/tag/problema-de-asignacion/feed/" rel="self" type="application/rss+xml" />
	<link>https://ingenieriaindustrialonline.com/tag/problema-de-asignacion/</link>
	<description>ingenieriaindustriaonline.com</description>
	<lastBuildDate>Sun, 24 Mar 2024 20:43:36 +0000</lastBuildDate>
	<language>es</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.3</generator>

<image>
	<url>https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/cropped-faVicon-32x32.png</url>
	<title>Problema de asignación archivos &#187; Ingenieria Industrial Online</title>
	<link>https://ingenieriaindustrialonline.com/tag/problema-de-asignacion/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Solución de un modelo de transporte mediante un algoritmo de asignación</title>
		<link>https://ingenieriaindustrialonline.com/investigacion-de-operaciones/solucion-de-un-modelo-de-transporte-mediante-un-algoritmo-de-asignacion/</link>
					<comments>https://ingenieriaindustrialonline.com/investigacion-de-operaciones/solucion-de-un-modelo-de-transporte-mediante-un-algoritmo-de-asignacion/#respond</comments>
		
		<dc:creator><![CDATA[Bryan Salazar López]]></dc:creator>
		<pubDate>Tue, 10 Aug 2021 18:26:15 +0000</pubDate>
				<category><![CDATA[Investigación de operaciones]]></category>
		<category><![CDATA[Google OR-Tools]]></category>
		<category><![CDATA[Modelo de transporte]]></category>
		<category><![CDATA[Problema de asignación]]></category>
		<category><![CDATA[Problema de transporte]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://ingenieriaindustrialonline.com/?p=26835</guid>

					<description><![CDATA[<p>En su versión más básica, un modelo de transporte tiene por objetivo llevar unidades de un punto específico llamado fuente u origen  hacia otro punto específico llamado destino. Para cumplir con este objetivo deberá satisfacer los requerimientos establecidos por los destinos (demanda), al tiempo que satisface la disponibilidad de las fuentes (oferta). Estos planes de transporte deberán cumplir algún &#8230;</p>
<p>La entrada <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/solucion-de-un-modelo-de-transporte-mediante-un-algoritmo-de-asignacion/">Solución de un modelo de transporte mediante un algoritmo de asignación</a> se publicó primero en <a href="https://ingenieriaindustrialonline.com">Ingenieria Industrial Online</a>.</p>
]]></description>
										<content:encoded><![CDATA[
		<div id="introduccion" data-title="Introducción" class="index-title"></div>
	En su versión más básica, un <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/problema-del-transporte-o-distribucion/"><strong>modelo de transporte</strong></a> tiene por objetivo llevar unidades de un punto específico llamado <em><strong>fuente</strong></em> u <em><strong>origen</strong></em>  hacia otro punto específico llamado <em><strong>destino</strong></em>. Para cumplir con este objetivo deberá satisfacer los requerimientos establecidos por los destinos (demanda), al tiempo que satisface la disponibilidad de las fuentes (oferta). Estos planes de transporte deberán cumplir algún criterio de optimización: <em>minimizar distancias, minimizar tiempos, maximizar ganancias, </em>por citar algunos ejemplos.</p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2021/08/Figure-2021-08-10-093443.png" alt="" width="345" height="353" class="aligncenter size-full wp-image-26838" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2021/08/Figure-2021-08-10-093443.png 345w, https://ingenieriaindustrialonline.com/wp-content/uploads/2021/08/Figure-2021-08-10-093443-293x300.png 293w" sizes="(max-width: 345px) 100vw, 345px" /></p>
<p>Es conocido, que los <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/problemas-de-asignacion/"><strong>problemas de asignación puros</strong></a> son una variación del problema original del transporte, en cuyos casos las variables de decisión solo pueden tomar valores binarios. <em>¿Esto qué significa? </em>Pues bien, como algoritmo de red, un problema básico de transporte es un modelo de asignación genérico; modelo en el cual se pretende establecer la asignación entre fuentes y destinos; es decir, cuántas unidades se transportarán desde el origen <em>i </em>hacia el destino <em>j</em>. Se entiende además, que en el caso del transporte, estas variables de asignación no son necesariamente binarias.</p>
<p>El objetivo de este artículo consiste en utilizar las librerías del software Google OR-Tools (<em>Python</em>), para abordar un problema de transporte básico, de acuerdo a un modelo de asignación.</p>
<hr />
<h2>El problema</h2>

		<div id="el-problema" data-title="El problema" class="index-title"></div>
	
<p><span>Con el propósito de evaluar los resultados obtenidos a través del tratamiento de un problema técnicamente formulado y abordado, utilizaremos un caso descrito en el libro Investigación de Operaciones (9na edición), de Hamdy A. Taha (University of Arkansas, Fayetteville), (Ejemplo 5.1-1):</span></p>
<blockquote class=" quote-simple "><p>MG Auto cuenta con tres plantas en Los Ángeles, Detroit y Nueva Orleáns, y dos importantes centros de distribución en Denver y Miami. Las capacidades trimestrales de las tres plantas son 1000, 1500 y 1200 automóviles, y las demandas de los dos centros de distribución durante el mismo periodo son de 2300 y 1400 automóviles. La distancia en millas entre las plantas y los centros de distribución aparece en la siguiente tabla: <cite>Hamdy A. Taha</cite></p></blockquote>
<p><strong>Relación de distancias entre plantas y cedis</strong></p>
<table width="247">
<tbody>
<tr>
<td width="87" style="text-align: center;"></td>
<td width="80" style="text-align: center;"><strong>Denver</strong></td>
<td width="80" style="text-align: center;"><strong>Miami</strong></td>
</tr>
<tr>
<td style="text-align: center;"><strong>Los Ángeles</strong></td>
<td style="text-align: center;">1000</td>
<td style="text-align: center;">2690</td>
</tr>
<tr>
<td style="text-align: center;"><strong>Detroit</strong></td>
<td style="text-align: center;">1250</td>
<td style="text-align: center;">1350</td>
</tr>
<tr>
<td style="text-align: center;"><strong>Nueva Orleáns</strong></td>
<td style="text-align: center;">1275</td>
<td style="text-align: center;">850</td>
</tr>
</tbody>
</table>
<p><em>Distancia dada en millas</em></p>
<p>El caso también plantea que la compañía de transporte cobra 8 centavos por milla por automóvil. Así entonces, el objetivo del modelo no será minimizar la distancia total, sino minimizar el costo total de transporte. Con base en la distancia dada en millas y el costo de transporte unitario, construimos nuestra tabla de costos (redondeada al dólar más cercano):</p>
<p><strong>Relación de costos de distribución entre plantas y cedis</strong></p>
<table width="247">
<tbody>
<tr>
<td width="87" style="text-align: center;"></td>
<td width="80" style="text-align: center;"><strong>Denver</strong></td>
<td width="80" style="text-align: center;"><strong>Miami</strong></td>
</tr>
<tr>
<td style="text-align: center;"><strong>Los Ángeles</strong></td>
<td style="text-align: center;">80</td>
<td style="text-align: center;">215</td>
</tr>
<tr>
<td style="text-align: center;"><strong>Detroit</strong></td>
<td style="text-align: center;">100</td>
<td style="text-align: center;">108</td>
</tr>
<tr>
<td style="text-align: center;"><strong>Nueva Orleáns</strong></td>
<td style="text-align: center;">102</td>
<td style="text-align: center;">68</td>
</tr>
</tbody>
</table>
<p><em>Costo dado en dólares automóvil</em></p>
<p>La representación gráfica de la red sería la siguiente:</p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2021/08/Figure-2021-08-10-093443-1.png" alt="Problema del transporte" width="487" height="401" class="aligncenter size-full wp-image-26839" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2021/08/Figure-2021-08-10-093443-1.png 487w, https://ingenieriaindustrialonline.com/wp-content/uploads/2021/08/Figure-2021-08-10-093443-1-300x247.png 300w" sizes="(max-width: 487px) 100vw, 487px" /></p>
<h2>Resolviendo un problema de transporte mediante Or Tools (Asignación)</h2>

		<div id="resolviendo-un-problema-de-transporte-mediante-or-tools-asignacion" data-title="Resolviendo un problema de transporte mediante Or Tools (Asignación)" class="index-title"></div>
	
<p>De acuerdo a lo mencionado en el artículo de<span> </span><a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/que-es-y-para-que-sirve-google-or-tools/"><strong>introducción a Google OR-Tools</strong></a>, esta herramienta soporta múltiples lenguajes de programación, así entonces, haremos uso del lenguaje de programación Python.</p>
<p>Utilizaremos un solucionador para programación lineal mixta: <em>SCIP.</em></p>
<h3>Importar librerías</h3>
<p>El primer paso consiste en importar la librería de Google Or Tools, esto nos permitirá utilizar todas sus funciones.</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>f<span style="font-size: 14px; font-weight: lighter;">rom ortools.linear_solver import pywraplp</span></code></pre>
</div>
<h3>Declarar el solucionador</h3>
<p>Tal como lo mencionamos, vamos a utilizar un solucionador de <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/programacion-lineal-mixta-con-google-or-tools/"><strong>programación lineal mixta</strong></a>. Esto nos permitirá utilizar tanto variables enteras como variables continuas. Debemos declarar el solucionador <em>SCIP</em>.</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>solver = pywraplp.Solver.CreateSolver('SCIP')</code></pre>
</div>
<h3>Crear la data del modelo</h3>
<p>La data base del modelo corresponde a la matriz de costos. Debemos de considerar que el orden en el que se ingresa la información corresponda a la relación precisa entre las variables; veamos:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>costos = [
    [ 80, 215],
    [100, 108],
    [102,  68],
]

num_plantas = len(costos)
num_cedis = len(costos[0])</code></pre>
</div>
<p>Así mismo, utilizaremos el método <em><strong>len </strong></em>para calcular el número de <em>plantas</em> y el número de <em>cedis</em>. En el caso de las <em>plantas</em>, contará el número de filas de la matriz; en el caso de los <em>cedis</em>, contará en número de columnas (para saber que contará las columnas de la matriz se utiliza <em>costos[0]</em>).</p>
<h3>Crear las variables del modelo</h3>
<p>Este es un problema básico, y como tal las únicas variables necesarias serán las asignaciones. Es decir, las variables <span>x[i, j], donde <em>i </em>representa el origen y <em>j </em>representa el destino. Este proceso es relativamente sencillo y puede generarse cada variable de manera manual, sin embargo, automatizaremos la creación de las variables por medio de ciclos, con el propósito de preparar nuestro código para problemas más robustos:</span></p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>x = {}
for i in range(num_plantas):
    for j in range(num_cedis):
        x[i, j] = solver.IntVar(0, solver.infinity(), '')</code></pre>
</div>
<p>De esta manera se crean las variables de asignación. Es decir, tendremos tantos <em>i </em>como número de plantas (orígenes), asociados a tantos <em>j </em>como número de cedis (destinos). La naturaleza de las variables es entera (solver.IntVar), ya que hace referencia a la distribución de automóviles. Desde la creación de las variables podemos definir su rango, en este caso diremos que será desde 0 hasta infinito (solver.infinity).</p>
<p>Así entonces, se entiende que, por ejemplo, la variable x[0,0] hace referencia al número de automóviles que se enviarán desde el origen <em>0 </em>(<em>Los Ángeles</em>) hacia el destino 0 (<em>Denver</em>). El orden de la asignación se basa en la matriz de costos.</p>
<p>El código anterior crea todas las variables de asignación necesarias.</p>
<h3>Crear las restricciones</h3>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>#Restricciones de disponibilidad (oferta en plantas)
solver.Add(solver.Sum([x[0, j] for j in range(num_cedis)]) &lt;= 1000)
solver.Add(solver.Sum([x[1, j] for j in range(num_cedis)]) &lt;= 1500)
solver.Add(solver.Sum([x[2, j] for j in range(num_cedis)]) &lt;= 1200)

#Restricciones de demanda (cedis)
solver.Add(solver.Sum([x[i, 0] for i in range(num_plantas)]) &gt;= 2300)
solver.Add(solver.Sum([x[i, 1] for i in range(num_plantas)]) &gt;= 1400) </code></pre>
</div>
<p>El método <em><strong>Add </strong></em>de <em>solver</em>, nos servirá para agregar las restricciones al modelo. Las restricciones de oferta y demanda necesarias se adicionan tal cual el código anterior. Explicaremos la primera de ellas:</p>
<p style="text-align: center;">solver.Add(solver.Sum([x[0, j] for j in range(num_cedis)]) &lt;= 80)</p>
<p>La anterior restricción indica que, la sumatoria de todas las variables x[0, j], para los <em>j </em>del conjunto <em>cedis </em>deberá ser menor o igual a 1000. Esto significa que la cantidad enviada desde el nodo (planta) <em>0 </em>hacia los destinos <em>j (Denver y Miami) </em>no puede ser mayor que su disponibilidad de automóviles.</p>
<h3>Crear la función objetivo</h3>
<p>Tal como lo planteamos desde la formulación del problema, el criterio de optimización des este modelo corresponde a minimizar el costo total de distribución. El siguiente fragmento calcula el producto entre cada variable x[i, j] y su respectivo costo c[i, j] (obtenida desde la matriz de costos). La sumatoria de productos corresponde a la ecuación objetivo.</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>for i in range(num_plantas):
    for j in range(num_cedis):
        objective_terms.append(costos[i][j] * x[i, j])
solver.Minimize(solver.Sum(objective_terms))</code></pre>
</div>
<p>Luego se declara el criterio de optimización: <em>Minimize </em>(para minimizar) y <em>Maximize </em>(para maximizar). En este caso minimizará la sumatoria de los productos.</p>
<h3>Invocar al solucionador</h3>
<p>La siguiente línea indica que el modelo debe solucionarse.</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>status = solver.Solve()</code></pre>
</div>
<h3>Configurar las salidas del modelo</h3>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>if status == pywraplp.Solver.OPTIMAL or status == pywraplp.Solver.FEASIBLE:
    print('Costo total = ', solver.Objective().Value(), '\n')

    for i in range(num_plantas):
        for j in range(num_cedis):
            print('|Planta {} -&gt; Cedi {} - Cantidad: {}|'.format(
            i,
            j,
            x[i, j].solution_value()))</code></pre>
</div>
<p>En el caso en el que el modelo encuentre una solución óptima, hemos configurado las salidas de tal manera que nos muestre la relación solución entre fuentes &gt; destinos y cantidades. Al ejecutar el modelo obtendremos la siguiente solución:</p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2021/08/transporte-solucion-asignacion.png" alt="" width="425" height="153" class="aligncenter size-full wp-image-26842" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2021/08/transporte-solucion-asignacion.png 425w, https://ingenieriaindustrialonline.com/wp-content/uploads/2021/08/transporte-solucion-asignacion-300x108.png 300w" sizes="(max-width: 425px) 100vw, 425px" /></p>
<p>Podemos también detallar mucho mejor las salidas del modelo, de acuerdo al nombre de las plantas y los cedis. Para ello, en la data de entrada creamos las listas correspondientes, veamos:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>costos = [
    [ 80, 215],
    [100, 108],
    [102,  68],
]

num_plantas = len(costos)
num_cedis = len(costos[0])

plantas = ['Los Ángeles', 'Detroit', 'New Orleans']
cedis = ['Denver', 'Miami']</code></pre>
</div>
<p>La información de las listas debe guardar correspondencia con el orden de la matriz de costos.</p>
<p>Ahora, configuramos nuevamente las salidas del modelo:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>if status == pywraplp.Solver.OPTIMAL or status == pywraplp.Solver.FEASIBLE:
    print('Costo total = ', solver.Objective().Value(), '\n')

    for i in range(num_plantas):
        for j in range(num_cedis):
            print('|{:^20} -&gt; {:^20} | Cantidad: {:^20}|'.format(
            plantas[i],
            cedis[j],
            x[i, j].solution_value()))</code></pre>
</div>
<p>En este caso hemos remplazado el índice solo de plantas y cedis, por el índice dentro del listado de plantas y cedis. Así entonces, tendremos la siguiente salida del modelo:</p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2021/08/transporte-solucion-asignacion_2.png" alt="" width="663" height="158" class="aligncenter size-full wp-image-26843" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2021/08/transporte-solucion-asignacion_2.png 663w, https://ingenieriaindustrialonline.com/wp-content/uploads/2021/08/transporte-solucion-asignacion_2-300x71.png 300w" sizes="(max-width: 663px) 100vw, 663px" /></p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2021/08/modelo-de-transporte-solucion-de-red.png" alt="" width="482" height="401" class="aligncenter size-full wp-image-26844" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2021/08/modelo-de-transporte-solucion-de-red.png 482w, https://ingenieriaindustrialonline.com/wp-content/uploads/2021/08/modelo-de-transporte-solucion-de-red-300x250.png 300w" sizes="(max-width: 482px) 100vw, 482px" /></p>
<p>Pueden cotejar los resultados obtenidos los cuales corresponden a los mismos resultados presentados por <em>Taha, quien utiliza </em>TORA como solucionador.</p>
<hr />
<h2>¿Cómo ejecutar el modelo?
		<div id="como-ejecutar-el-modelo" data-title="¿Cómo ejecutar el modelo?" class="index-title"></div>
	</h2>
<p><em><strong>Alternativa 1, ejecución en nuestro equipo:</strong></em></p>
<p>Lo primero que debemos considerar, en el caso de que queramos ejecutar este código en nuestro equipo, es que es preciso contar con la instalación de <em>Python </em>en nuestro equipo de cómputo y por supuesto, el software <em>OR-Tools.</em> Una guía detallada de la instalación de estos requerimientos la podrás encontrar en el siguiente enlace:</p>
<p style="text-align: center;"><a href="https://developers.google.com/optimization/install/python/windows" target="_blank" class="shortc-button medium blue">Instalación de OR-Tools para Python</a>
<p>Ahora, lo recomendable es trabajar con algún editor de código práctico (IDE), por ejemplo: <a href="https://www.sublimetext.com/3"><strong><em>Sublime Text</em></strong></a>, o <em><strong>Spyder</strong></em> (Una herramienta más completa y por ende más robusta y pesada).</p>
<p><em><strong>Alternativa 2, ejecución en un entorno virtual (Recomendado):</strong></em></p>
<p>Podemos utilizar del mismo modo, un entorno virtual. En este caso recomendamos el uso de <em><strong>Colaboratory de Google</strong></em>, un entorno que cuenta con todas las herramientas necesarias para nuestros desarrollos. No tendremos que instalar nada en nuestro equipo, y aprovecharemos la potencia de las máquinas de Google.</p>
<hr />
<p>El código completo de nuestro desarrollo lo presentamos a continuación.</p>

		<div class="box info  ">
			<div class="box-inner-block">
				<span class="fa tie-shortcode-boxicon"></span>También puedes ver el cuaderno de este módulo en nuestro <em>Colaboratory: <a href="https://colab.research.google.com/drive/1a4ctY8P8XuP_XDLy4tGuwFe8vpQLYRtK?usp=sharing"><strong>Transporte mediante asignación</strong></a>.</em>
			</div>
		</div>
	
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code># Importar la librería de Google OR-Tools
from ortools.linear_solver import pywraplp

# Declarar el solucionador que abordará el modelo
solver = pywraplp.Solver.CreateSolver('SCIP')

# Data del modelo
costos = [
    [ 80, 215],
    [100, 108],
    [102,  68],
]

plantas = ['Los Ángeles', 'Detroit', 'New Orleans']
cedis = ['Denver', 'Miami']

num_plantas = len(costos)
num_cedis = len(costos[0])

# Variables del modelo
x = {}
for i in range(num_plantas):
    for j in range(num_cedis):
        x[i, j] = solver.IntVar(0, solver.infinity(), '')
        
#Restricciones de disponibilidad (oferta en plantas) 
solver.Add(solver.Sum([x[0, j] for j in range(num_cedis)]) &lt;= 1000) 
solver.Add(solver.Sum([x[1, j] for j in range(num_cedis)]) &lt;= 1500) 
solver.Add(solver.Sum([x[2, j] for j in range(num_cedis)]) &lt;= 1200) 

#Restricciones de demanda (cedis) 
solver.Add(solver.Sum([x[i, 0] for i in range(num_plantas)]) &gt;= 2300) 
solver.Add(solver.Sum([x[i, 1] for i in range(num_plantas)]) &gt;= 1400)      



# Función objetivo con criterio de optimización: minimizar
objective_terms = []
for i in range(num_plantas):
    for j in range(num_cedis):
        objective_terms.append(costos[i][j] * x[i, j])

solver.Minimize(solver.Sum(objective_terms))

# Invoca el solucionador
status = solver.Solve()

# Configura los parámetros de impresión, las salidas del modelo
if status == pywraplp.Solver.OPTIMAL or status == pywraplp.Solver.FEASIBLE:
    print('Costo total = ', solver.Objective().Value(), '\n')

    for i in range(num_plantas):
        for j in range(num_cedis):
            print('|{:^20} -&gt; {:^20} | Cantidad: {:^20}|'.format(
            plantas[i],
            cedis[j],
            x[i, j].solution_value()))</code></pre>
</div>
<hr />
<p>También es posible integrar nuestro desarrollo con data proveniente de fuentes externas, como por ejemplo Excel.</p>
<p>En próximos artículos, resolveremos el problema de transporte básico mediante un algoritmo de flujo mínimo.</p>
<p>La entrada <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/solucion-de-un-modelo-de-transporte-mediante-un-algoritmo-de-asignacion/">Solución de un modelo de transporte mediante un algoritmo de asignación</a> se publicó primero en <a href="https://ingenieriaindustrialonline.com">Ingenieria Industrial Online</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ingenieriaindustrialonline.com/investigacion-de-operaciones/solucion-de-un-modelo-de-transporte-mediante-un-algoritmo-de-asignacion/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Problemas de asignación en Google OR-Tools</title>
		<link>https://ingenieriaindustrialonline.com/investigacion-de-operaciones/problemas-de-asignacion-en-google-or-tools/</link>
					<comments>https://ingenieriaindustrialonline.com/investigacion-de-operaciones/problemas-de-asignacion-en-google-or-tools/#respond</comments>
		
		<dc:creator><![CDATA[Bryan Salazar López]]></dc:creator>
		<pubDate>Thu, 15 Apr 2021 00:20:49 +0000</pubDate>
				<category><![CDATA[Investigación de operaciones]]></category>
		<category><![CDATA[Google OR-Tools]]></category>
		<category><![CDATA[Investigación de Operaciones]]></category>
		<category><![CDATA[Problema de asignación]]></category>
		<category><![CDATA[Problema de transporte]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://ingenieriaindustrialonline.com/?p=25366</guid>

					<description><![CDATA[<p>Tal como se ha abordado en artículos anteriores, dentro de la investigación de operaciones, el problema de asignación corresponde a una variación del problema original de transporte. Es uno de los problemas de optimización combinatoria más popularizados debido a su alto grado de aplicación práctica. Suponga que es necesario llevar a cabo un conjunto de &#8230;</p>
<p>La entrada <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/problemas-de-asignacion-en-google-or-tools/">Problemas de asignación en Google OR-Tools</a> se publicó primero en <a href="https://ingenieriaindustrialonline.com">Ingenieria Industrial Online</a>.</p>
]]></description>
										<content:encoded><![CDATA[
		<div id="introduccion" data-title="Introducción" class="index-title"></div>
	
<p>Tal como se ha abordado en artículos anteriores, dentro de la investigación de operaciones, el <em><strong><a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/problemas-de-asignacion/">problema de asignación</a></strong></em> corresponde a una variación del <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/solucion-de-un-modelo-de-transporte-mediante-un-algoritmo-de-asignacion/"><strong>problema original de transporte</strong></a>. Es uno de los problemas de optimización combinatoria más popularizados debido a su alto grado de aplicación práctica.</p>
<p>Suponga que es necesario llevar a cabo un conjunto de tareas, y que para ello se cuenta con un conjunto de operarios; además, cada trabajador en particular ejecutando una tarea en particular tiene un costo específico. Pues bien, el problema consiste en asignar a cada trabajador como máximo una tarea específica, sin que dos trabajadores puedan realizar la misma tarea, mientras se minimiza el costo total.</p>
<p><span>En el </span><strong>modelo de asignación, </strong><span>la idea fundamental de resolución es </span><em><b>¿Qué conjunto de fuentes satisface mejor el conjunto de destinos?</b></em></p>
<p>En artículos anteriores hemos planteado la resolución de problemas de asignación mediante el método húngaro (manual) y mediante programación lineal, haciendo uso de WinQSB.</p>
<p>El objetivo de este artículo consiste en utilizar las librerías del software Google OR-Tools para abordar un problema de asignación clásico y una variación del modelo mediante un criterio de maximización.</p>
<h2>El problema</h2>
<p>Con el propósito de evaluar los resultados obtenidos mediante distintos métodos y solucionadores, utilizaremos el mismo problema que abordamos mediante el <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/problemas-de-asignacion/"><strong>método húngaro</strong></a>.</p>
<blockquote class=" quote-simple "><p>La compañía de manufactura «Jiménez y Asociados» desea realizar una jornada de mantenimiento preventivo a sus tres máquinas principales A, B y C. El tiempo que demanda realizar el mantenimiento de cada máquina es de 1 día, sin embargo la jornada de mantenimiento no puede durar más de un día, teniendo en cuenta que la compañía cuenta con tres proveedores de servicios de mantenimiento debe de asignarse un equipo de mantenimiento a cada máquina para poder cumplir con la realización del mantenimiento preventivo. Teniendo en cuenta que según el grado de especialización de cada equipo prestador de servicios de mantenimiento el costo de la tarea varía para cada máquina en particular, debe de asignarse el equipo correcto a la máquina indicada con el objetivo de minimizar el costo total de la jornada. Los costos asociados se pueden observar en la siguiente tabla:</p></blockquote>
<p><em><strong>Tabla 1</strong></em></p>
<table width="421">
<tbody>
<tr>
<td width="181" style="text-align: center;"></td>
<td width="80" style="text-align: center;"><strong>Máquina 0</strong></td>
<td width="80" style="text-align: center;"><strong>Máquina 1</strong></td>
<td width="80" style="text-align: center;"><strong>Máquina 2</strong></td>
</tr>
<tr>
<td style="text-align: center;"><strong>Equipo de mantenimiento 0</strong></td>
<td style="text-align: center;">10</td>
<td style="text-align: center;">9</td>
<td style="text-align: center;">5</td>
</tr>
<tr>
<td style="text-align: center;"><strong>Equipo de mantenimiento 1</strong></td>
<td style="text-align: center;">9</td>
<td style="text-align: center;">8</td>
<td style="text-align: center;">3</td>
</tr>
<tr>
<td style="text-align: center;"><strong>Equipo de mantenimiento 2</strong></td>
<td style="text-align: center;">6</td>
<td style="text-align: center;">4</td>
<td style="text-align: center;">7</td>
</tr>
</tbody>
</table>
<h2>
		<div id="resolviendo-un-problema-de-asignacion-mediante-google-or-tools" data-title="Resolviendo un problema de asignación mediante Google OR-Tools" class="index-title"></div>
	Resolviendo un problema de asignación mediante Google OR-Tools</h2>
<p>De acuerdo a lo mencionado en el artículo de <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/que-es-y-para-que-sirve-google-or-tools/"><strong>introducción a Google OR-Tools</strong></a>, esta herramienta soporta múltiples lenguajes de programación, así entonces, haremos uso del lenguaje de programación Python.</p>
<p>Del mismo modo, OR-Tools cuenta con un par de solucionadores para abordar problemas de asignación:</p>

		<div class="checklist tie-list-shortcode">
<ul>
<li>MIP</li>
<li>CP-SAT</li>
</ul>

		</div>
	
<p>En este caso, utilizaremos el solucionador MIP.</p>
<h3><em>Paso 1: Importar la librería
		<div id="paso-1-importar-la-libreria" data-title="Paso 1: Importar la librería" class="index-title"></div>
	</em></h3>
<p>El siguiente fragmento de código importa las librerías necesarias:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code># Importar la librería de Google OR-Tools
from<span class="pln"> ortools</span><span class="pun">.</span><span class="pln">linear_solver </span><span class="kwd">import</span><span class="pln"> pywraplp</span></code></pre>
</div>
<h3><em>Paso 2: Declarar el solucionador (MIP)
		<div id="paso-2-declarar-el-solucionador-mip" data-title="Paso 2: Declarar el solucionador (MIP)" class="index-title"></div>
	</em></h3>
<p>El siguiente fragmento de código declara el solucionador mediante el que se abordará el problema:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code># Declarar el solucionador que abordará el modelo
<span class="pln">solver = pywraplp.Solver.CreateSolver('SCIP')</span></code></pre>
</div>
<h3><em>Paso 3: Crear la data del modelo
		<div id="paso-3-crear-la-data-del-modelo" data-title="Paso 3: Crear la data del modelo" class="index-title"></div>
	</em></h3>
<p>El siguiente fragmento de código crea la data del modelo de asignación:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code># Crear la data del modelo de asignación
<span class="pln">costs = [
    [10, 9, 5],
    [9, 8, 3],
    [6, 4, 7],
]
num_teams = len(costs)
num_machines = len(costs[0])</span></code></pre>
</div>
<p>La matriz de costos corresponde a los valores de la <em><strong>tabla 1</strong></em> para asignar los equipos de mantenimiento a las máquinas.</p>
<p>El número de equipos de mantenimiento y el número de máquinas (tareas) los calcula mediante la función <em>len </em> a partir de la matriz de costos. En un sentido práctico, cuenta el número de elementos de la matriz.</p>
<h3><em>Paso 4: Crear las variables
		<div id="paso-4-crear-las-variables" data-title="Paso 4: Crear las variables" class="index-title"></div>
	</em></h3>
<p>El siguiente fragmento de código crea las variables binarias enteras del problema de asignación (x[i, j]):</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code># x[i, j] es una matriz de variables binarias 0-1, que será 1
# si un equipo de mantenimiento i es asignado a la máquina j.
<span class="pln">x = {}
for i in range(num_teams):
    for j in range(num_machines):
        x[i, j] = solver.IntVar(0, 1, '')</span></code></pre>
</div>
<h3><em>Paso 5: Crear las restricciones
		<div id="paso-5-crear-las-restricciones" data-title="Paso 5: Crear las restricciones" class="index-title"></div>
	</em></h3>
<p>El siguiente fragmento de código crea las restricciones del problema de asignación:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code># Cada equipo de mtto. podrá ser asignado a un máximo de una máquina
for i in range(num_teams):
<span class="pln">    solver.Add(solver.Sum([x[i, j] for j in range(num_machines)]) &lt;= 1)
# Cada máquina será asignada exactamente a un equipo de mantenimiento
for j in range(num_machines):
    solver.Add(solver.Sum([x[i, j] for i in range(num_teams)]) == 1)
</span></code></pre>
</div>
<h3><em>Paso 6: Crear la función objetivo
		<div id="paso-6-crear-la-funcion-objetivo" data-title="Paso 6: Crear la función objetivo" class="index-title"></div>
	</em></h3>
<p>El siguiente fragmento de código crea la función objetivo con un criterio de optimización <em><strong>minimizar</strong></em></p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code># Función objetivo con criterio de optimización: minimizar
objective_terms = []
<span class="pln">for i in range(num_teams):
    for j in range(num_machines):
        objective_terms.append(costs[i][j] * x[i, j])
solver.Minimize(solver.Sum(objective_terms))
</span></code></pre>
</div>
<h3><em>Paso 7: Invocar el solucionador
		<div id="paso-7-invocar-el-solucionador" data-title="Paso 7: Invocar el solucionador" class="index-title"></div>
	</em></h3>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code># Invoca el solucionador
<span class="pln">status = solver.Solve()
</span></code></pre>
</div>
<h3><em>Paso 8: Imprimir la solución
		<div id="paso-8-imprimir-la-solucion" data-title="Paso 8: Imprimir la solución" class="index-title"></div>
	</em></h3>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code># Configura los parámetros de impresión, las salidas del modelo
<span class="pln">if status == pywraplp.Solver.OPTIMAL or status == pywraplp.Solver.FEASIBLE:
    print('Costo total = ', solver.Objective().Value(), '\n')
    for i in range(num_teams):
        for j in range(num_machines):
            # Test if x[i,j] is 1 (con tolerancia de punto flotante)
            if x[i, j].solution_value() &gt; 0.5:
                print('Equipo %d asignado a la máquina %d. Costo = %d' %
                      (i, j, costs[i][j]))
</span></code></pre>
</div>
<hr />
<p>Es posible que el desarrollo de los ocho pasos anteriores demande algún grado de complejidad subyacente del uso de un lenguaje de programación; sin embargo, es preciso mencionar que, el modelo anterior queda perfectamente configurado, y puede replicarse con modificaciones menores en múltiples problemas de asignación.</p>
<h2>¿Cómo ejecutar el modelo?
		<div id="como-ejecutar-el-modelo" data-title="¿Cómo ejecutar el modelo?" class="index-title"></div>
	</h2>
<p><em><strong>Alternativa 1, ejecución en nuestro equipo:</strong></em></p>
<p>Lo primero que debemos considerar, en el caso de que queramos ejecutar este código en nuestro equipo, es que es preciso contar con la instalación de <em>Python </em>en nuestro equipo de cómputo, así mismo debemos contar con la última versión del comando <em>pip</em> y por supuesto, el software <em>OR-Tools.</em> Una guía detallada de la instalación de estos requerimientos la podrás encontrar en el siguiente enlace:</p>
<p style="text-align: center;"><a href="https://developers.google.com/optimization/install/python/windows" target="_blank" class="shortc-button medium blue">Instalación de OR-Tools para Python</a>
<p>Ahora, lo recomendable es trabajar con algún editor de código práctico (IDE), por ejemplo: <a href="https://www.sublimetext.com/3"><strong><em>Sublime Text</em></strong></a>, o <em><strong>Spyder</strong></em> (Una herramienta más completa y por ende más robusta y pesada).</p>
<p><em><strong>Alternativa 2, ejecución en un entorno virtual (Recomendado):</strong></em></p>
<p>Podemos utilizar del mismo modo, un entorno virtual. En este caso recomendamos el uso de <em><strong>Colaboratory de Google</strong></em>, un entorno que cuenta con todas las herramientas necesarias para nuestros desarrollos. No tendremos que instalar nada en nuestro equipo, y aprovecharemos la potencia de las máquinas de Google.</p>
<hr />
<p>El código completo de nuestro desarrollo lo presentamos a continuación. También puedes ver el cuaderno de este módulo en nuestro <em>Colaboratory: <a href="https://colab.research.google.com/drive/1iY-IXyaM-uMT9JovuZdMlID4DI2iIl3V?usp=sharing"><strong>Asignación</strong></a>.</em></p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code><span class="pln"># Importar la librería de Google OR-Tools
from ortools<span class="pun">.</span>linear_solver <span class="kwd">import</span> pywraplp

# Declarar el solucionador que abordará el modelo
solver = pywraplp.Solver.CreateSolver('SCIP')

# Data del modelo
costs = [
    [10, 9, 5],
    [9, 8, 3],
    [6, 4, 7],
]
num_teams = len(costs)
num_machines = len(costs[0])

# Variables del modelo
x = {}
for i in range(num_teams):
    for j in range(num_machines):
        x[i, j] = solver.IntVar(0, 1, '')

# Restricciones del modelo
for i in range(num_teams):
    solver.Add(solver.Sum([x[i, j] for j in range(num_machines)]) &lt;= 1)
# Cada máquina será asignada exactamente a un equipo de mantenimiento
for j in range(num_machines):
    solver.Add(solver.Sum([x[i, j] for i in range(num_teams)]) == 1)

# Función objetivo con criterio de optimización: minimizar
objective_terms = []
for i in range(num_teams):
    for j in range(num_machines):
        objective_terms.append(costs[i][j] * x[i, j])
solver.Minimize(solver.Sum(objective_terms))

# Invoca el solucionador
status = solver.Solve()

# Configura los parámetros de impresión, las salidas del modelo
if status == pywraplp.Solver.OPTIMAL or status == pywraplp.Solver.FEASIBLE:
    print('Costo total = ', solver.Objective().Value(), '\n')
    for i in range(num_teams):
        for j in range(num_machines):
            # Test if x[i,j] is 1 (con tolerancia de punto flotante)
            if x[i, j].solution_value() &gt; 0.5:
                print('Equipo %d asignado a la máquina %d. Costo = %d' %
                      (i, j, costs[i][j]))
</span></code></pre>
</div>
<p><em>Ejecutamos:</em></p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2021/04/asignacion_min_solucion.png" alt="asignacion_min_solucion" width="639" height="108" class="aligncenter size-full wp-image-26358" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2021/04/asignacion_min_solucion.png 639w, https://ingenieriaindustrialonline.com/wp-content/uploads/2021/04/asignacion_min_solucion-300x51.png 300w" sizes="(max-width: 639px) 100vw, 639px" /></p>
<p>Y bien, tenemos la solución a este problema simple de asignación en menos de 1 segundo.</p>
<hr />
<p>Podemos observar que se ha obtenido la misma respuesta que la lograda mediante el <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/problemas-de-asignacion/"><strong><em>método húngaro </em></strong>y <em><strong>programación lineal (WinQSB)</strong></em></a><em>.</em></p>
<p>Ahora bien, el modelo de asignación y el <em>script </em>del solucionador quedaron desarrollados en un lenguaje de programación estándar y ampliamente utilizado. Desde luego, las posibilidades de integrar datos de entrada y procesar los datos de salidas son interesantes. Por ejemplo, es posible desarrollar un <em>script </em>mediante el cual el código ya desarrollado tome los datos de entrada desde un archivo de Excel, o desde un servidor externo.</p>
<p>También, es posible desarrollar una interfaz amigable desde la cual se ingrese la información; o vincular los datos de salida con algún modelo o documento determinado.</p>
<hr />
<p>Ahora, podemos evidenciar una de las bondades de este tipo de modelamiento, y es la flexibilidad. Pues bien, vamos a modificar muy fácilmente la información de entrada y el criterio de optimización, para desarrollar un modelo de asignación cuyo criterio sea maximizar. Para ello, vamos a abordar un problema de asignación planteado anteriormente, con el propósito de contrastar los resultados.</p>
<h2>Modelamiento y solución de un problema de maximización mediante Google OR-Tools
		<div id="modelamiento-y-solucion-de-un-problema-de-maximizacion-mediante-google-or-tools" data-title="Modelamiento y solución de un problema de maximización mediante Google OR-Tools" class="index-title"></div>
	</h2>
<h3><em>El problema</em></h3>
<blockquote class=" quote-simple "><p>Una organización de recolección de café cuenta con tres equipos de siembra y cosecha del mismo (equipos 1, 2, 3). Estos equipos de trabajo se encuentran entrenados para trabajar en condiciones particulares del proceso, condiciones como lo son el tipo de suelo, las condiciones del clima y el tipo de grano. La organización cuenta con cuatro terrenos disponibles para efectuar el proceso de siembra y cosecha (terrenos A, B, C, D), estos terrenos tienen condiciones particulares de suelo, clima y tipo de grano. Cada equipo cuenta con la capacidad de efectuar el proceso en solo uno de los terrenos disponibles, salvo el equipo 2, que cuenta con una serie de herramientas tecnológicas que le permiten realizar la siembra y cosecha del grano en dos de los terrenos disponibles.</p></blockquote>
<p><em>Se ha contratado a un Ingeniero Industrial con el objetivo de realizar las asignaciones precisas que maximicen la cantidad de sacos de café cosechados en total. El siguiente tabulado muestra la capacidad (en cientos de sacos) de cosecha de café de cada uno de los equipos dependiendo de cada uno de los terrenos.</em></p>
<p>Dado que existe un equipo que cuenta con la capacidad de trabajar en dos de los terrenos disponibles (desarrollar dos tareas), renombraremos los equipos partiendo desde el 0, así mismo los terrenos, y el equipo 1 y 2 corresponderán a una misma flotilla (misma capacidad de producción) que puede desarrollar dos tareas (atender dos terrenos). Así entonces, el tabulado con las capacidades de producción se muestra a acontinuación:</p>
<p><em><strong>Tabla 2</strong></em></p>
<div class="code-block code-block-2">
<table width="501">
<tbody>
<tr>
<td width="80" style="text-align: center;"><strong></strong></td>
<td width="80" style="text-align: center;"><strong>Terreno 0</strong></td>
<td width="80" style="text-align: center;"><strong>Terreno 1</strong></td>
<td width="80" style="text-align: center;"><strong>Terreno 2</strong></td>
<td width="80" style="text-align: center;"><strong>Terreno 3</strong></td>
</tr>
<tr>
<td style="text-align: center;"><strong>Equipo 0</strong></td>
<td style="text-align: center;">13</td>
<td style="text-align: center;">7</td>
<td style="text-align: center;">12</td>
<td style="text-align: center;">12</td>
</tr>
<tr>
<td style="text-align: center;"><strong>Equipo 1</strong></td>
<td style="text-align: center;">10</td>
<td style="text-align: center;">13</td>
<td style="text-align: center;">15</td>
<td style="text-align: center;">7</td>
</tr>
<tr>
<td style="text-align: center;"><strong>Equipo 2</strong></td>
<td style="text-align: center;">10</td>
<td style="text-align: center;">13</td>
<td style="text-align: center;">15</td>
<td style="text-align: center;">7</td>
</tr>
<tr>
<td style="text-align: center;"><strong>Equipo 3</strong></td>
<td style="text-align: center;">13</td>
<td style="text-align: center;">10</td>
<td style="text-align: center;">8</td>
<td style="text-align: center;">8</td>
</tr>
</tbody>
</table>
<h2>Modelamiento</h2>
<p>Dado que el modelo que desarrollamos anteriormente puede mantenerse en esencia, vamos a detallar las modificaciones que precisa:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code># Crear la data del modelo de asignación
<span class="pln">capacidad = [
    [13, 7, 12, 12],
    [10, 13, 15, 7],
    [10, 13, 15, 7],
    [13, 10, 8, 8],
]
num_equipos = len(capacidad)
num_terrenos = len(capacidad[0])</span></code></pre>
</div>
<p>Evidentemente, la matriz del modelo varía de acuerdo al problema, y, en este caso, queremos renombrar las variables de acuerdo al problema planteado.</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code># Función objetivo con criterio de optimización: maximizar
objective_terms = []
<span class="pln">for i in range(num_equipos):
    for j in range(num_terrenos):
        objective_terms.append(capacidad[i][j] * x[i, j])
solver.Maximize(solver.Sum(objective_terms))
</span></code></pre>
</div>
<p>Salvo ajustes de forma, vemos como en el anterior fragmento se modifica el criterio de la optimización: <em>Solver.Maximize</em>. Así entonces, el modelo estaría listo para entregar resultados.</p>
</div>
<p>El código completo, con algunas modificaciones de acuerdo al renombre de las variables y a los textos que acompañarán los resultados se presenta a continuación (también puedes encontrarlo en nuestro <em><a href="https://colab.research.google.com/drive/1wl4aU3Uu71QqNuIQvK89GqczXd6RKylq?usp=sharing">Colaboratory</a>)</em>:</p>
<div class="code-block code-block-2">
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code><span class="pln"># Importar la librería de Google OR-Tools
from ortools<span class="pun">.</span>linear_solver <span class="kwd">import</span> pywraplp

# Declarar el solucionador que abordará el modelo
solver = pywraplp.Solver.CreateSolver('SCIP')

# Data del modelo
capacidad = [ 
[13, 7, 12, 12], 
[10, 13, 15, 7], 
[10, 13, 15, 7],
[13, 10, 8, 8], 
] 
num_equipos = len(capacidad) 
num_terrenos = len(capacidad[0])

# Variables del modelo
x = {}
for i in range(num_equipos):
    for j in range(num_terrenos):
        x[i, j] = solver.IntVar(0, 1, '')

# Restricciones del modelo
for i in range(num_equipos):
    solver.Add(solver.Sum([x[i, j] for j in range(num_terrenos)]) &lt;= 1)

for j in range(num_terrenos):
    solver.Add(solver.Sum([x[i, j] for i in range(num_equipos)]) == 1)

# Función objetivo con criterio de optimización: maximizar
objective_terms = []
for i in range(num_equipos):
    for j in range(num_terrenos):
        objective_terms.append(capacidad[i][j] * x[i, j])
solver.Maximize(solver.Sum(objective_terms))

# Invoca el solucionador
status = solver.Solve()

# Configura los parámetros de impresión, las salidas del modelo
if status == pywraplp.Solver.OPTIMAL or status == pywraplp.Solver.FEASIBLE:
    print('Producción total = ', solver.Objective().Value(), '\n')
    for i in range(num_equipos):
        for j in range(num_terrenos):
            # Test if x[i,j] is 1 (con tolerancia de punto flotante)
            if x[i, j].solution_value() &gt; 0.5:
                print('Equipo %d asignado al terreno %d. Producción = %d' %
                      (i, j, capacidad[i][j]))
</span></code></pre>
</div>
<p><em>Ejecutamos el modelo:</em></p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2021/04/asignacion_max_solucion.png" alt="asignacion_max_solucion" width="629" height="125" class="aligncenter size-full wp-image-26359" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2021/04/asignacion_max_solucion.png 629w, https://ingenieriaindustrialonline.com/wp-content/uploads/2021/04/asignacion_max_solucion-300x60.png 300w" sizes="(max-width: 629px) 100vw, 629px" /></p>
<p>Podemos observar que se ha obtenido la misma respuesta que la lograda mediante el <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/problemas-de-asignacion/"><strong><em>método húngaro </em></strong>y <em><strong>programación lineal (WinQSB)</strong></em></a><em>.</em></p>
<hr />
<p>De esta manera se evidencia una de las ventajas del modelamiento haciendo uso de Google OR-Tools, puesto que, podemos pasar de modelar un problema a otro mediante la modificación mínima de los datos de entrada. Del mismo modo, podemos modificar criterios de optimización con suma facilidad, y realizar modificaciones de forma que en algunos casos pueden ser relevantes.</p>
<p>En próximos artículos abordaremos algunos <em>scripts </em>básicos en <em>Python </em>que permitan integrar el modelo de optimización con la data contenida en otros formatos; así mismo revisaremos algunas funciones que nos permiten organizar y exportar los resultados del solucionador.</p>
</div>
<p>La entrada <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/problemas-de-asignacion-en-google-or-tools/">Problemas de asignación en Google OR-Tools</a> se publicó primero en <a href="https://ingenieriaindustrialonline.com">Ingenieria Industrial Online</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ingenieriaindustrialonline.com/investigacion-de-operaciones/problemas-de-asignacion-en-google-or-tools/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Problemas de asignación</title>
		<link>https://ingenieriaindustrialonline.com/investigacion-de-operaciones/problemas-de-asignacion/</link>
					<comments>https://ingenieriaindustrialonline.com/investigacion-de-operaciones/problemas-de-asignacion/#comments</comments>
		
		<dc:creator><![CDATA[Bryan Salazar López]]></dc:creator>
		<pubDate>Wed, 12 Jun 2019 20:52:09 +0000</pubDate>
				<category><![CDATA[Investigación de operaciones]]></category>
		<category><![CDATA[Problema de asignación]]></category>
		<category><![CDATA[Problema de transporte]]></category>
		<category><![CDATA[Teoría de redes]]></category>
		<category><![CDATA[WinQSB]]></category>
		<guid isPermaLink="false">http://contentlab.co/ingenieria/?p=1246</guid>

					<description><![CDATA[<p>El problema de asignación es una variación del problema original de transporte, variación en la cual las variables de decisión X(i,j) solo pueden tomar valores binarios, es decir ser cero (0) o uno (1), en la solución óptima, lo que supone que la oferta y la demanda están perfectamente alineadas, de hecho ambas son iguales a uno (1). &#8230;</p>
<p>La entrada <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/problemas-de-asignacion/">Problemas de asignación</a> se publicó primero en <a href="https://ingenieriaindustrialonline.com">Ingenieria Industrial Online</a>.</p>
]]></description>
										<content:encoded><![CDATA[
		<div id="problema-de-asignacion" data-title="Problema de asignación" class="index-title"></div>
	El <strong>problema de asignación</strong> es una variación del <em><strong><a class="" title="Problema del Transporte o Distribución" href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/problema-del-transporte-o-distribucion/">problema original de transporte</a></strong></em>, variación en la cual las variables de decisión X(i,j) solo pueden tomar valores binarios, es decir ser cero (0) o uno (1), en la solución óptima, lo que supone que la oferta y la demanda están perfectamente alineadas, de hecho ambas son iguales a uno (1).</p>
<p>Múltiples son los casos en los que como ingenieros industriales podemos hacer uso del problema de asignación para resolver diversas situaciones, entre los que cabe mencionar se encuentran la asignación de personal a maquinas, herramientas a puestos de trabajos, horarios a maestros, candidatos a vacantes, huéspedes a habitaciones, comensales a mesas, vendedores a zonas territoriales etc.</p>
<div id="cc-m-2964799413" class="j-module n j-text ">
<p>En el <strong>modelo de asignación,</strong> la idea fundamental de resolución es <em><b>¿Qué fuente satisface mejor el destino?</b></em>, y dado que hemos asociado el modelo a una gran diversidad de circunstancias esta pregunta puede plantearse en múltiples contextos, como ¿Qué candidato es el idóneo para la vacante?, o ¿Qué personal es el indicado para la línea productiva?, o ¿Qué personal es el mejor para ejecutar determinada tarea?. Una característica particular del modelo de asignación es que para su resolución no se hace necesario que el número de fuentes sea igual al número de destinos, lo cual es muy común en la vida real, teniendo en cuenta su aplicación, pues generalmente la cantidad de aspirantes es superior al número de vacantes (lógicamente haciendo referencia a la aplicación del modelo al contexto de oferta y demanda laboral).</p>

		<div class="clearfix"></div>
		<hr style="margin-top:20px; margin-bottom:20px;" class="divider divider-solid">
	
<h2>
		<div id="metodo-hungaro" data-title="Método Húngaro" class="index-title"></div>
	Método Húngaro</h2>
<p>Apartándonos un poco de la idea expresada en módulos anteriores respecto a la facilidad de resolver problemas atinentes a la investigación operativa en especial aquellos de transporte mediante el uso de herramientas tecnológicas como lo son WinQSB, LINGO, TORA, STORM, Excel, <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/problemas-de-asignacion-en-google-or-tools/"><strong>Or Tools</strong></a>, etc.. vale la pena ya sea para fines académicos o de cultura ingenieril realizar la resolución del problema de asignación mediante el algoritmo que se creó para tal fin, como lo es el <strong>Método Húngaro</strong>.</p>
</div>
<div id="cc-m-5678944213" class="j-module n j-spacing ">
		<div class="box info  alignleft">
			<div class="box-inner-block">
				<span class="fa tie-shortcode-boxicon"></span>El método Húngaro es un método de optimización de problemas de asignación, conocido como tal gracias a que los primeros aportes al método clásico definitivo fueron de <strong>Dénes König</strong> y <strong>Jenő Egerváry</strong> dos matemáticos húngaros. El algoritmo tal como se detallará a continuación está diseñado para la resolución de problemas de minimización únicamente, será entonces cuestión de agregar un paso adicional para abordar ejercicios de maximización.
			</div>
		</div>
	</div>
<div></div>
<div>
<div id="cc-m-2964801813" class="j-module n j-header ">
<h3 id="cc-m-header-2964801813" class=""><em>Paso 1</em></h3>
</div>
<div id="cc-m-2964802613" class="j-module n j-text ">
<p>Antes que nada cabe recordar que el método húngaro trabaja en una matriz de costos n*m (en este caso conocida como matriz m*m, dado que el número de filas es igual al número de columnas n = m), una vez construida esta se debe encontrar el elemento más pequeño en cada fila de la matriz.</p>
</div>
<div id="cc-m-2964802713" class="j-module n j-header ">
<h3 id="cc-m-header-2964802713" class=""><em>Paso 2</em></h3>
</div>
<div id="cc-m-2964802813" class="j-module n j-text ">
<p>Una vez se cumple el procedimiento anterior se debe construir una nueva matriz n*m, en la cual se consignarán los valores resultantes de la diferencia entre cada costo y el valor mínimo de la fila a la cual cada costo corresponde (valor mínimo hallado en el primer paso).</p>
</div>
<div id="cc-m-2964802913" class="j-module n j-header ">
<h3 id="cc-m-header-2964802913" class=""><em>Paso 3</em></h3>
</div>
<div id="cc-m-2964803013" class="j-module n j-text ">
<p>Este paso consiste en realizar el mismo procedimiento de los dos pasos anteriores referidos ahora a las columnas, es decir, se halla el valor mínimo de cada columna, con la diferencia que este se halla de la matriz resultante en el segundo paso, luego se construirá una nueva matriz en la cual se consignarán los valores resultantes de la diferencia entre cada costo y el valor mínimo de la columna a la cual cada costo corresponde, matriz llamada «Matriz de Costos Reducidos».</p>
</div>
<div id="cc-m-2964804713" class="j-module n j-header ">
<h3 id="cc-m-header-2964804713" class=""><em>Paso 4</em></h3>
</div>
<div id="cc-m-2964804813" class="j-module n j-text ">
<p>A continuación se deben de trazar líneas horizontales o verticales o ambas (únicamente de esos tipos) con el objetivo de cubrir todos los ceros de la matriz de costos reducidos con el menor número de líneas posibles, si el número de lineas es igual al número de filas o columnas se ha logrado obtener la solución óptima (la mejor asignación según el contexto de optimización), si el número de líneas es inferior al número de filas o columnas se debe de proceder con el paso 5.</p>
</div>
<div id="cc-m-2964805013" class="j-module n j-header ">
<h3 id="cc-m-header-2964805013" class=""><em>Paso 5</em></h3>
</div>
<div id="cc-m-2964806313" class="j-module n j-text ">
<p>Este paso consiste en encontrar el menor elemento de aquellos valores que no se encuentran cubiertos por las lineas del paso 4, ahora se restará del restante de elementos que no se encuentran cubiertos por las líneas; a continuación este mismo valor se sumará a los valores que se encuentren en las intersecciones de las lineas horizontales y verticales, una vez finalizado este paso se debe volver al paso 4.</p>

		<div class="clearfix"></div>
		<hr style="margin-top:20px; margin-bottom:20px;" class="divider divider-solid">
	
<h2>
		<div id="solucion-de-un-problema-de-asignacion-mediante-el-metodo-hungaro" data-title="Solución de un problema de asignación mediante el Método Húngaro" class="index-title"></div>
	Solución de un problema de asignación mediante el Método Húngaro</h2>
<h3>El problema</h3>
<blockquote class="aligncenter quote-simple "><p>La compañía de manufactura «Jiménez y Asociados» desea realizar una jornada de mantenimiento preventivo a sus tres máquinas principales A, B y C. El tiempo que demanda realizar el mantenimiento de cada máquina es de 1 día, sin embargo la jornada de mantenimiento no puede durar más de un día, teniendo en cuenta que la compañía cuenta con tres proveedores de servicios de mantenimiento debe de asignarse un equipo de mantenimiento a cada máquina para poder cumplir con la realización del mantenimiento preventivo. Teniendo en cuenta que según el grado de especialización de cada equipo prestador de servicios de mantenimiento el costo de la tarea varía para cada máquina en particular, debe de asignarse el equipo correcto a la máquina indicada con el objetivo de minimizar el costo total de la jornada. Los costos asociados se pueden observar en la siguiente tabla:</p></blockquote>
</div>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-258.webp" alt="Problema de asignación" width="367" height="152" class="aligncenter wp-image-26538 size-full" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-258.webp 367w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-258-300x124.webp 300w" sizes="(max-width: 367px) 100vw, 367px" /></p>
<p><em style="font-size: 22px; font-weight: bold;">Paso 1</em></p>
<div id="cc-m-2964821713" class="j-module n j-text ">
<p><em>Encontramos el menor elemento de cada fila</em></p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-259.webp" alt="Problema de asignación" width="474" height="165" class="aligncenter wp-image-26539 size-full" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-259.webp 474w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-259-300x104.webp 300w" sizes="(max-width: 474px) 100vw, 474px" /></p>
</div>
<div id="cc-m-2964821813" class="j-module n j-imageSubtitle ">
<p>&nbsp;</p>
</div>
<div id="cc-m-2964821913" class="j-module n j-header ">
<h3 id="cc-m-header-2964821913" class=""><em>Paso 2</em></h3>
</div>
<div id="cc-m-2964822013" class="j-module n j-text ">
<p>Construimos una nueva matriz con las diferencias entre los valores de la matriz original y el elemento menor de la fila a la cual corresponde.</p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-260.webp" alt="Problema de asignación" width="495" height="144" class="aligncenter wp-image-26540 size-full" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-260.webp 495w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-260-300x87.webp 300w" sizes="(max-width: 495px) 100vw, 495px" /></p>
</div>
<div id="cc-m-2964822113" class="j-module n j-imageSubtitle ">
<figure class="cc-imagewrapper cc-m-image-align-3"><figcaption></figcaption></figure>
<div class="cc-clear"><em><span style="font-size: 22px; font-weight: bold;">Paso 3</span></em></div>
</div>
<div id="cc-m-2964822313" class="j-module n j-text ">
<p>En la matriz construida en el paso anterior se procede a efectuar el paso 1 esta vez en relación a las columnas, por ende escogemos el elemento menor de cada columna. Igualmente construimos una nueva matriz con la diferencia entre los valores de la matriz 2 y el elemento menor de la columna a la cual corresponde cada valor.</p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-261.webp" alt="Matriz de costos reducidos" width="368" height="388" class="aligncenter size-full wp-image-26541" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-261.webp 368w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-261-285x300.webp 285w" sizes="(max-width: 368px) 100vw, 368px" /></p>
</div>
<div id="cc-m-2964822513" class="j-module n j-imageSubtitle ">
<p>&nbsp;</p>
</div>
<div id="cc-m-2964822913" class="j-module n j-header ">
<h3 id="cc-m-header-2964822913" class=""><em>Paso 4</em></h3>
</div>
<div id="cc-m-2964822813" class="j-module n j-text ">
<p>En este paso trazaremos la menor cantidad de combinaciones de líneas horizontales y verticales con el objetivo de cubrir todos los ceros de la matriz de costos reducidos.</p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-262.webp" alt="" width="369" height="183" class="aligncenter size-full wp-image-26542" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-262.webp 369w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-262-300x149.webp 300w" sizes="(max-width: 369px) 100vw, 369px" /></p>
</div>
<div id="cc-m-2964823013" class="j-module n j-imageSubtitle ">
<figure class="cc-imagewrapper cc-m-image-align-3"><figcaption></figcaption></figure>
</div>
<div id="cc-m-2964823113" class="j-module n j-text ">
<p>Como se puede observar el menor número de líneas horizontales y/o verticales necesarias para cubrir los ceros de la matriz de costos reducidos es igual a 2, por ende al ser menor que el número de filas o columnas es necesario recurrir al paso 5.</p>
</div>
<div id="cc-m-2964823213" class="j-module n j-header ">
<h3></h3>
<h3 id="cc-m-header-2964823213" class=""><em>Paso 5</em></h3>
</div>
<div id="cc-m-2964823313" class="j-module n j-text ">
<p><em>En este paso seleccionamos el menor elemento de los elementos no subrayados.</em></p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-263.webp" alt="" width="369" height="274" class="aligncenter size-full wp-image-26543" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-263.webp 369w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-263-300x223.webp 300w" sizes="(max-width: 369px) 100vw, 369px" /></p>
</div>
<div id="cc-m-2964823913" class="j-module n j-imageSubtitle ">
<div class="cc-clear"></div>
</div>
<div id="cc-m-2964824013" class="j-module n j-text ">
<p>Luego se procede a restarse de los elementos no subrayados y a adicionarse a los elementos ubicados en las intersecciones de las líneas, en este caso existe una única intersección (3).</p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-264.webp" alt="" width="367" height="179" class="aligncenter size-full wp-image-26544" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-264.webp 367w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-264-300x146.webp 300w" sizes="(max-width: 367px) 100vw, 367px" /></p>
</div>
<div id="cc-m-2964824113" class="j-module n j-imageSubtitle ">
<figure class="cc-imagewrapper cc-m-image-align-3"><figcaption></figcaption></figure>
</div>
<div id="cc-m-2964824213" class="j-module n j-text ">
<p><em>Ahora ya efectuado este paso pasamos al paso 4.</em></p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-265.webp" alt="" width="367" height="179" class="aligncenter size-full wp-image-26545" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-265.webp 367w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-265-300x146.webp 300w" sizes="(max-width: 367px) 100vw, 367px" /></p>
</div>
<div id="cc-m-2964824313" class="j-module n j-imageSubtitle ">
<figure class="cc-imagewrapper cc-m-image-align-3"><figcaption></figcaption></figure>
</div>
<div id="cc-m-2964824413" class="j-module n j-text ">
<p>Ahora observamos cómo se hace necesario trazar tres líneas (la misma cantidad de filas o columnas de la matriz) por ende se ha llegado al tabulado final, en el que por simple observación se determina las asignaciones óptimas.</p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-266.webp" alt="" width="367" height="179" class="aligncenter size-full wp-image-26546" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-266.webp 367w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-266-300x146.webp 300w" sizes="(max-width: 367px) 100vw, 367px" /></p>
</div>
<div id="cc-m-2964824513" class="j-module n j-imageSubtitle ">
<figure class="cc-imagewrapper cc-m-image-align-3"><figcaption></figcaption></figure>
</div>
<div id="cc-m-2964824613" class="j-module n j-text ">
<p>Por ende la asignación que representa el menor costo para la jornada de mantenimiento preventivo determina que el Equipo 1 realice el mantenimiento de la Máquina 1, el Equipo 2 realice el mantenimiento de la Máquina 3 y el Equipo 3 realice el mantenimiento de la Máquina 2, jornada que tendrá un costo total de 17 unidades monetarias.</p>

		<div class="clearfix"></div>
		<hr style="margin-top:20px; margin-bottom:20px;" class="divider divider-solid">
	
<h2>
		<div id="solucion-de-un-problema-de-maximizacion-mediante-el-metodo-hungaro" data-title="Solución de un problema de maximización mediante el Método Húngaro" class="index-title"></div>
	Solución de un problema de maximización mediante el Método Húngaro</h2>
<h3>El problema</h3>
<blockquote class="aligncenter quote-simple "><p>Una organización de recolección de café cuenta con tres equipos de siembra y cosecha del mismo (equipos 1, 2, 3). Estos equipos de trabajo se encuentran entrenados para trabajar en condiciones particulares del proceso, condiciones como lo son el tipo de suelo, las condiciones del clima y el tipo de grano. La organización cuenta con cuatro terrenos disponibles para efectuar el proceso de siembra y cosecha (terrenos A, B, C, D), estos terrenos tienen condiciones particulares de suelo, clima y tipo de grano. Cada equipo cuenta con la capacidad de efectuar el proceso en solo uno de los terrenos disponibles, salvo el equipo 2, que cuenta con una serie de herramientas tecnológicas que le permiten realizar la siembra y cosecha del grano en dos de los terrenos disponibles.</p></blockquote>
<p><em>Se ha contratado a un Ingeniero Industrial con el objetivo de realizar las asignaciones precisas que maximicen la cantidad de sacos de café cosechados en total. El siguiente tabulado muestra la capacidad (en cientos de sacos) de cosecha de café de cada uno de los equipos dependiendo de cada uno de los terrenos.</em></p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-267.webp" alt="Problemas de asignación" width="422" height="146" class="aligncenter wp-image-26547 size-full" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-267.webp 422w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-267-300x104.webp 300w" sizes="(max-width: 422px) 100vw, 422px" /></p>
<h3><em>Solución</em></h3>
<p>En este problema debemos recordar un concepto fundamental para la aplicación del método húngaro, este concepto nos dice que el número de filas debe ser exactamente igual al número de columnas. Por ende, la acción a realizar debería ser crear un equipo ficticio, el cual nos deje el tabulado balanceado y a este asignarle un número de sacos cosechados equivalente a cero en cada uno de los terrenos. Sin embargo el problema nos indica que uno de los equipos se encuentra en capacidad de que se le asignen dos terrenos, en este caso crearemos un equipo 2 alternativo (Equipo 2B) el cual nos balanceará el tabulado y nos hará prescindir del equipo ficticio pensado inicialmente. A este equipo 2B que crearemos le corresponderá la misma capacidad de cosecha del equipo 2 (en adelante equipo 2A) según el terreno, lógicamente.</p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-268.webp" alt="Problemas de asignación" width="422" height="182" class="aligncenter wp-image-26548 size-full" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-268.webp 422w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-268-300x129.webp 300w" sizes="(max-width: 422px) 100vw, 422px" /></p>
<div id="cc-m-5695446513" class="j-module n j-imageSubtitle ">
<div class="cc-clear"></div>
</div>
<div id="cc-m-5695446613" class="j-module n j-text ">
<p>Una vez balanceado el tabulado debemos de cuestionarnos acerca del criterio de optimización, pues recordemos que el método húngaro se encuentra diseñado para ejercicios de minimización. En este caso nuestro objetivo es maximizar, por lo que tendremos que aplicar un paso adicional.</p>
<p><em>Lo primero que debemos hacer es ubicar el mayor valor del tabulado inicial.</em></p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-269.webp" alt="" width="422" height="182" class="aligncenter size-full wp-image-26549" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-269.webp 422w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-269-300x129.webp 300w" sizes="(max-width: 422px) 100vw, 422px" /></p>
</div>
<div id="cc-m-5695446713" class="j-module n j-imageSubtitle ">
<div class="cc-clear"></div>
</div>
<div id="cc-m-5695446813" class="j-module n j-text ">
<p>En este caso este valor es 15, por lo cual procederemos a realizar la siguiente operación con cada uno de los valores:</p>
<p><em>Restaremos a 15, el valor de cada una de las celdas y este valor quedará en cada una de las celdas correspondientes.</em></p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-270.webp" alt="" width="426" height="177" class="aligncenter size-full wp-image-26550" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-270.webp 426w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-270-300x125.webp 300w" sizes="(max-width: 426px) 100vw, 426px" /></p>
</div>
<div id="cc-m-5695447013" class="j-module n j-imageSubtitle ">
<div class="cc-clear"></div>
</div>
<div id="cc-m-5695447113" class="j-module n j-text ">
<p><em>Ahora nuestro tabulado inicial quedará de la siguiente manera:</em></p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-271.webp" alt="" width="426" height="177" class="aligncenter size-full wp-image-26551" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-271.webp 426w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-271-300x125.webp 300w" sizes="(max-width: 426px) 100vw, 426px" /></p>
</div>
<div id="cc-m-5695447313" class="j-module n j-imageSubtitle ">
<div class="cc-clear"></div>
</div>
<div id="cc-m-5695447413" class="j-module n j-text ">
<p>A partir de este tabulado ya podemos aplicar el algoritmo del método húngaro como se aplicaría en un caso e minimización (normalmente).</p>
<p><em>Ahora encontramos el menor elemento de cada fila.</em></p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-272.webp" alt="" width="426" height="177" class="aligncenter size-full wp-image-26553" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-272.webp 426w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-272-300x125.webp 300w" sizes="(max-width: 426px) 100vw, 426px" /></p>
</div>
<div id="cc-m-5695447713" class="j-module n j-imageSubtitle ">
<div class="cc-clear"></div>
</div>
<div id="cc-m-5695447813" class="j-module n j-text ">
<p><em>Y se lo restamos a todas las celdas de la fila.</em></p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-273.webp" alt="" width="525" height="177" class="aligncenter size-full wp-image-26554" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-273.webp 525w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-273-300x101.webp 300w" sizes="(max-width: 525px) 100vw, 525px" /></p>
</div>
<div id="cc-m-5695447913" class="j-module n j-imageSubtitle ">
<div class="cc-clear"></div>
</div>
<div id="cc-m-5695448113" class="j-module n j-text ">
<p>Ahora efectuamos este mismo paso, pero esta vez con las columnas. Elegimos el menor de los valores de cada columna y se lo restamos a cada una de las celdas de la columna correspondiente.</p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-274.webp" alt="" width="392" height="177" class="aligncenter size-full wp-image-26555" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-274.webp 392w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-274-300x135.webp 300w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-274-390x177.webp 390w" sizes="(max-width: 392px) 100vw, 392px" /></p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/hungaro_0.png" alt="" width="392" height="177" class="size-full wp-image-35736 aligncenter" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/hungaro_0.png 392w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/hungaro_0-300x135.png 300w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/hungaro_0-390x177.png 390w" sizes="(max-width: 392px) 100vw, 392px" /></p>
</div>
<div id="cc-m-5695448613" class="j-module n j-imageSubtitle ">
<div class="cc-clear"></div>
</div>
<div id="cc-m-5695449113" class="j-module n j-text ">
<p>Ahora procedemos a cubrir la mayor cantidad de ceros, con la menor cantidad de líneas, si el número de líneas que empleemos es igual al grado de la matriz (en este caso matriz grado 4, 4&#215;4) habremos llegado al final del ejercicio.</p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-276.webp" alt="" width="392" height="177" class="aligncenter size-full wp-image-26556" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-276.webp 392w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-276-300x135.webp 300w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-276-390x177.webp 390w" sizes="(max-width: 392px) 100vw, 392px" /></p>
</div>
<div id="cc-m-5695449213" class="j-module n j-imageSubtitle ">
<div class="cc-clear"></div>
</div>
<div id="cc-m-5695448313" class="j-module n j-text ">
<p>Dado que el número de líneas es igual al grado de la matriz, hemos concluido el algoritmo. Lo único que quedará será asignar a cada equipo el terreno en el que el intercepto es igual a 0 (cero).</p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-277.webp" alt="" width="392" height="177" class="aligncenter size-full wp-image-26557" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-277.webp 392w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-277-300x135.webp 300w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-277-390x177.webp 390w" sizes="(max-width: 392px) 100vw, 392px" /></p>
</div>
<div id="cc-m-5695449313" class="j-module n j-imageSubtitle ">
<div class="cc-clear"></div>
</div>
<div id="cc-m-5695449413" class="j-module n j-text ">
<p>Las asignaciones, como es lógico deberán iniciarse por el equipo al cual solo corresponda un terreno, en este caso al Equipo 3 le corresponde el Terreno A. De esta manera al Equipo 1 le corresponde el Terreno D. Mientras tanto el Equipo 2 se encargará de la cosecha en los terrenos B y C. Según el tabulado del problema (recordemos que es de maximización), la cantidad de sacos (expresada en cientos de sacos) será así:</p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-278.webp" alt="" width="392" height="197" class="aligncenter size-full wp-image-26558" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-278.webp 392w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-278-300x151.webp 300w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-278-390x197.webp 390w" sizes="(max-width: 392px) 100vw, 392px" /></p>
</div>
<div id="cc-m-5695449813" class="j-module n j-imageSubtitle ">

		<div class="clearfix"></div>
		<hr style="margin-top:20px; margin-bottom:20px;" class="divider divider-solid">
	
<h2>
		<div id="solucion-de-un-problema-de-asignacion-mediante-programacion-lineal" data-title="Solución de un problema de asignación mediante programación lineal" class="index-title"></div>
	Solución de un problema de asignación mediante programación lineal</h2>
<h3>El problema</h3>
<blockquote class="aligncenter quote-simple "><p>La compañía de manufactura «Jiménez y Asociados» desea realizar una jornada de mantenimiento preventivo a sus tres máquinas principales A, B y C. El tiempo que demanda realizar el mantenimiento de cada máquina es de 1 día, sin embargo la jornada de mantenimiento no puede durar más de un día, teniendo en cuenta que la compañía cuenta con tres proveedores de servicios de mantenimiento debe de asignarse un equipo de mantenimiento a cada máquina para poder cumplir con la realización del mantenimiento preventivo. Teniendo en cuenta que según el grado de especialización de cada equipo prestador de servicios de mantenimiento el costo de la tarea varía para cada máquina en particular, debe de asignarse el equipo correcto a la máquina indicada con el objetivo de minimizar el costo total de la jornada. Los costos asociados se pueden observar en la siguiente tabla:</p></blockquote>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-279.webp" alt="" width="367" height="152" class="aligncenter wp-image-26559 size-full" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-279.webp 367w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-279-300x124.webp 300w" sizes="(max-width: 367px) 100vw, 367px" /></p>
<div id="cc-m-2964835313" class="j-module n j-header ">
<h3 id="cc-m-header-2964835313" class=""><em>Variables de decisión</em></h3>
</div>
<div id="cc-m-2964835413" class="j-module n j-text ">
<p>Las variables de decisión de este tipo de problemas es igual a las variables de cualquier modelo de transporte tradicional, es decir variables X<sub>i,j</sub> donde i {Equipo de mantenimiento 1,2,3} y j {Máquina 1,2,3}, y corresponden a variables binarias en las cuales el valor 1 significa la asignación de un equipo de mantenimiento a una máquina en particular.</p>
</div>
<div id="cc-m-2964835513" class="j-module n j-header ">
<h3 id="cc-m-header-2964835513" class=""><em>Restricciones</em></h3>
</div>
<div id="cc-m-2964835613" class="j-module n j-text ">
<p>Dado que un equipo de mantenimiento no puede ser asignado a más de una maquinaria, esta característica debe de restringirse mediante las siguientes inecuaciones.</p>
<p>X<sub>1,1</sub> + X<sub>1,2</sub> + X<sub>1,3</sub> = 1</p>
<p>X<sub>2,1</sub> + X<sub>2,2</sub> + X<sub>2,3</sub> = 1</p>
<p>X<sub>3,1</sub> + X<sub>3,2</sub> + X<sub>3,3</sub> = 1</p>
<p>Además debe restringirse el hecho de que cada máquina solo requiere de un equipo de mantenimiento, por ende</p>
<p>X<sub>1,1</sub> + X<sub>2,1</sub> + X<sub>3,1</sub> = 1</p>
<p>X<sub>1,2</sub> + X<sub>2,2</sub> + X<sub>3,2</sub> = 1</p>
<p>X<sub>1,3</sub> + X<sub>2,3</sub> + X<sub>3,3</sub> = 1</p>
<p>Además se hace necesario que para efectos de resolución en cualquier paquete de herramientas se especifique que estas variables corresponden al conjunto de los enteros (por obvias razones) y que deben ser mayores que cero (dado que es un problema de minimización esta restricción se hace muy necesario).</p>
<p>X<sub>i,j</sub> ≥ 0</p>
<p>X<sub>i,j</sub> ∈ {Z}</p>
<p>&nbsp;</p>
</div>
<div id="cc-m-2964835913" class="j-module n j-header ">
<h3 id="cc-m-header-2964835913" class=""><em>Función Objetivo</em></h3>
</div>
<div id="cc-m-2964836013" class="j-module n j-text ">
<p>Z<sub>MIN</sub> = 10X<sub>1,1</sub> + 9X<sub>1,2</sub> + 5X<sub>1,3</sub> + 9X<sub>2,1</sub> + 8X<sub>2,2</sub> + 3X<sub>2,3</sub> + 6X<sub>3,1</sub> + 4X<sub>3,2</sub> + 7X<sub>3,3</sub></p>
<div id="cc-m-2964836113" class="j-module n j-header ">
<h3></h3>
<h3 id="cc-m-header-2964836113" class=""><em>Ingresando los datos a WinQSB</em></h3>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-280.webp" alt="Problemas de asignación WinQSB" width="535" height="166" class="aligncenter wp-image-26560 size-full" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-280.webp 535w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-280-300x93.webp 300w" sizes="(max-width: 535px) 100vw, 535px" /></p>
</div>
<div id="cc-m-2964836213" class="j-module n j-imageSubtitle ">
<div class="cc-clear"></div>
</div>
<div id="cc-m-2964836313" class="j-module n j-header ">
<h3 id="cc-m-header-2964836313" class="">Resultados obtenidos mediante WinQSB</h3>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-281.webp" alt="Problemas de asignación" width="549" height="225" class="aligncenter wp-image-26561 size-full" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-281.webp 549w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-281-300x123.webp 300w" sizes="(max-width: 549px) 100vw, 549px" /></p>
</div>
<div id="cc-m-2964836413" class="j-module n j-imageSubtitle ">
<div class="cc-clear"></div>
</div>
<div id="cc-m-2964836513" class="j-module n j-text ">
<p>Por ende la asignación que representa el menor costo para la jornada de mantenimiento preventivo determina que el Equipo 1 realice el mantenimiento de la Máquina 1, el Equipo 2 realice el mantenimiento de la Máquina 3 y el Equipo 3 realice el mantenimiento de la Máquina 2, jornada que tendrá un costo total de 17 unidades monetarias.</p>

		<div class="clearfix"></div>
		<hr style="margin-top:20px; margin-bottom:20px;" class="divider divider-solid">
	
<h2 id="cc-m-header-2964836913" class="">
		<div id="solucion-de-un-problema-de-asignacion-mediante-winqsb-network-modeling" data-title="Solución de un problema de asignación mediante WinQSB &#8211; Network Modeling" class="index-title"></div>
	Solución de un problema de asignación mediante WinQSB &#8211; Network Modeling</h2>
<p>La facilidad de resolver un problema de asignación mediante WinQSB es aún mayor a la que se incurre mediante <strong><a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/programacion-lineal/" target="" rel="noopener noreferrer">programación lineal</a></strong>, y esta metodología justifica el pensar en que el método húngaro es sumamente anacrónico únicamente contemplado para fines históricos y académicos. En el módulo NETWORK MODELING del paquete de herramientas WinQSB se puede resolver el modelo tan solo traspasando los costos de una matriz n*m a otra que brinda el módulo <em>n*m</em>.</p>
<div id="cc-m-2964837113" class="j-module n j-header ">
<h3 id="cc-m-header-2964836113" class=""><em>Ingresando los datos a WinQSB &#8211; Network Modeling</em></h3>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-282.webp" alt="Problemas de asignación" width="424" height="72" class="aligncenter wp-image-26562 size-full" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-282.webp 424w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-282-300x51.webp 300w" sizes="(max-width: 424px) 100vw, 424px" /></p>
</div>
<div id="cc-m-2964837313" class="j-module n j-imageSubtitle ">
<div class="cc-clear"></div>
</div>
<div id="cc-m-2964837213" class="j-module n j-header ">
<h3 class="">Resultados obtenidos mediante WinQSB <em>&#8211; Network Modeling</em></h3>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-283.webp" alt="Problemas de asignación" width="549" height="95" class="aligncenter wp-image-26563 size-full" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-283.webp 549w, https://ingenieriaindustrialonline.com/wp-content/uploads/2019/06/Sin-titulo-283-300x52.webp 300w" sizes="(max-width: 549px) 100vw, 549px" /></p>
</div>
<div id="cc-m-2964837413" class="j-module n j-imageSubtitle ">
<p>Por ende la asignación que representa el menor costo para la jornada de mantenimiento preventivo determina que el Equipo 1 realice el mantenimiento de la Máquina 1, el Equipo 2 realice el mantenimiento de la Máquina 3 y el Equipo 3 realice el mantenimiento de la Máquina 2, jornada que tendrá un costo total de 17 unidades monetarias.</p>
<p>De esta manera se hace evidente cual es la alternativa predilecta para resolver problemas de asignación.</p>
<hr />
<p>Le recomendamos revisar: <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/problemas-de-asignacion-en-google-or-tools/"><em><strong>Problemas de asignación en Google OR-Tools</strong></em></a><em>. </em>Descubre esta poderosa herramienta de modelamiento y solución de problemas de optimización.</p>
</div>
</div>
</div>
</div>
</div>
</div>
<p>La entrada <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/problemas-de-asignacion/">Problemas de asignación</a> se publicó primero en <a href="https://ingenieriaindustrialonline.com">Ingenieria Industrial Online</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ingenieriaindustrialonline.com/investigacion-de-operaciones/problemas-de-asignacion/feed/</wfw:commentRss>
			<slash:comments>12</slash:comments>
		
		
			</item>
	</channel>
</rss>
