PES Pesquisa Operacional

Prof. Milton Procópio de Borba

Originais do Prof. Fernando Deeke Sasse

2. Programação Linear : Método Gráfico

2.1 Introdução

Um dos métodos mais simples o poderosos da Pesquisa Operacional é a Programação Linear. Normalmente este é o primeiro tópico em todos os cursos de pesquisa Operacional.

Programação linear é uma técnica de otimização flexível e poderosa utilizada para determinar os valores não negativos de n variáveis de decisão x[j] que satisfazem m restrições lineares

sum(a[i,j]*x[j],j = 1 .. n) <=, = >= b[i] , i = 1,2, ... m ,

e maximizar (ou minimizar) uma função objetivo linear

z = sum(c[j]*x[j],j = 1 .. n) ,

onde os parâmetros a[i,j] , b[i] e c[j] são constantes dadas.

A origem da programação linear está em um artigo de G. B. Danzig [1] em 1951, que desenvolveu um método algébrico muito eficiente para resolver problemas de Programação Linear, denominado método simplex. Nas próximas seções descreveremos a matemática do método simplex, e aprenderemos a resolver problemas de PL utilizando o pacote simplex do Maple.

2.2 Exemplo1 : produção de brinquedos

Formulação do problema

Para motivar a discussão, iremos formular um problema simples de programação linear envolvendo duas variáveis de decisão e três restrições, obtendo a solução gráfica de forma semelhante àquela utilizada no exemplo da Duas Minas (Word_ZIP ou Maple_ZIP ou Excel_ZIP)

Suponha que temos uma empresa que produz carros de brinquedo e trens de brinquedo. O Departamento de Contabilidade analisou os custos e lucros e determinou que para cada carro produzido (e imediatamente vendido) havia um lucro de $30, e para cada trem, $40. Temos dois departamentos onde esses brinquedos são produzidos. O departamento de carros tem uma capacidade de produção diaria de 90 unidades, e o departamento de trens, 60 unidades. Um fator complicante na produção destes brinquedos é uma parte especial que deve ser comprada de um fornecedor externo que pode fornecer somente 600 unidades por dia. Segundo o departamento de engenharia, cada carro necessita 5 partes, e cada trem 6 partes. Temos que determinar a produção diária de carros e trens de forma a maximizar o lucro diário.

Neste problema temos duas variáveis de decisão:

x[1] - número de carros / dia

x[2] - número de trens / dia

A função-objetivo a ser maximizada é o lucro diário, dado por:

z = 30*x[1]+40*x[2] .

Nossas restrições são dadas por

x[1] <= 90 , x[2] <= 60 - limites de capacidade de produção de cada departamento,

5*x[1]+6*x[2] <= 600 - limites das peças especiais.

Temos ainda as restrições naturais 0 <= x[1] , 0 <= x[2] .

Ver solução no Excel 

Solução Gráfica

Como temos somente duas variáveis de decisão, a solução gráfica é viável, de modo que podemos proceder como no caso da Companhia de Duas Minas.

Vamos obter inicialmente a região factível:

> restart:

> with(plots):

Warning, the name changecoords has been redefined

> Rest:=[5*x1+6*x2<=600,x1<=90,x2<=60,x1>=0,x2>=0];

