<?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>PLE archivos &#187; Ingenieria Industrial Online</title>
	<atom:link href="https://ingenieriaindustrialonline.com/tag/ple/feed/" rel="self" type="application/rss+xml" />
	<link>https://ingenieriaindustrialonline.com/tag/ple/</link>
	<description>ingenieriaindustriaonline.com</description>
	<lastBuildDate>Sun, 16 Apr 2023 16:04:31 +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>PLE archivos &#187; Ingenieria Industrial Online</title>
	<link>https://ingenieriaindustrialonline.com/tag/ple/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Programación lineal mixta con Google OR-Tools</title>
		<link>https://ingenieriaindustrialonline.com/investigacion-de-operaciones/programacion-lineal-mixta-con-google-or-tools/</link>
					<comments>https://ingenieriaindustrialonline.com/investigacion-de-operaciones/programacion-lineal-mixta-con-google-or-tools/#comments</comments>
		
		<dc:creator><![CDATA[Bryan Salazar López]]></dc:creator>
		<pubDate>Mon, 26 Apr 2021 19:53:07 +0000</pubDate>
				<category><![CDATA[Investigación de operaciones]]></category>
		<category><![CDATA[Google OR-Tools]]></category>
		<category><![CDATA[Optimización]]></category>
		<category><![CDATA[Optimización lineal]]></category>
		<category><![CDATA[PLE]]></category>
		<category><![CDATA[Programación lineal]]></category>
		<category><![CDATA[Programación lineal entera]]></category>
		<category><![CDATA[Programación lineal mixta]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://ingenieriaindustrialonline.com/?p=25584</guid>

					<description><![CDATA[<p>En artículos anteriores hemos mencionado la diferencia existente entre programación lineal (PL) y programación lineal entera (PLE). Recordamos entonces que, cuando un modelo presenta todas sus variables enteras, se denomina puro. En caso contrario, cuando utiliza una combinación de variables enteras y continuas, se denomina mixto, constituyendo un modelo de programación lineal mixta. En materia de optimización lineal, la programación &#8230;</p>
<p>La entrada <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/programacion-lineal-mixta-con-google-or-tools/">Programación lineal mixta con 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>En artículos anteriores hemos mencionado la diferencia existente entre <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/programacion-lineal-entera-con-google-or-tools/"><em><strong>programación lineal (PL)</strong></em></a> y <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/programacion-lineal-entera-con-google-or-tools/"><em><strong>programación lineal entera (PLE)</strong></em></a>. Recordamos entonces que, cuando un modelo presenta todas sus variables enteras, se denomina <em>puro. </em>En caso contrario, cuando utiliza una combinación de variables enteras y continuas, se denomina <em>mixto, </em>constituyendo un modelo de <em>programación lineal mixta.</em></p>
<p>En materia de optimización lineal, la programación lineal mixta, lógicamente, aborda la mayor cantidad de casos de aplicación práctica. En la medida en que se consideren la mayor cantidad de variables que representen mediante un modelo de optimización, la realidad; es potencialmente adecuado, hacer uso de modelos de programación mixta.</p>
<p>Por ejemplo, pensemos en la producción de televisores, es posible que en un modelo lineal queramos representar por medio de una variable entera, la cantidad de unidades producidas; ahora bien, también es posible que queramos representar por medio de una variable continua, el tiempo empleado en la fabricación. En este escenario, requerimos de programación lineal mixta.<em></em></p>
<hr />
<p><span>El objetivo de este artículo consiste en utilizar las librerías del software Google OR-Tools para abordar problemas de programación lineal mixta (optimización lineal mixta). </span></p>
<p>OR-Tools proporciona una herramienta principal para resolver este tipo de problemas de optimización:</p>

		<div class="checklist tie-list-shortcode">
<ul>
<li>MPSolver: un contenedor para varios solucionadores de MIP de terceros, que utilizan técnicas estándar de ramificación y vinculación <em>(branch and bound).</em></li>
</ul>

		</div>
	
<hr />
<h2>El problema
		<div id="el-problema" data-title="El problema" class="index-title"></div>
	</h2>
<p>En el artículo de introducción (<a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/programacion-lineal-entera-con-google-or-tools/">programación lineal</a>), abordamos un caso descrito en el libro <em>Applied Mathematical Programming, de Bradley, Hax, and Magnanti (Addison-Wesley, 1977), del MIT (Cápitulo 2 página 50). </em>Con fines prácticos, hemos adaptado dicho problema, incorporando nuevas restricciones y modificando algunos datos del modelo original, con el propósito de evidenciar la diferencia en los resultados obtenidos por medio del uso de variables continuas, enteras y mixtas.</p>
<blockquote class=" quote-simple "><p>El propietario de una tienda que produce remolques para automóviles desea determinar la mejor combinación para sus tres productos: remolques de plataforma plana, remolques económicos y remolques de lujo. Su taller se limita a trabajar 24 días al mes en el trabajo de los metales y 60 días al mes en el trabajo de la madera para estos productos.</p>
<p>Existe un contrato vigente, mediante el cual, el propietario deberá entregar como mínimo 4 remolques tipo económico cada mes.</p>
<p>La siguiente tabla indica los datos de producción de los remolques.</p></blockquote>
<table width="492">
<tbody>
<tr>
<td width="172"></td>
<td colspan="3" width="240" style="text-align: center;">Uso por cada unidad de tráiler</td>
<td rowspan="2" width="80" style="text-align: center;">Recursos disponibles</td>
</tr>
<tr>
<td style="text-align: center;"></td>
<td width="80" style="text-align: center;">Plataforma plana</td>
<td width="80" style="text-align: center;">Económica</td>
<td width="80" style="text-align: center;">Lujosa</td>
</tr>
<tr>
<td style="text-align: center;">Días de trabajo en metales</td>
<td style="text-align: center;">0,6</td>
<td style="text-align: center;">2</td>
<td style="text-align: center;">1</td>
<td style="text-align: center;">24</td>
</tr>
<tr>
<td style="text-align: center;">Días de trabajo en madera</td>
<td style="text-align: center;">1</td>
<td style="text-align: center;">2</td>
<td style="text-align: center;">4</td>
<td style="text-align: center;">60</td>
</tr>
<tr>
<td style="text-align: center;">Contribución ($ x 100)</td>
<td style="text-align: center;">6</td>
<td style="text-align: center;">14</td>
<td style="text-align: center;">13</td>
<td style="text-align: center;"></td>
</tr>
</tbody>
</table>
<h2>Modelamiento del problema
		<div id="modelamiento-del-problema" data-title="Modelamiento del problema" class="index-title"></div>
	</h2>
<p><em>Sean las variables de decisión del problema:</em></p>
<p>x<sub>0</sub> = Número de remolques de plataforma plana producidos por mes</p>
<p>x<sub>1</sub> = Número de remolques económicos producidos por mes</p>
<p>x<sub>2</sub> = Número de remolques de lujo producidos por mes</p>
<p><em>Suponiendo que los costos de la capacidad de trabajo en metal y madera sean fijos, el problema se convierte en un problema de maximización:</em></p>
<p>Zmax = 6<strong>x<sub>0</sub></strong> + 14<strong>x<sub>1</sub></strong> + 13<strong>x<sub>2</sub></strong></p>
<p><em>Sujeto a las siguientes restricciones de capacidad:</em></p>
<p>0,6<strong>x<sub>0</sub></strong> + 2<strong>x<sub>1</sub></strong> + <strong>x<sub>2</sub></strong> &lt;= 24,</p>
<p><strong>x<sub>0</sub></strong> + 2<strong>x<sub>1</sub></strong> + 4<strong>x<sub>2</sub></strong> &lt;= 60,</p>
<p><em>Sujeto a la siguiente restricción de demanda mínima (contrato)</em></p>
<p><strong>x<sub>1</sub></strong> &gt;= 4</p>
<p><em>Sujeto a las siguientes restricciones de no-negatividad:</em></p>
<p><strong>x<sub>0</sub></strong> &gt;= 0,</p>
<p><strong>x<sub>1</sub></strong> &gt;= 0,</p>
<p><strong>x<sub>2</sub></strong> &gt;= 0,</p>
<p><em>Podemos, del mismo modo, establecer un par de variables que correspondan a las horas ociosas para las dos tareas establecidas (metal y madera):</em></p>
<p>x<sub>3</sub> = Número de horas ociosas en el trabajo en metal al mes,</p>
<p>x<sub>4</sub> = Número de horas ociosas en el trabajo en madera al mes,</p>
<p><em>Reescribimos las restricciones (adicionando las variables de horas ociosas). Podemos observar que las inecuaciones ahora serán igualdades, para que de esta forma ahora podamos tener información relacionada a los recursos. En otras palabras, lo que se utiliza (horas productivas) + lo que sobre (horas ociosas) = tiempo disponible:</em></p>
<p>0,6<strong>x<sub>0</sub></strong> + 2<strong>x<sub>1</sub></strong> + <strong>x<sub>2</sub></strong> + <strong>x<sub>3</sub></strong> = 24,</p>
<p><strong>x<sub>0</sub></strong> + 2<strong>x<sub>1</sub></strong> + 4<strong>x<sub>2</sub></strong> + <strong>x<sub>4</sub></strong> = 60,</p>
<p><strong>x<sub>0</sub></strong> &gt;= 0,</p>
<p><strong>x<sub>1</sub></strong> &gt;= 0,</p>
<p><strong>x<sub>2</sub></strong> &gt;= 0,</p>
<p><strong>x<sub>3</sub></strong> &gt;= 0,</p>
<p><strong>x<sub>4</sub></strong> &gt;= 0,</p>
<p>Así entonces, tenemos el problema completamente modelado.</p>
<hr />
<h2>Resolución del modelo mediante Google OR-Tools</h2>
<p><span>De acuerdo a lo mencionado en el artículo de </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><span>, esta herramienta soporta múltiples lenguajes de programación, en esta ocasión, haremos uso del lenguaje de programación Python.</span></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 ortools.linear_solver import pywraplp
</code></pre>
</div>
<h3><em>Paso 2: Declarar el solucionador
		<div id="paso-2-declarar-el-solucionador" data-title="Paso 2: Declarar el solucionador" class="index-title"></div>
	</em></h3>
<p>El siguiente fragmento de código declara el solucionador SCIP <em>(Solving Constraint Integer Programs), un solucionador de código abierto disponible que permite resolver problemas lineales mixtos (Google OR-Tools posee múltiples solucionadores):</em></p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code><span class="pln">solver = pywraplp.Solver.CreateSolver('SCIP')</span></code></pre>
</div>
<h3><em>Paso 3: Crear las variables del modelo
		<div id="paso-4-crear-las-variables-del-modelo" data-title="Paso 4: Crear las variables del modelo" class="index-title"></div>
	</em></h3>
<p>El siguiente fragmento de código permite crear las variables del modelo. La sintaxis permite declarar la naturaleza de cada una de las variables y el rango de valores permitidos (restricciones de no-negatividad).</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code><span class="pln">    x0 = solver.IntVar(0, solver.infinity(), 'x0')
    x1 = solver.IntVar(0, solver.infinity(), 'x1')
    x2 = solver.IntVar(0, solver.infinity(), 'x2')
    x3 = solver.NumVar(0, solver.infinity(), 'x3')
    x4 = solver.NumVar(0, solver.infinity(), 'x4')
</span></code></pre>
</div>

		<div class="checklist tie-list-shortcode">
<ul>
<li>solver.IntVar = Variables enteras</li>
<li>solver.NumVar = Variables continuas</li>
</ul>

		</div>
	
<p>A partir de la declaración de estas variables, el modelo corresponde a un problema de programación lineal mixta.</p>
<h3><em>Paso 4: Definir las restricciones del modelo
		<div id="paso-5-definir-las-restricciones-del-modelo" data-title="Paso 5: Definir las restricciones del modelo" class="index-title"></div>
	</em></h3>
<p>El siguiente fragmento de código define las restricciones del modelo:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code><span class="pln">    # Restricción 0: 0.6x0 + 2x1 + x2 + x3 = 24. (horas metales)
    solver.Add(0.6 * x0 + 2 * x1 + x2 + x3 == 24.0)

    # Restricción 1: x0 + 2x1 + 4x2 + x4 = 60. (horas madera)
    solver.Add(x0 + 2 * x1 + 4 *x2 + x4 == 60.0)

    # Restricción 3: x1 &gt;= 4. (demanda mínima)
    solver.Add(x1 &gt;= 4.0)
</span></code></pre>
</div>
<h3><em>Paso 5: Definir la función objetivo del modelo
		<div id="paso-5-definir-la-funcion-objetivo-del-modelo" data-title="Paso 5: Definir la función objetivo del modelo" class="index-title"></div>
	</em></h3>
<p>El siguiente fragmento de código define la función objetivo del modelo:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code><span class="pln">    # Función objetivo (max): 6x0 + 14x1 + 13x2
    solver.Maximize(6 * x0 + 14 * x1 + 13 * x2)
</span></code></pre>
</div>
<h3><em>Paso 6: Invocar el solucionador
		<div id="paso-6-invocar-el-solucionador" data-title="Paso 6: Invocar el solucionador " class="index-title"></div>
	</em></h3>
<p>El siguiente fragmento de código sirve para invocar el solucionador del modelo:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code><span class="pln">status = solver.Solve()
</span></code></pre>
</div>
<h3><em>Paso 7: Definir las salidas del solucionador
		<div id="paso-7-definir-las-salidas-del-solucionador" data-title="Paso 7: Definir las salidas del solucionador" class="index-title"></div>
	</em></h3>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code><span class="pln">    if status == pywraplp.Solver.OPTIMAL:
        print('Solución:')
        print('Valor objetivo =', solver.Objective().Value())
        print('Número de remolques de plataforma plana producidos por mes =', x0.solution_value())
        print('Número de remolques económicos producidos por mes =', x1.solution_value())
        print('Número de remolques de lujo producidos por mes =', x2.solution_value())
        print('Número de horas ociosas en el trabajo en metal al mes =', x3.solution_value())
        print('Número de horas ociosas en el trabajo en madera al mes =', x4.solution_value())
    else:
      if status == solver.FEASIBLE:
        print('Se encontró una solución potencialmente subóptima.')
      else:
        print('El problema no tiene solución óptima.')

    # Información avanzada del solucionador

    print('\nUso avanzado:')
    print('Problema resuelto en %f milisegundos' % solver.wall_time())
    print('Problema resuelto en %d iteraciones' % solver.iterations())
</span></code></pre>
</div>
<p>&nbsp;</p>
<hr />
<p>Es posible que el desarrollo de los siete 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 optimización lineal.</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/1QEYOChKrnjJWk3l9DiaQVzote7jMl_VK?usp=sharing"><strong>Programación Lineal Mixta</strong></a>.</em></p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code><span class="pln">#Adaptado de: Bradley, Hax, and Magnanti, 'Applied Mathematical Programming', Chapter 2
#Nuevo caso y modelo: Salazar, ingenieriaindustrialonline.com (Programación lineal mixta)

# Importar la librería de Google OR-Tools
from ortools.linear_solver import pywraplp

def LinearProgrammingExample():
    solver = pywraplp.Solver.CreateSolver('SCIP')

    x0 = solver.IntVar(0, solver.infinity(), 'x0')
    x1 = solver.IntVar(0, solver.infinity(), 'x1')
    x2 = solver.IntVar(0, solver.infinity(), 'x2')
    x3 = solver.NumVar(0, solver.infinity(), 'x3')
    x4 = solver.NumVar(0, solver.infinity(), 'x4')

    print('Número de variables =', solver.NumVariables())

    # Restricción 0: 0.5x0 + 2x1 + x2 + x3 = 24.
    solver.Add(0.6 * x0 + 2 * x1 + x2 + x3 == 24.0)

    # Restricción 1: x0 + 2x1 + 4x2 + x4 = 60.
    solver.Add(x0 + 2 * x1 + 4 *x2 + x4 == 60.0)

    # Restricción 3: x1 &gt;= 4.
    solver.Add(x1 &gt;= 4.0)

    print('Número de restricciones =', solver.NumConstraints())

    # Función objetivo (max): 6x0 + 14x1 + 13x2
    solver.Maximize(6 * x0 + 14 * x1 + 13 * x2)

    # Declarar el solucionador.
    status = solver.Solve()

    # Declarar las salidas del solucionador
    if status == pywraplp.Solver.OPTIMAL:
        print('Solución:')
        print('Valor objetivo =', solver.Objective().Value())
        print('Número de remolques de plataforma plana producidos por mes =', x0.solution_value())
        print('Número de remolques económicos producidos por mes =', x1.solution_value())
        print('Número de remolques de lujo producidos por mes =', x2.solution_value())
        print('Número de horas ociosas en el trabajo en metal al mes =', x3.solution_value())
        print('Número de horas ociosas en el trabajo en madera al mes =', x4.solution_value())
    else:
      if status == solver.FEASIBLE:
        print('Se encontró una solución potencialmente subóptima.')
      else:
        print('El problema no tiene solución óptima.')

    # Información avanzada del solucionador

    print('\nUso avanzado:')
    print('Problema resuelto en %f milisegundos' % solver.wall_time())
    print('Problema resuelto en %d iteraciones' % solver.iterations())

LinearProgrammingExample()</span></code></pre>
</div>
<p>Al ejecutar nuestro desarrollo en <em><a href="https://colab.research.google.com/drive/1QEYOChKrnjJWk3l9DiaQVzote7jMl_VK?usp=sharing">Colaboratory</a>, </em>tenemos:</p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2021/04/pl_mixta_solucion.png" alt="pl_mixta_solucion" width="661" height="258" class="aligncenter size-full wp-image-26352" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2021/04/pl_mixta_solucion.png 661w, https://ingenieriaindustrialonline.com/wp-content/uploads/2021/04/pl_mixta_solucion-300x117.png 300w" sizes="(max-width: 661px) 100vw, 661px" /></p>
<p>Hemos modificado la naturaleza de las variables con el objetivo de mostrar los resultados a partir de tres escenarios: variables mixtas, enteras y continuas:</p>
<table width="506">
<tbody>
<tr>
<td width="152" style="text-align: center;"></td>
<td width="109" style="text-align: center;">Variables mixtas</td>
<td width="116" style="text-align: center;">Variables enteras</td>
<td width="129" style="text-align: center;">Variables continuas</td>
</tr>
<tr>
<td style="text-align: center;">Valor objetivo</td>
<td style="text-align: center;">247</td>
<td style="text-align: center;">246</td>
<td style="text-align: center;">248,57</td>
</tr>
<tr>
<td style="text-align: center;">Plataforma plana</td>
<td style="text-align: center;">8</td>
<td style="text-align: center;">10</td>
<td style="text-align: center;">8,57</td>
</tr>
<tr>
<td style="text-align: center;">Económicos</td>
<td style="text-align: center;">4</td>
<td style="text-align: center;">4</td>
<td style="text-align: center;">4</td>
</tr>
<tr>
<td style="text-align: center;">Lujosos</td>
<td style="text-align: center;">11</td>
<td style="text-align: center;">10</td>
<td style="text-align: center;">10,86</td>
</tr>
<tr>
<td style="text-align: center;">Horas ociosas (metal)</td>
<td style="text-align: center;">0,19</td>
<td style="text-align: center;">0,00</td>
<td style="text-align: center;">0,00</td>
</tr>
<tr>
<td style="text-align: center;">Horas ociosas (madera)</td>
<td style="text-align: center;">0,00</td>
<td style="text-align: center;">2,00</td>
<td style="text-align: center;">0,00</td>
</tr>
</tbody>
</table>
<p>El anterior, es un problema lineal que representa un caso sencillo, sin embargo, los resultados obtenidos presentan variaciones menores de acuerdo a la naturaleza de las variables consideradas.</p>
<p>Sin embargo, en modelos robustos, estas variaciones pueden ser considerables y determinantes. Por tal razón, la programación lineal mixta ofrece la posibilidad de modelar variables cuya naturaleza refleje con precisión la realidad que se pretende representar.</p>
<hr />
<p>Ahora bien, el modelo de optimización lineal mixta 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<span> </span><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>
<p>La entrada <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/programacion-lineal-mixta-con-google-or-tools/">Programación lineal mixta con 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/programacion-lineal-mixta-con-google-or-tools/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>Programación lineal entera con Google OR-Tools</title>
		<link>https://ingenieriaindustrialonline.com/investigacion-de-operaciones/programacion-lineal-entera-con-google-or-tools/</link>
					<comments>https://ingenieriaindustrialonline.com/investigacion-de-operaciones/programacion-lineal-entera-con-google-or-tools/#respond</comments>
		
		<dc:creator><![CDATA[Bryan Salazar López]]></dc:creator>
		<pubDate>Fri, 23 Apr 2021 22:48:25 +0000</pubDate>
				<category><![CDATA[Investigación de operaciones]]></category>
		<category><![CDATA[Google OR-Tools]]></category>
		<category><![CDATA[Optimización]]></category>
		<category><![CDATA[Optimización lineal]]></category>
		<category><![CDATA[PLE]]></category>
		<category><![CDATA[Programación lineal]]></category>
		<category><![CDATA[Programación lineal entera]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://ingenieriaindustrialonline.com/?p=25536</guid>

					<description><![CDATA[<p>Básicamente, la diferencia entre programación lineal (PL) y programación lineal entera (PLE) consiste en la naturaleza de sus variables; en el caso de la optimización lineal simple, el uso de variables de naturaleza continua permite el uso de valores fraccionarios en sus variables de decisión; lo cual, de acuerdo al modelo, puede ajustarse a la &#8230;</p>
<p>La entrada <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/programacion-lineal-entera-con-google-or-tools/">Programación lineal entera con Google OR-Tools</a> se publicó primero en <a href="https://ingenieriaindustrialonline.com">Ingenieria Industrial Online</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Básicamente, la diferencia entre <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/programacion-lineal/"><strong>programación lineal (PL)</strong></a> y programación lineal entera (PLE) consiste en la naturaleza de sus variables; en el caso de la optimización lineal simple, el uso de variables de naturaleza continua permite el uso de valores fraccionarios en sus variables de decisión; lo cual, de acuerdo al modelo, puede ajustarse a la realidad, o no. Por ejemplo, pensemos en la producción de maíz, es posible procesar fácilmente 1,7 toneladas del grano; en cuyo caso, las variables continuas ajustarán el modelo a la realidad.</p>
<p>Ahora bien, existen innumerables casos de aplicación práctica en los cuales las soluciones fraccionarias no se ajustan a la realidad y debemos considerar el uso de variables enteras, así entonces, tendremos un modelo de programación lineal entera (PLE). Por ejemplo, pensemos en la producción de lápices, es posible que queramos determinar la producción en términos de unidades de producto, no tanto así de fracciones.</p>
<p>Es preciso mencionar que, cuando un modelo presenta todas sus variables enteras, se denomina <em>puro. </em>En caso contrario, cuando utiliza una combinación de variables enteras y continuas, se denomina <em>mixto, </em>y se abordará mediante <em><strong><a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/programacion-lineal-mixta-con-google-or-tools/">programación lineal mixta</a></strong>.</em></p>
<hr />
<p>Ciertamente, en la práctica, los solucionadores de modelos de optimización han abordado la naturaleza de las variables brindando relativa facilidad; es decir, podemos cambiar el tipo de variable entre continua y entera de una manera muy sencilla, sin que esto afecte considerablemente el modelo.</p>
<p><span>El objetivo de este artículo consiste en utilizar las librerías del software Google OR-Tools para abordar problemas de programación lineal entera (optimización lineal entera). </span></p>
<p>OR-Tools proporciona dos herramientas principales para resolver este tipo de problemas de optimización:</p>

		<div class="checklist tie-list-shortcode">
<ul>
<li>MPSolver: un contenedor para varios solucionadores de MIP de terceros, que utilizan técnicas estándar de ramificación y vinculación <em>(branch and bound).</em></li>
<li>Solucionador de CP-SAT: Un solucionador de programación de restricciones que utiliza métodos SAT (satisfacibilidad).</li>
</ul>

		</div>
	
<hr />
<h2>El problema</h2>
<p>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), (<em>Conjunto de problemas 9.1A &#8211; Problema 3</em>).</p>
<blockquote class=" quote-simple "><p>Suponga que tiene 7 botellas de vino llenas, 7 a la mitad y 7 vacías. Le gustaría dividir las 21 botellas entre tres individuos de modo que cada uno reciba exactamente 7. Además, cada individuo debe recibir la misma cantidad de vino. Exprese el problema como restricciones del PLE, y halle una solución. <cite>TAHA</cite></p></blockquote>
<table width="439">
<tbody>
<tr>
<td width="172" style="text-align: center;"></td>
<td width="89" style="text-align: center;">Botellas llenas</td>
<td width="89" style="text-align: center;">Botellas a la mitad</td>
<td width="89" style="text-align: center;">Botellas vacías</td>
</tr>
<tr>
<td width="172" style="text-align: center;">Contenido</td>
<td width="89" style="text-align: center;">1</td>
<td width="89" style="text-align: center;">0,5</td>
<td width="89" style="text-align: center;">0</td>
</tr>
<tr>
<td width="172" style="text-align: center;">Cantidad de botellas</td>
<td width="89" style="text-align: center;">7</td>
<td width="89" style="text-align: center;">7</td>
<td width="89" style="text-align: center;">7</td>
</tr>
</tbody>
</table>
<h2>Modelamiento del problema</h2>
<p>El problema plantea un caso de asignación, en el cual debemos determinar la cantidad de botellas de cada tipo (llenas, medias y vacías), asignadas a cada uno de un conjunto de 3 individuos (1, 2 y 3). Por lo tanto, las variables de decisión se definirán de la siguiente manera:</p>
<p><strong>x<em><sub>ij</sub></em></strong><span> = Cantidad de botellas de tipo <em>i </em>asignadas al individuo <em>j</em></span></p>
<p><strong><em>i </em></strong>= {0 = Llena; 1 = Media; 2 = Vacía}</p>
<p><em><strong>j</strong> = </em>{0 = Individuo 1; 1 = individuo 2; 2 = individuo 3}</p>
<p>Donde todos los <strong>x<em><sub>ij</sub></em> son enteros no negativos</strong>. (Ya que queremos determinar cantidad de botellas, es decir que las variables de decisión no están formuladas en función del contenido).</p>
<p>Este modelo puede abordar las restricciones de volumen de líquido (contenido igual para todos los individuos), por medio de coeficientes de contenido, o, definiendo que el contenido corresponde a una variable, la cual debe declararse de igual forma. Ya que el contenido que se encuentra en una botella llena, por ejemplo, es el mismo sea asignado a cualquier individuo, la manera más simple de abordarlo es por medio de coeficientes.</p>
<p>En la formulación del modelo de <em>Python</em> lo abordaremos por medio de variables con fines prácticos.</p>
<p><em>La función objetivo es artificial, dado que el modelo no pretende maximizar o minimizar algún factor. Por lo tanto podemos utilizar cualquier coeficiente, por ejemplo cero.</em></p>
<p><span>Zmax = 0</span><strong>x<em><sub>00</sub></em> + </strong>0<strong>x<em><sub>01</sub></em>  +  </strong>0<strong>x<em><sub>02</sub></em>  + </strong>0<strong>x<em><sub>10</sub></em> + </strong>0<strong>x<em><sub>11</sub></em>  +  </strong>0<strong>x<em><sub>12</sub></em>  + </strong>0<strong>x<em><sub>20</sub></em></strong><span><strong> + </strong>0<strong>x<em><sub>21</sub></em>  +  </strong>0<strong>x<em><sub>22</sub></em></strong>  </span></p>
<p><em>Sujeto a las siguientes restricciones:</em></p>
<p><span>x</span><em><sub>00</sub></em><span> + x<em><sub>01</sub></em>  +  x<em><sub>02</sub></em>  = 7</span></p>
<p><span>x</span><em><sub>10</sub></em><span> + x<em><sub>11</sub></em>  +  x<em><sub>12</sub></em>  = 7</span></p>
<p><span>x</span><em><sub>20</sub></em><span> + x<em><sub>21</sub></em>  +  x<em><sub>22</sub></em>  = 7</span></p>
<p>Las anteriores restricciones limitan la disponibilidad de botellas de cada tipo. Es decir, por ejemplo, la sumatoria de botellas llenas enviadas a los individuos 1, 2 y 3 deberá ser igual a 7; así mismo para el restante tipo de botellas.</p>
<p><span>x</span><em><sub>00</sub></em><span> + x<em><sub>10</sub></em>  +  x<em><sub>20</sub></em>  = 7</span></p>
<p><span>x</span><em><sub>01</sub></em><span> + x<em><sub>11</sub></em>  +  x<em><sub>21</sub></em>  = 7</span></p>
<p><span>x</span><em><sub>02</sub></em><span> + x<em><sub>12</sub></em>  +  x<em><sub>22</sub></em>  = 7</span></p>
<p>Las anteriores restricciones indican que cada individuo deberá recibir exactamente 7 botellas sin importar el tipo de las mismas. Es decir, por ejemplo, la sumatoria de botellas tipo 0, 1 y 2 enviadas al individuo 0, deberá ser igual a 7; así mismo para los individuos restantes.</p>
<p>Respecto a las restricciones de contenido, que limitarán el modelo para que cada individuo reciba la misma cantidad de vino, podemos realizar una operación previa, en la cual determinemos la cantidad total de vino disponible.</p>
<p><em>Vino disponible = 1( 7 botellas llenas) + 0,5( 7 botellas medias)</em></p>
<p><em>Vino disponible = 10,5 </em></p>
<p>Así entonces, para que a cada individuo le corresponda la misma cantidad de vino en la distribución de botellas, deberá dividirse el vino disponible entre el total de individuos.</p>
<p><em>Vino para cada individuo = (10,5 / 3) = 3,5</em></p>
<p>Así entonces, las restricciones de equidad en la distribución (contenido) serán las siguientes:</p>
<p><strong>x<em><sub>00</sub></em></strong><span> + 0,5<strong>x<em><sub>10</sub></em></strong>   = 3,5</span></p>
<p><strong>x<em><sub>01</sub></em></strong><span> + 0,5<strong>x<em><sub>11</sub></em></strong>  = 3,5</span></p>
<p><strong>x<em><sub>02</sub></em></strong><span> + 0,5<strong>x<em><sub>12</sub></em></strong>  = 3,5</span></p>
<p><span>Así entonces, tenemos el problema completamente modelado.</span></p>
<hr />
<h2>Resolución del modelo mediante Google OR-Tools</h2>
<p><span>De acuerdo a lo mencionado en el artículo de </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><span>, esta herramienta soporta múltiples lenguajes de programación, en esta ocasión, haremos uso del lenguaje de programación Python.</span></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 ortools.linear_solver import pywraplp
</code></pre>
</div>
<h3><em>Paso 2: Declarar el solucionador
		<div id="paso-2-declarar-el-solucionador" data-title="Paso 2: Declarar el solucionador" class="index-title"></div>
	</em></h3>
<p>El siguiente fragmento de código declara el solucionador SCIP <em>(Solving Constraint Integer Programs), un solucionador de código abierto disponible (Google OR-Tools posee múltiples solucionadores):</em></p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code><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. En este caso, la matriz de contenido de las botellas distribuidas a los 3 individuos (matriz 3 x 3).</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">contenido = [
    [  1,   1,   1],
    [0.5, 0.5, 0.5],
    [  0,   0,   0],
]
num_botellas = len(contenido)
num_individuos = len(contenido[0])</span></code></pre>
</div>
<h3><em>Paso 4: Crear las variables del modelo
		<div id="paso-4-crear-las-variables-del-modelo" data-title="Paso 4: Crear las variables del modelo" class="index-title"></div>
	</em></h3>
<p>El siguiente fragmento crea las variables del modelo mediante un bucle (Hace uso número de botellas y el número de individuos), definiendo las variables x [i, j]. Así mismo, se declara el rango de valores que pueden tomar las variables, del mismo modo su naturaleza: <em>variables enteras </em>(solver.IntVar). Esta declaración sustituye las restricciones de no-negatividad (0, solver.infinity()), es decir, mayores a cero.</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code><span class="pln">  x = {}
  for i in range(num_botellas):
      for j in range(num_individuos):
          x[i, j] = solver.IntVar(0, solver.infinity(), '')
</span></code></pre>
</div>
<h3><em>Paso 5: Definir las restricciones del modelo
		<div id="paso-5-definir-las-restricciones-del-modelo" data-title="Paso 5: Definir las restricciones del modelo" class="index-title"></div>
	</em></h3>
<p>El siguiente fragmento de código define las restricciones del modelo mediante bucles:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code><span class="pln"># Restricciones de disponibilidad de botellas de cada tipo = 7
# Para cada i (tipo de botella), suma sus posibles variaciones de j (individuos)
# Por ejemplo, siendo i = 0, sumará X00 + X01 + X02, esta sumatoria
# deberá ser igual a 7 (botellas disponibles de cada tipo)
  for i in range(num_botellas):
      solver.Add(solver.Sum([x[i, j] for j in range(num_individuos)]) == 7)
# Restricciones de cantidad de botellas asignadas a cada individuo
# Para cada j (individuo), suma sus posibles variaciones de i (tipos de botella)
# Por ejemplo, siendo j = 0, sumará X00 + X10 + X20, esta sumatoria
# deberá ser igual a 7 (botellas asignadas a un individuo sin importar el tipo)
  for j in range(num_individuos):
      solver.Add(solver.Sum([x[i, j] for i in range(num_botellas)]) == 7)
# Restricciones de equidad en la distribución (utiliza la matriz de contenido)
# Para cada j (individuo), suma los productos de las posibles
# variaciones de i (tipo de botella) por sus coeficientes de contenido
# Por ejemplo, siendo j = 0 y C[i][j] equivalente al contenido
# de una botella tipo i entregado a un individuo tipo j
# sumará (C00 * X00) + (C10 * X10) + (C20 * X20), los valores de C[i][j]
# los tomará de la matriz de contenido. Esta sumatoria
# deberá ser igual a 3,5 (distribución equitativa por individuo)
  for j in range(num_individuos):
      solver.Add(solver.Sum([contenido[i][j] * x[i, j] for i in range(num_botellas)]) == 3.5)
</span></code></pre>
</div>
<h3><em>Paso 6: Definir la función objetivo del modelo
		<div id="paso-5-definir-la-funcion-objetivo-del-modelo" data-title="Paso 5: Definir la función objetivo del modelo" class="index-title"></div>
	</em></h3>
<p>El siguiente fragmento de código define la función objetivo del modelo. Consideremos que no es importante el criterio de la función, tampoco existe un costo asociado a las variables de decisión. Sin embargo, formularemos una función objetivo basada en bucles (utilizando la matriz de contenido), la cual quizá puede ser de utilidad en modelamientos futuros. Los coeficientes de las variables de decisión se basarán en la matriz de contenido (contenido[i][j]).</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code><span class="pln"># Función objetivo
  objective_terms = []
  for i in range(num_botellas):
      for j in range(num_individuos):
          objective_terms.append(contenido[i][j] * x[i, j])
  solver.Maximize(solver.Sum(objective_terms))
</span></code></pre>
</div>
<h3><em>Paso 7: Invocar el solucionador
		<div id="paso-6-invocar-el-solucionador" data-title="Paso 6: Invocar el solucionador " class="index-title"></div>
	</em></h3>
<p>El siguiente fragmento de código sirve para invocar el solucionador del modelo:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code><span class="pln">status = solver.Solve()
</span></code></pre>
</div>
<h3><em>Paso 8: Definir las salidas del solucionador
		<div id="paso-7-definir-las-salidas-del-solucionador" data-title="Paso 7: Definir las salidas del solucionador" class="index-title"></div>
	</em></h3>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code><span class="pln"># Configura los parámetros de impresión, las salidas del modelo
botellas_ind0 = 0
botellas_ind1 = 0
botellas_ind2 = 0  
if status == pywraplp.Solver.OPTIMAL or status == pywraplp.Solver.FEASIBLE:
      print('Puntaje total = ', solver.Objective().Value(), '\n')
      for i in range(num_botellas):
          for j in range(num_individuos):
              # Test if x[i,j] is 1 (con tolerancia de punto flotante)
              if x[i, j].solution_value() &gt; 0.5:
                print('Botellas del tipo %d asignadas al individuo %d.  Cantidad = %d' %
                          (i, j, x[i, j].solution_value()))
      for i in range(num_botellas):
          botellas_ind0 = x[i, 0].solution_value() + botellas_ind0
      for i in range(num_botellas):
          botellas_ind1 = x[i, 1].solution_value() + botellas_ind1
      for i in range(num_botellas):
          botellas_ind2 = x[i, 2].solution_value() + botellas_ind2
  print('Número de botellas asignadas al individuo 0:', botellas_ind0)
  print('Número de botellas asignadas al individuo 1:', botellas_ind1)
  print('Número de botellas asignadas al individuo 2:', botellas_ind2)
</span></code></pre>
</div>
<p>En este caso, configuramos las salidas del solucionador. Nos deberá indicar la cantidad de botellas de cada tipo que deberán ser distribuidas a cada individuo. El valor de la función objetivo (contenido total), nos servirá para verificar la solución (10,5).</p>
<p>Como información adicional, hemos configurado algunas impresiones (arbitrarias) para que nos detalle la cantidad de botellas que le deberán ser asignadas a cada individuo.</p>
<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 optimización lineal.</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/1USpjLdh8Iqd5uPmOy7CzpqWPYWPAwq8U?usp=sharing"><strong>Programación Lineal Entera</strong></a>.</em></p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code><span class="pln"># Caso: Investigación de Operaciones (9na edición), de Hamdy A. Taha 
# (University of Arkansas, Fayetteville), (Conjunto de problemas 9.1A - Problema 3)
# Modelo: MSc. Ing. Bryan Salazar López

# 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

contenido = [ 
    [  1,   1,   1], 
    [0.5, 0.5, 0.5],
    [  0,   0,   0],      
] 
num_botellas = len(contenido)
num_individuos = len(contenido[0])


def main():

# Variables del modelo
  x = {}
  for i in range(num_botellas):
      for j in range(num_individuos):
          x[i, j] = solver.IntVar(0, solver.infinity(), '')

  # Las sumatoria de botellas de cada tipo es igual a 7
  # Cada curso podrá tener un máximo de n estudiantes
  for i in range(num_botellas):
      solver.Add(solver.Sum([x[i, j] for j in range(num_individuos)]) == 7)
  for j in range(num_individuos):
      solver.Add(solver.Sum([x[i, j] for i in range(num_botellas)]) == 7)
  for j in range(num_individuos):
      solver.Add(solver.Sum([contenido[i][j] * x[i, j] for i in range(num_botellas)]) == 3.5)



  # Función objetivo con criterio de optimización: minimizar
  objective_terms = []
  for i in range(num_botellas):
      for j in range(num_individuos):
          objective_terms.append(contenido[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
  botellas_ind0 = 0
  botellas_ind1 = 0
  botellas_ind2 = 0
  if status == pywraplp.Solver.OPTIMAL or status == pywraplp.Solver.FEASIBLE:
      print('Contenido total = ', solver.Objective().Value(), '\n')
      for i in range(num_botellas):
          for j in range(num_individuos):
              # Test if x[i,j] is 1 (con tolerancia de punto flotante)
              if x[i, j].solution_value() &gt; 0.5:
                print('Botellas del tipo %d asignadas al individuo %d.  Cantidad = %d' %
                          (i, j, x[i, j].solution_value()))
      for i in range(num_botellas):
          botellas_ind0 = x[i, 0].solution_value() + botellas_ind0
      for i in range(num_botellas):
          botellas_ind1 = x[i, 1].solution_value() + botellas_ind1
      for i in range(num_botellas):
          botellas_ind2 = x[i, 2].solution_value() + botellas_ind2
  print('Número de botellas asignadas al individuo 0:', botellas_ind0)
  print('Número de botellas asignadas al individuo 1:', botellas_ind1)
  print('Número de botellas asignadas al individuo 2:', botellas_ind2)



if __name__ == '__main__':
  main()</span></code></pre>
</div>
<p>Al ejecutar nuestro desarrollo en <em><a href="https://colab.research.google.com/drive/1USpjLdh8Iqd5uPmOy7CzpqWPYWPAwq8U?usp=sharing">Colaboratory</a>, </em>tenemos:</p>
<p><img decoding="async" src="https://ingenieriaindustrialonline.com/wp-content/uploads/2021/04/plentera_solucion.png" alt="plentera_solucion" width="671" height="258" class="aligncenter size-full wp-image-26349" srcset="https://ingenieriaindustrialonline.com/wp-content/uploads/2021/04/plentera_solucion.png 671w, https://ingenieriaindustrialonline.com/wp-content/uploads/2021/04/plentera_solucion-300x115.png 300w" sizes="(max-width: 671px) 100vw, 671px" /></p>
<p>De esta manera se ha hallado una solución óptima al modelo formulado. Esta misma respuesta se encuentra consignada en el libro <em>Investigación de Operaciones de TAHA:</em></p>
<table width="439">
<tbody>
<tr>
<td width="172"></td>
<td width="89" style="text-align: center;">Individuo 1</td>
<td width="89" style="text-align: center;">Individuo 2</td>
<td width="89" style="text-align: center;">Individuo 3</td>
</tr>
<tr>
<td width="172" style="text-align: center;">Botellas llenas</td>
<td width="89" style="text-align: center;">3</td>
<td width="89" style="text-align: center;">1</td>
<td width="89" style="text-align: center;">3</td>
</tr>
<tr>
<td width="172" style="text-align: center;">Botellas medio llenas</td>
<td width="89" style="text-align: center;">1</td>
<td width="89" style="text-align: center;">5</td>
<td width="89" style="text-align: center;">1</td>
</tr>
<tr>
<td width="172" style="text-align: center;">Botellas vacías</td>
<td width="89" style="text-align: center;">3</td>
<td width="89" style="text-align: center;">1</td>
<td width="89" style="text-align: center;">3</td>
</tr>
</tbody>
</table>
<hr />
<p>Ahora bien, el modelo de optimización lineal 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<span> </span><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>
<p>En próximos artículos abordaremos algunos modelos que incorporen la combinación de tipos de variables (continuas y enteras): <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/programacion-lineal-mixta-con-google-or-tools/"><strong><em>programación lineal mixta</em></strong></a>.</p>
<p>La entrada <a href="https://ingenieriaindustrialonline.com/investigacion-de-operaciones/programacion-lineal-entera-con-google-or-tools/">Programación lineal entera con 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/programacion-lineal-entera-con-google-or-tools/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
