Pesquisa Operacional

Igor M. Coelho

6 de Julho de 2020

Método Simplex

Sobre esse material

Esses slides foram possíveis devido a contribuições de diversas pessoas/materiais, em especial:

  • Notas do prof. Marcone Jamilson Freitas Souza
  • Livro Nelson Maculan e Marcia Fampa
  • Livro-texto do curso
  • [2] Tutorial ilectures (https://igormcoelho.github.io/ilectures-pandoc/)
  • Minha esposa Cristiane Tavares pelas valiosas dicas na elaboração desse material

Fundamentos Necessários

Caso não se sintam confiantes nos tópicos abaixo, façam uma revisão antes de aprofundar neste material:

  • Álgebra Linear e Geometria Analítica
    • Equação da Reta
    • Operações Vetoriais
    • Operações com Matrizes
  • Métodos Numéricos
    • Método da Eliminação de Gauss
  • Cálculo
    • Gradientes e Otimização

História do Simplex

Breve história

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.

Aplicações no planejamento da produção e outros métodos

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.

Fundamentos do Simplex

Um Problema de Programação Linear

Considere o seguinte problema de programação linear:

maximizar  f(x)=j=1pcjxjmaximizar \; f(x) = \sum_{j=1}^p c_j x_j Sujeito a: j=1paijxjbi,  i=1,2,...,q\sum_{j=1}^p a_{ij}x_j \leq b_i, \; i=1,2,...,q xj0,  j=1,2,...,px_j \geq 0, \; j=1,2,...,p

onde: cjc_j, aija_{ij} e bib_i são dados (números reais) e xjx_j representa as variáveis de decisão (não-negativas). Consideramos, neste caso, uma função objetivo f(x)f(x) de maximização, e restrições do tipo \leq.

Variáveis de Folga

Restrições do tipo \leq (ou \geq) 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=1paijxjbi    {j=1paijxj+xp+1=bi,xp+i0\sum_{j=1}^p a_{ij}x_j \leq b_i \iff \begin{cases} \sum_{j=1}^p a_{ij}x_j + x_{p+1} = b_i,\\ x_{p+i} \geq 0 \end{cases}

j=1paijxjbi    {j=1paijxjxp+1=bi,xp+i0\sum_{j=1}^p a_{ij}x_j \geq b_i \iff \begin{cases} \sum_{j=1}^p a_{ij}x_j - x_{p+1} = b_i,\\ x_{p+i} \geq 0 \end{cases}

Variáveis de Folga (exemplo)

Um exemplo de transformação de \leq em igualdade (introduzindo variável de folga x3x_3):

2x1+3x252x1+3x2+x3x30=52x_1 + 3x_2 \leq 5 \Rightarrow 2x_1 + 3x_2 + \underbrace{x_3}_{x_3 \geq 0} = 5

O mesmo para restrições \geq (introduzindo variável x4x_4):

x1+6x27x1+6x2x4x40=7x_1 + 6x_2 \geq 7 \Rightarrow x_1 + 6x_2 - \underbrace{x_4}_{x_4 \geq 0} = 7

Outras conversões à forma padrão

Demais técnicas de conversão de variáveis/restrições:

  • Existe bi<0b_i < 0:
    • Solução: multiplique a restrição ii por 1-1
  • Existem variáveis não positivas (seja xk0x_k \leq 0):
    • Solução: Substituir por variável xk0x_k' \geq 0 tal que xk=xkx_k' = -x_k
  • Existem variáveis livres xk0x_k \gtrless 0 (seja xkRx_k \in \mathbb{R}):
    • Solução: substituir xkx_k por xkxkx_k' - x_k'', tal que xk0x_k' \geq 0 e xk0x_k'' \geq 0
  • Um problema de minimização pode ser convertido em maximização (vice-versa): maximizar  f(x)=minimizar  {f(x)} maximizar \; f(x) = - minimizar \; \{ - f(x) \}

Tipos de PPL

Listamos três tipos fundamentais de PPL7:

  • padrão (standard): Ax=bAx=b e x0x\geq 0
  • canônico (canonical): AxbAx \geq b e x0x\geq 0
  • geral (general): aix=bia_i x=b_i (  iM\forall\;i \in M), aixbia_i x \geq b_i (  iMˉ\forall\;i \in \bar{M}), xj0x_j \geq 0 (  jN\forall\;j \in N), xj0x_{j} \gtrless 0 (  jNˉ\forall\;j \in \bar{N})

Problema de Programação Linear Padrão

Sempre poderemos escrever um problema de programação linear na forma padrão (PPL):

(PPL):  maximizar  f(x)=j=1ncjxj(PPL):\; maximizar \; f(x) = \sum_{j=1}^n c_j x_j j=1naijxj=bi,  i=1,2,...,m\sum_{j=1}^n a_{ij} x_j = b_i, \; i=1,2,...,m xj0,  j=1,2,...,nx_j \geq 0, \; j=1,2,...,n

tendo assim, nn variáveis e mm restrições.

Problema de Programação Linear Padrão (vetores)

De forma equivalente, podemos representar o PPL na forma vetorial: (PPL):  maximizar  z=cx(PPL):\; maximizar \; z = cx Ax=bAx = b x0x \geq 0

onde c=(c1  c2  ...  cN)c=(c_1\;c_2\;...\;c_\mathcal{N}), x=(x1  x2  ...  xN)x^{\intercal} = (x_1\;x_2\;...\;x_\mathcal{N}), b=(b1  b2  ...  bm)b^{\intercal} = (b_1\;b_2\;...\;b_m), A=(a1  a2  ...  an)A=(a_1\;a_2\;...\;a_n) e aj=(a1j  a2j  ...amj)a_j^{\intercal} = (a_{1j} \; a_{2j} \; ... a_{mj}), isto é, cRnc^{\intercal} \in \mathbb{R}^n, xRnx \in \mathbb{R}^n, bRmb \in \mathbb{R}^m, ARm×nA \in \mathbb{R}^{m\times n} e ajRma_j \in \mathbb{R}^m.

Definição 2.1 (Maculan&Fampa)
Seja X={xRnAx=b,x0}X=\{x \in \mathbb{R}^n|Ax=b, x\geq 0 \} a região viável do PPL, e xXx \in X uma solução viável do PPL. Se xXx^* \in X tal que cxcx,xXcx^* \geq cx, \forall x\in X, xx^* é uma solução ótima.

Exemplo de PPL

maxx1+2x2x12x22x1+x23x1,x20    maxx1+2x2+0x3+0x4+0x5x1+x3=2x2+x4=2x1+x2+x5=3x1,x2,x3,x4,x50 \begin{matrix} max & x_1 & +2x_2 \\ & x_1 & & \leq 2\\ & & x_2 & \leq 2\\ & x_1 & +x_2 & \leq 3\\ & x_1,& x_2 & \geq 0\\ \end{matrix} \; \Rightarrow \; \begin{matrix} max & x_1 & +2x_2 & +0x_3 & +0x_4 & +0x_5\\ & x_1 & & +x_3 & & & = 2\\ & & x_2 & & +x_4 & & = 2\\ & x_1 & +x_2 & & & +x_5 & = 3\\ & x_1,& x_2, & x_3, & x_4, & x_5 & \geq 0\\ \end{matrix}

[101000101011001]A[x1x2x3x4x5]x=[b1b2b3]b \underbrace { \begin{bmatrix} 1 & 0 & 1 & 0 & 0\\ 0 & 1 & 0 & 1 & 0\\ 1 & 1 & 0 & 0 & 1\\ \end{bmatrix} }_{A} \underbrace { \begin{bmatrix} x_1\\ x_2\\ x_3\\ x_4\\ x_5\\ \end{bmatrix} }_{x}= \underbrace { \begin{bmatrix} b_1\\ b_2\\ b_3\\ \end{bmatrix} }_{b}

(Vide slides prof. Marcone para visualização gráfica)

Matriz básica e não-básica

A matriz Am×nA_{m \times n} pode ser particionada da seguinte maneira (supondo posto(A)=mposto(A)=m, com mm colunas independentes):

A=(B  N)A = ( B \; N )

onde Bm×mB_{m \times m}, chamada de matriz básica, é inversível; e Nm×(nm)N_{m \times (n-m)} é chamada de não-básica. Analogamente, particionamos xx e cc, tal que: x=(xB  xN)x^{\intercal} = (x_\mathcal{B}^{\intercal} \; x_\mathcal{N}^{\intercal}), c=(cB  cN)c = (c_\mathcal{B} \; c_\mathcal{N}). Vetores xBx_\mathcal{B} e cBc_\mathcal{B} possuem mm componentes associadas à matriz BB. Reescrevemos o PPL:

(PPL):  maximizar  z=cBxB+cNxN(PPL): \; maximizar \; z = c_\mathcal{B} x_\mathcal{B} + c_\mathcal{N} x_\mathcal{N} BxB+NxNBx_\mathcal{B} + Nx_\mathcal{N} xB0,xN0x_\mathcal{B}\geq 0, x_\mathcal{N} \geq 0

Solução básica e não-básica

Explicitamos xBx_\mathcal{B} em função de xNx_\mathcal{N} (Eq. 2.10 em Maculan&Fampa):

xB=B1bB1NxNx_\mathcal{B} = B^{-1}b - B^{-1}Nx_\mathcal{N}

Faremos xN=0x_\mathcal{N}=0 e xˉB=B1b\bar{x}_\mathcal{B} = B^{-1}b.

Definição 2.2 (Maculan&Fampa)
xˉ\bar{x} é uma solução básica, se xˉ=(xˉB  0)\bar{x}^{\intercal} = (\bar{x}_\mathcal{B}^{\intercal} \; 0).

Quando xˉB0\bar{x}_\mathcal{B} \geq 0, será uma solução básica viável.

Sejam IBI_\mathcal{B} o conjunto dos índices das colunas de AA pertencendo à matriz BB, e INI_\mathcal{N} os demais índices de AA, tal que: IBIN=I_\mathcal{B} \cap I_\mathcal{N} = \varnothing e IBIN={1,2,...,n}I_\mathcal{B} \cup I_\mathcal{N} = \{ 1,2, ..., n\}.

PPL com matriz básica

(PPL):  maximizar  z=cBB1b(cBB1NcN)xN(PPL): \; maximizar \; z = c_\mathcal{B}B^{-1}b - (c_\mathcal{B}B^{-1}N - c_\mathcal{N})x_\mathcal{N} Sujeito a: xB=B1bB1NxNx_\mathcal{B}=B^{-1}b - B^{-1}Nx_\mathcal{N} xB0,xN0x_\mathcal{B} \geq 0, x_\mathcal{N} \geq 0

PPL com notação aprimorada

De acordo com Maculan&Fampa, definiremos:

  • λ=cBB1\lambda = c_\mathcal{B}B^{-1}, λRm\lambda^{\intercal} \in \mathbb{R}^m
  • xˉB=B1b\bar{x}_\mathcal{B} = B^{-1}b, xˉBRm\bar{x}_\mathcal{B} \in \mathbb{R}^m
  • zj=λajz_j = \lambda a_j, (jIBIN)(j \in I_\mathcal{B} \cup I_\mathcal{N}), zjRz_j \in \mathbb{R}
  • yj=B1ajy_j = B^{-1} a_j, (jIBIN)(j \in I_\mathcal{B} \cup I_\mathcal{N}), yjRmy_j \in \mathbb{R}^m
  • zˉ=cBB1b=λb=cBxˉB\bar{z} = c_\mathcal{B}B^{-1}b = \lambda b = c_\mathcal{B}\bar{x}_\mathcal{B}.

Então teremos um novo PPL aprimorado:

(PPL):  maximizar  z=zˉjIN(zjcj)xj(PPL): \; maximizar \; z = \bar{z} - \sum_{j \in I_\mathcal{N}}(z_j - c_j)x_j sujeito a: xB=xˉBjINyjxj x_\mathcal{B}=\bar{x}_\mathcal{B} - \sum_{j \in I_\mathcal{N}} y_j x_j xB0,xj0,jINx_\mathcal{B} \geq 0, x_j \geq 0, j \in I_\mathcal{N}

Otimalidade no PPL

Proposição 2.1 (de Maculan&Fampa)
Se xˉB0\bar{x}_\mathcal{B} \geq 0 e zjcj0z_j - c_j \geq 0, jIN\forall j \in I_\mathcal{N}, então o vetor xRnx^* \in \mathbb{R}^n, onde xB(i)=xˉB(i)x^*_{\mathcal{B}(i)} = \bar{x}_{\mathcal{B}(i)}, i=1,2,...,mi=1,2,...,m e xj=0x^*_j=0, jINj \in I_\mathcal{N}, será uma solução ótima do (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).

Detalhamento do Simplex

Simplex para problemas de \leq

O Simplex consiste de duas fases, onde a primeira consiste em encontrar uma base BB.

Para problemas com restrições \leq, as variáveis de folga introduzidas no modelo irão naturalmente formar uma matriz identidade Im\mathcal{I}_m.

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=ImB = \mathcal{I}_m. Neste caso, a primeira fase do Simplex já é naturalmente efetuada.

Pseudo-código do Simplex (Fase II) livro-texto

  1. Passo 1: cálculo da solução básica {xˉB=B1bxˉN=0 \begin{cases} \bar{x}_\mathcal{B} = B^{-1}b\\ \bar{x}_N = 0 \end{cases}
  2. Passo 2: cálculo dos custos relativos
    1. Vetor multiplicador simplex
      • λ=cBB1\lambda^{\intercal} = c_\mathcal{B}^{\intercal}B^{-1}
    2. Custos relativos
      • c^N(j)=cN(j)λaN(j),  j=1,2,...,nm\hat{c}_{N(j)}=c_{N(j)} - \lambda^{\intercal} a_{N(j)}, \; j=1,2,...,n-m
    3. Determinação de variável a entrar na base
      • c^N(k)=min{c^N(j),j=1,...,nm}\hat{c}_{N(k)} = min\{\hat{c}_{N(j)}, j=1,...,n-m\} (a variável xN(k)x_{N(k)} entra na base)
  3. Passo 3: teste de otimalidade (minimização)
    • Se c^N(k)0\hat{c}_{N(k)} \geq 0, então: pare (solução atual é ótima!).

Pseudo-código do Simplex (Fase II) livro-texto

  1. Passo 4: Cálculo da direção Simplex
    • y=B1aN(k)y = B^{-1} a_{\mathcal{N}(k)}
  2. Passo 5: Determinação do passo e variável a sair da base
    • Se y0y \leq 0, então: pare (não existe solução ótima finita: f(x)f(x) \rightarrow -\infty)
    • Caso contrário, determine a variável a sair da base pela razão mínima: ε^=x^B()y=min{x^B(i)yi:yi>0,i=1,...,m}\hat{\varepsilon}=\frac{\hat{x}_{\mathcal{B}(\ell)}}{y_\ell} = min\left\{ \frac{\hat{x}_{\mathcal{B}(i)}}{y_i}: y_i > 0, i = 1, ..., m \right\} (variável xB()x_{\mathcal{B}(\ell)} sai da base)
  3. Passo 6: atualização
    • matriz básica: B=(aB(1)  ...  aB(1)  aN(k)  aB(+1)  ...  aB(m))\mathcal{B}=(a_{\mathcal{B}(1)}\;...\;a_{\mathcal{B}(\ell-1)}\;a_{\mathcal{N}(k)}\;a_{\mathcal{B}(\ell+1)}\;...\;a_{\mathcal{B}(m)})
    • não-básica: N=(aN(1)  ...  aN(k1)  aB()  aN(k+1)  ...  aN(nm))\mathcal{N}=(a_{\mathcal{N}(1)}\;...\;a_{\mathcal{N}(k-1)}\;a_{\mathcal{B}(\ell)}\;a_{\mathcal{N}(k+1)}\;...\;a_{\mathcal{N}(n-m)})
    • incrementa iteração e volte ao Passo 1

Exemplo com Python

Exemplo do Simplex

Vide “Exemplo 2.26” do livro-texto de Arenales (página 85).

minimizar  f(x0,x1)=x02x1x0+x16x0x14x0+x14x0,x10 \begin{matrix} minimizar \; f(x_0,x_1) = & -x_0 & -2x_1\\ & x_0 & +x_1 & \leq 6\\ & x_0 & -x_1 & \leq 4\\ & -x_0 & +x_1& \leq 4\\ & x_0, & x_1 & \geq 0\\ \end{matrix}

Solução Básica Ótima: xB=(x0,x3,x1)x_\mathcal{B}=(x_0, x_3, x_1), tal que f(xB)=11f(x_\mathcal{B}) = -11

Exemplo com Python (dados do problema)

Primeiramente, adicionamos restrições de folga \leq (novas variáveis x2x_2, x3x_3 e x4x_4), e obtemos uma matriz identidade I3\mathcal{I}_3 como base BB para o passo 1 do Simplex: B=(2,3,4)\mathcal{B}=(2,3,4).

Dados do problema:

x0x_0 x1x_1 x2x_2 x3x_3 x4x_4 bb
AA 1 1 1 0 0 6
^ 1 -1 0 1 0 4
^ -1 1 0 0 1 4
cc -1 -2 0 0 0 Min ff

Exemplo com Python (construindo base)

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]])

Exemplo com Python (primeira iteração - passo 1)

Passo 1 - Cálculo da solução básica (resolva BxB=bB\cdot x_\mathcal{B} = b) e obtenha: x^B=(644)\hat{x}_\mathcal{B}= \begin{pmatrix} 6\\4\\4\\ \end{pmatrix}

x = np.linalg.inv(Base).dot(b)
#>>> x
#array([6., 4., 4.])

Exemplo com Python (primeira iteração - passo 2)

Passo 2 - Calcule custos relativos (para N0N_0 e N1N_1): cB=(cB(0),cB(1),cB(2))c_\mathcal{B}=(c_{\mathcal{B}(0)}, c_{\mathcal{B}(1)}, c_{\mathcal{B}(2)}), Bλ=cBB^{\intercal}\lambda=c_\mathcal{B}, onde λ=(0,0,0)\lambda^{\intercal}=(0,0,0).

cB = [ c[IB[0]], c[IB[1]], c[IB[2]] ] 
# calcula "lambda" (chamado 'u' aqui)
u = np.linalg.inv(np.transpose(Base)).dot(cB)
#>>> u
#array([0., 0., 0.])
  • c^0=c0λa0=1\hat{c}_0 = c_0 - \lambda^{\intercal} a_0 = -1
a0 = A[:,0]
cr0 = c[0] - u.dot(a0)
#>>> cr0
#-1.0
  • c^1=c1λa1=2\hat{c}_1 = c_1 - \lambda^{\intercal} a_1 = -2
a1 = A[:,1]
cr1 = c[1] - u.dot(a1)
#>>> cr1
#-2.0

(xB(1)=x1x_{B(1)}=x_1 entra na base)

Exemplo com Python (primeira iteração - passos 3-6)

Passo 3 dispensado (c^1=2<0\hat{c}_1 = -2 < 0), solução não é ótima! Vamos ao passo 4 para cálculo da direção simplex: resolva By=a1By=a_1 e obtenha y=(1  1    1)y^{\intercal}=(1\;-1\;\;1).

y = np.linalg.inv(Base).dot(a1)
#>>> y
#array([ 1., -1.,  1.])
#>>> x
#array([6., 4., 4.])
#>>> x/y
#array([ 6., -4.,  4.])

Escolhemos ε^=x^B(2)y2=4\hat{\varepsilon}=\frac{\hat{x}_{\mathcal{B}(2)}}{y_2}=4, então xB(2)=x4x_{\mathcal{B}(2)}=x_4 sai da base: B=(2,3,1)\mathcal{B}=(2,3,1), N=(0,4)\mathcal{N}=(0,4), f(x)=f(x^)+c^N(k)ε^=02×4=8f(x) = f(\hat{x}) + \hat{c}_{\mathcal{N}(k)}\hat{\varepsilon} = 0 -2\times 4 = -8.

Exemplo com Python (segunda iteração - passos 1-6)

Passo 1 - Cálculo da solução básica (resolva BxB=bB\cdot x_\mathcal{B} = b) e obtenha: x^B=(284)\hat{x}_\mathcal{B}= \begin{pmatrix} 2\\8\\4\\ \end{pmatrix}

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)\mathcal{B}=(0,3,2), N=(2,4)\mathcal{N}=(2,4).