Rest := [5*x1+6*x2 <= 600, x1 <= 90, x2 <= 60, 0 <=...

> Regiao_factivel:=inequal(Rest, x1=0..130,x2=0..80, optionsfeasible=(color=blue),optionsexcluded=(color=white)):

>

>

> display([Regiao_factivel]);

[Maple Plot]

>

Vamos agora inserir neste gráfico algumas retas correspondendo a valores particulares de lucro diário:

> curvas_de_lucro:=contourplot(30*x1+40*x2,x1=0..140,x2=0..120,contours=[1800,3000,4000],linestyle=4,numpoints=1000,color=black):

> display([Regiao_factivel,curvas_de_lucro]);

[Maple Plot]

Observe que a linha correspondente a z = 4000 corresponde a uma solução não factível para o problema. É óbvio neste problema que a solução factível que maximiza o lucro é aquela que passa pelo vértice dado pela intersecção da reta 5*x[1]+6*x[2] = 600 com a reta x[2] = 60 :

> sol:=solve({5*x1+6*x2 = 600,x2=60},{x1,x2});

sol := {x1 = 48, x2 = 60}

> assign(sol);

Com essa solução o lucro será

> z:=30*x1+40*x2;

z := 3840

>

De fato, podemos verificar o resultado no gráfico.

> unassign('x1', 'x2'):

> lucro_maximo:=implicitplot(30*x1+40*x2=3840,x1=0..140,x2=0..120,linestyle=3,numpoints=1000,color=red):

> display([Regiao_factivel,lucro_maximo]);

[Maple Plot]

Um modo mais compacto para fazer o cálculo anterior é

> with(simplex):

Warning, the name display has been redefined

Warning, the protected names maximize and minimize have been redefined and unprotected

> solve(convert({Rest[1],Rest[3]},equality));

{x1 = 48, x2 = 60}

> assign(%):

> z:=30*x1+40*x2;

> x1:='x1':x2:='x2':

z := 3840

A região factível no exemplo acima é um exemplo de região convexa. Vamos definir formalmente o conceito de região convexa e ponto extremo de uma região convexa.

Definição 1 Um conjunto F é dito convexo se para quaisquer dois pontos x1 e x2 em F, o segmento que liga os dois pontos está inteiramente dentro de conjunto, ou seja, x = lambda(x1 - x2) + x2 pertence a F para 0 <= lambda £ 1.

Intuitivamente um conjunto convexo não pode ter buracos, e suas fronteiras devem ser planas e retas ligando dois vértices quaisquer não devem sair do polígono.

Definição 2 Um ponto x é dito ser um ponto extremo de um conjunto convexo se e somente se não há outros pontos x1 e x2 (x1 <> x2) no conjunto tais que x = lambdax1 + (1- lambda) x2 , 0 <= lambda£ 1.

Intuitivamente, um ponto extremo não pode estar situado "entre" dois outros pontos do conjunto.

É possível mostrar que, em problemas de programação linear, as regiões factíveis são sempre convexas. Além disso, se a região convexa factível correspondente ao problema de programação linear é não vazia, ela deve ter ao menos um extremo. Além disso, se há uma solução finita ótima para o programa linear, então esta solução deve ser um ponto extremo da região factível. No nosso exemplo anterior a região factível possui 5 pontos extremos. Formalmente deveríamos testar todos os pontos extremos, mas normalmente, em problemas 2-dimensionais o método gráfico-visual é apropriado, especialmente quando o número de restrições (número de pontos extremos) é muito alto.

Por outro lado, se temos n = 3 variáveis de decisão torna-se mais difícil a visualização. Para n >3 ela é impossível. Modelos de problemas da vida real podem ter até milhares de variáveis e condições de restrição. Neste caso é utilizada uma técnica matemática denominada método simplex .

2.3 Exemplo2 : problema algébrico

Como já mencionamos acima, em problemas onde temos mais de três variáveis de decisão, um método alternativo ao gráfico deve ser desenvolvido. Vamos introduzir mais tarde o método simplex, desenvolvido por Danzig em 1947. Vamos considerar o seguinte problema de programação linear:

max z = x[1]+2*x[2]

-x[1]+3*x[2] <= 9

x[1]-2*x[2] <= 0

2*x[1]+x[2] <= 10

5 <= 2*x[1]+x[2]

x[1]-.1*x[2] <= 3

0 <= x[1] , 0 <= x[2]

Embora este problema tenha uma solução gráfica simples, por possuir somente duas variáveis de decisão, vamos tratá-lo de uma forma mais geral.

Graficamente obtemos

> restart:

> with(plots):

Warning, the name changecoords has been redefined

>

> Rest:=[ -x1+3*x2 <= 9, x1-2*x2 <= 0,2*x1+x2 <= 10,x1-0.1*x2<=3,5 <= 2*x1+x2, x1>=0,x2>=0];

Rest := [-x1+3*x2 <= 9, x1-2*x2 <= 0, 2*x1+x2 <= 10...

> Regiao_factivel:=inequal(Rest, x1=0..5,x2=0..5, optionsfeasible=(color=blue),optionsexcluded=(color=white)):

> retamax:=contourplot(x1+2*x2,x1=0..5,x2=0..5,contours=[5,6,9],linestyle=4,numpoints=1000,color=black):

> display([Regiao_factivel,retamax]);

[Maple Plot]

> with(simplex):

> solve(convert({Rest[1],Rest[3]},equality));

{x1 = 3, x2 = 4}

> assign(%):

> z:=x1+2*x2;

z := 11

> x1:='x1':x2:='x2':

>

Embora neste exemplo a localização do vértice por onde passa a reta que corresponde à solução maximal seja ótima, o procedimento algorítmico consiste em determinar (x,y) para todos os possíveis vértices, calcular z em cada um deles e tomar o maior (descartando os não factíveis). Isso implicaria na resolução de binomial(7,2) = 7!/2!/(7-2)!= 21 sistemas 2x2. (5 restrições impostas + 2 de não-negatividade). Observe que nem todos os vértices aparecemm no gráfico acima e que a maioria deles corresponde a pontos não-factíveis. Em geral, se temos m+n restrições com n variáveis de decisão, temos que resolver binomial(n+m, n) = (n+m)! / n! m! sistemas de equações n x n. Esse número é muito grande mesmo para um problema relativamente pequeno. Por exemplo, se temos n = 10 variáveis e m = 5 restrições, teremos que resolver 3003 sistemas de 10 equações e 10 incógnitas. Mesmo para computadores, tal algoritmo seria não prático para problemas envolvendo milhares de variáveis e restrições.

2.4 Exercício

1. Considere o seguinte problema de programação linear com duas variáveis de decisão:

maximize 20*x[1]+30*x[2] ,

tal que

x[1]/2+x[2] <= 8

x[1]+x[2] <= 10

4 <= x[2]

0 <= x[1] .

Resolva o problema graficamente e depois utilizando o pacote simplex do Maple.