Igor M. Coelho
6 de Julho de 2020
Esses slides foram possíveis devido a contribuições de diversas pessoas/materiais, em especial:
Caso não se sintam confiantes nos tópicos abaixo, façam uma revisão antes de aprofundar neste material:
De acordo com Maculan&Fampa (2006)1, as primeiras ideias de como otimizar um sistema de desigualdades lineares foi explorado por Fourier2 em 1880, porém somente George Dantzig3 em 1947 que de fato propôs o método de resolução simplex.
O simplex é um algoritmo reconhecidamente bem-sucedido, tendo sido implementado em diversos solvers de computador altamente eficientes, como CPLEX, Gurobi, CBC (open-source), etc.
Em 1939, L. Kantorovich4 modelou e resolveu matematicamente problemas de planejamento da produção na União Soviética, ganhando o prêmio Nobel de Economia em 1975.
Outros métodos para resolução: Métodos Elipsoidais de L. Khachian5 em 1978; Métodos de Pontos Interiores de N. Karmarkar6 em 1984; embora elegantes (com garantia de tempo polinomial), são tipicamente menos eficientes na prática que o simplex.
Considere o seguinte problema de programação linear:
maximizarf(x)=j=1∑pcjxj Sujeito a: j=1∑paijxj≤bi,i=1,2,...,q xj≥0,j=1,2,...,p
onde: cj, aij e bi são dados (números reais) e xj representa as variáveis de decisão (não-negativas). Consideramos, neste caso, uma função objetivo f(x) de maximização, e restrições do tipo ≤.
Restrições do tipo ≤ (ou ≥) podem ser facilmente transformadas em igualdades, com a introdução de novas variáveis (não-negativas) de folga/falta (do inglês, slack/surplus):
j=1∑paijxj≤bi⟺{∑j=1paijxj+xp+1=bi,xp+i≥0
j=1∑paijxj≥bi⟺{∑j=1paijxj−xp+1=bi,xp+i≥0
Um exemplo de transformação de ≤ em igualdade (introduzindo variável de folga x3):
2x1+3x2≤5⇒2x1+3x2+x3≥0x3=5
O mesmo para restrições ≥ (introduzindo variável x4):
x1+6x2≥7⇒x1+6x2−x4≥0x4=7
Demais técnicas de conversão de variáveis/restrições:
Listamos três tipos fundamentais de PPL7:
Sempre poderemos escrever um problema de programação linear na forma padrão (PPL):
(PPL):maximizarf(x)=j=1∑ncjxj j=1∑naijxj=bi,i=1,2,...,m xj≥0,j=1,2,...,n
tendo assim, n variáveis e m restrições.
De forma equivalente, podemos representar o PPL na forma vetorial: (PPL):maximizarz=cx Ax=b x≥0
onde c=(c1c2...cN), x⊺=(x1x2...xN), b⊺=(b1b2...bm), A=(a1a2...an) e aj⊺=(a1ja2j...amj), isto é, c⊺∈Rn, x∈Rn, b∈Rm, A∈Rm×n e aj∈Rm.
maxx1x1x1x1,+2x2x2+x2x2≤2≤2≤3≥0⇒maxx1x1x1x1,+2x2x2+x2x2,+0x3+x3x3,+0x4+x4x4,+0x5+x5x5=2=2=3≥0
A⎣⎢⎡101011100010001⎦⎥⎤x⎣⎢⎢⎢⎢⎢⎡x1x2x3x4x5⎦⎥⎥⎥⎥⎥⎤=b⎣⎢⎡b1b2b3⎦⎥⎤
(Vide slides prof. Marcone para visualização gráfica)
A matriz Am×n pode ser particionada da seguinte maneira (supondo posto(A)=m, com m colunas independentes):
A=(BN)
onde Bm×m, chamada de matriz básica, é inversível; e Nm×(n−m) é chamada de não-básica. Analogamente, particionamos x e c, tal que: x⊺=(xB⊺xN⊺), c=(cBcN). Vetores xB e cB possuem m componentes associadas à matriz B. Reescrevemos o PPL:
(PPL):maximizarz=cBxB+cNxN BxB+NxN xB≥0,xN≥0
Explicitamos xB em função de xN (Eq. 2.10 em Maculan&Fampa):
xB=B−1b−B−1NxN
Faremos xN=0 e xˉB=B−1b.
Quando xˉB≥0, será uma solução básica viável.
Sejam IB o conjunto dos índices das colunas de A pertencendo à matriz B, e IN os demais índices de A, tal que: IB∩IN=∅ e IB∪IN={1,2,...,n}.
(PPL):maximizarz=cBB−1b−(cBB−1N−cN)xN Sujeito a: xB=B−1b−B−1NxN xB≥0,xN≥0
De acordo com Maculan&Fampa, definiremos:
Então teremos um novo PPL aprimorado:
(PPL):maximizarz=zˉ−j∈IN∑(zj−cj)xj sujeito a: xB=xˉB−j∈IN∑yjxj xB≥0,xj≥0,j∈IN
(PPL)
.
Focaremos agora na versão do Simplex por tabelas, após apresentar um pseudo-código do algoritmo (com base no livro-texto de Arenales).
O Simplex consiste de duas fases, onde a primeira consiste em encontrar uma base B.
Para problemas com restrições ≤, as variáveis de folga introduzidas no modelo irão naturalmente formar uma matriz identidade Im.
Assim, escolheremos essas variáveis de folga como variáveis básicas, atribuindo valor zero a todas as demais variáveis não-básicas (originais do modelo). Teremos assim uma base inversível B=Im. Neste caso, a primeira fase do Simplex já é naturalmente efetuada.
Vide “Exemplo 2.26” do livro-texto de Arenales (página 85).
minimizarf(x0,x1)=−x0x0x0−x0x0,−2x1+x1−x1+x1x1≤6≤4≤4≥0
Solução Básica Ótima: xB=(x0,x3,x1), tal que f(xB)=−11
Primeiramente, adicionamos restrições de folga ≤ (novas variáveis x2, x3 e x4), e obtemos uma matriz identidade I3 como base B para o passo 1 do Simplex: B=(2,3,4).
Dados do problema:
x0 | x1 | x2 | x3 | x4 | b | |
---|---|---|---|---|---|---|
A | 1 | 1 | 1 | 0 | 0 | 6 |
^ | 1 | -1 | 0 | 1 | 0 | 4 |
^ | -1 | 1 | 0 | 0 | 1 | 4 |
c | -1 | -2 | 0 | 0 | 0 | Min f |
import numpy as np
A=np.array([[1,1,1,0,0],[1,-1,0,1,0],[-1,1,0,0,1]])
b=np.array([6,4,4])
c=np.array([-1, -2, 0, 0, 0])
#
IB=[2,3,4] # variaveis "de folga" na base
IN=[0,1] # variaveis "originais" não-básicas
# Construindo a Base a partir das variáveis dadas
Base=np.transpose(np.asarray([A[:,IB[0]], A[:,IB[1]],
A[:,IB[2]]]))
#>>> Base
#array([[1, 0, 0],
# [0, 1, 0],
# [0, 0, 1]])
Passo 1 - Cálculo da solução básica (resolva B⋅xB=b) e obtenha: x^B=⎝⎜⎛644⎠⎟⎞
Passo 2 - Calcule custos relativos (para N0 e N1): cB=(cB(0),cB(1),cB(2)), B⊺λ=cB, onde λ⊺=(0,0,0).
Passo 3 dispensado (c^1=−2<0), solução não é ótima! Vamos ao passo 4 para cálculo da direção simplex: resolva By=a1 e obtenha y⊺=(1−11).
y = np.linalg.inv(Base).dot(a1)
#>>> y
#array([ 1., -1., 1.])
#>>> x
#array([6., 4., 4.])
#>>> x/y
#array([ 6., -4., 4.])
Escolhemos ε^=y2x^B(2)=4, então xB(2)=x4 sai da base: B=(2,3,1), N=(0,4), f(x)=f(x^)+c^N(k)ε^=0−2×4=−8.
Passo 1 - Cálculo da solução básica (resolva B⋅xB=b) e obtenha: x^B=⎝⎜⎛284⎠⎟⎞
IB=[2,3,1] # variaveis na base
IN=[0,4] # variaveis fora da base
# Construindo a Base a partir das variáveis dadas
Base=np.transpose(np.asarray([A[:,IB[0]], A[:,IB[1]],
A[:,IB[2]]]))
x = np.linalg.inv(Base).dot(b)
#>>> x
#array([2., 8., 4.])
Avance nos passos 2-6 e obtenha: B=(0,3,2), N=(2,4).
Passo 1 - Cálculo da solução básica (resolva B⋅xB=b) e obtenha: x^B=⎝⎜⎛185⎠⎟⎞
IB=[0,3,1] # variaveis na base
IN=[2,4] # variaveis fora da base
# Construindo a Base a partir das variáveis dadas
Base=np.transpose(np.asarray([A[:,IB[0]], A[:,IB[1]],
A[:,IB[2]]]))
x = np.linalg.inv(Base).dot(b)
#>>> x
#array([1., 8., 5.])
Avance ao passo 2 e descubra que solução é ótima!
Obtenha valor f(x)=−11 na solução ótima x^⊺=(1,5,0,8,0):
IB=[0,3,1] # variaveis na base
IN=[2,4] # variaveis fora da base
# Construindo a Base a partir das variáveis dadas
Base=np.transpose(np.asarray([A[:,IB[0]], A[:,IB[1]],
A[:,IB[2]]]))
x = np.linalg.inv(Base).dot(b)
#>>> x
#array([1., 8., 5.])
cB = [ c[IB[0]], c[IB[1]], c[IB[2]] ]
#>>> sum(cB*x)
#-11.0
Uma versão prática do Simplex pode ser feita com tabelas (tableau simplex).
No caso de não haver apenas restrições ≤, é necessário criar variáveis artificiais, bem como um novo problema de otimização que busca minimizar o valor delas (a zero!). Nesse PPL estendido, o peso inicial é 0 para as variáveis do PPL original, e 1 para as artificiais. Quando a otimalidade é atingida nesse modelo (e as variáveis artificiais saem da base), podemos cortar as variáveis artificiais, e retornar ao modelo original (fase 2).
Os slides do prof. Marcone detalham o passo-a-passo dessa abordagem: Slides SIMPLEX (pdf).
A lista de exercícios está disponibilizada no site.
N. Maculan e M. Fampa. Otimização Linear. Editora UnB, 2006.↩︎
Fourier, J.B.J. Oeuvres. “Second Extrait”, G. Darboux, Gauthiers-Villars, p. 325-328, 1880.↩︎
Dantzig, George B. Maximization of a linear function of variables subject to linear inequalities. Activity Analysis of Production and Allocation. In: KOOPMANS, C. (Ed.). New York: Wiley, p. 359-373, 1951.↩︎
Kantorovich, L. Métodos Matemáticos na Organização e no Planejamento da Produção (em russo). Leningrado: Editora da Univ. Estatal de Leningrado, 1939 (tradução inglesa: Management Science, v.6, p. 366-422, 1960).↩︎
Khachian, L. A polynomial algorithm for linear programming. Doklady Academiia Nauk SSSR, v.244, p.191-194 (em russo. Tradução em inglês: Soviet Mathematics Doklady, v.20, p.191-194, 1979.).↩︎
Karmarkar, N. A new polynomial algorithm for linear programming. Combinatorica, v.4, p.373-395, 1984.↩︎
Christos Papadimitriou & Kenneth Steiglitz. Combinatorial Optimization, 1982 (1998).↩︎