Exemplo com Python (terceira iteração)

Passo 1 - Cálculo da solução básica (resolva BxB=bB\cdot x_\mathcal{B} = b) e obtenha: x^B=(185)\hat{x}_\mathcal{B}= \begin{pmatrix} 1\\8\\5\\ \end{pmatrix}

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!

Exemplo com Python (solução ótima)

Obtenha valor f(x)=11f(x)=-11 na solução ótima x^=(1,5,0,8,0)\hat{x}^{\intercal}=(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

Tableau Simplex

Simplex por Tabelas

Uma versão prática do Simplex pode ser feita com tabelas (tableau simplex).

No caso de não haver apenas restrições \leq, é 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 é 00 para as variáveis do PPL original, e 11 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).

Lista de Exercícios

A lista de exercícios está disponibilizada no site.


  1. N. Maculan e M. Fampa. Otimização Linear. Editora UnB, 2006.↩︎

  2. Fourier, J.B.J. Oeuvres. “Second Extrait”, G. Darboux, Gauthiers-Villars, p. 325-328, 1880.↩︎

  3. 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.↩︎

  4. 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).↩︎

  5. 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.).↩︎

  6. Karmarkar, N. A new polynomial algorithm for linear programming. Combinatorica, v.4, p.373-395, 1984.↩︎

  7. Christos Papadimitriou & Kenneth Steiglitz. Combinatorial Optimization, 1982 (1998).↩︎