# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# LCF586_R_ProgLinear_RefMinCusto.r
# ---------------------
# Projeto: Solução de problemas de programação linear usando o R
# Autor:   Luiz Carlos Estraviz Rodriguez
# Data:    20/Out/2020
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rm(list=ls(all=TRUE))                                   # Limpa memória
gc()

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# /* Problema 01 */
# /* Refeição de mínimo custo */
# 
# /* Função Objetivo */
# min: +0.10 ER +0.15 FE +0.13 QU +0.09 MI +0.10 TO +0.07 AR +0.50 FR +1.15 BI +1.90 PE +0.28 LA +0.42 MA +0.15 PU +0.15 GE;
# 
# /* Restrições */
# +ER +FE +QU +MI +TO +AR >= 1;
# +FR +BI +PE >= 1;
# +LA +MA +PU +GE >= 1;
# +10 ER +10 FE +10 QU +20 MI +40 TO +50 AR +20 FR +30 BI +30 PE +10 LA +10 MA +10 PU +10 GE >= 50;
# +30 ER +50 FE +50 QU +60 MI +20 TO +10 AR +10 FR +80 BI +60 PE +30 LA +20 MA >= 100;
# +10 ER +20 FE +10 QU +10 MI +10 TO +10 AR +30 FR +50 BI +60 PE +10 LA >= 100;
# +10 MI +10 TO +10 AR +10 FR +20 BI +10 PE +10 PU >= 20;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Definição dos coeficientes e parâmetros do problema
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Coeficientes das variáveis na função objetivo                    -> C
C <- c(0.10, 0.15, 0.13, 0.09, 0.10, 0.07, 0.50, 1.15, 1.90, 0.28, 0.42, 0.15, 0.15)
# Matrix de coeficientes técnicos das restrições                   -> A
A <- matrix(c(
   1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,
   0,  0,  0,  0,  0,  0,  1,  1,  1,  0,  0,  0,  0,
   0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,
  10, 10, 10, 20, 40, 50, 20, 30, 30, 10, 10, 10, 10,
  30, 50, 50, 60, 20, 10, 10, 80, 60, 30, 20,  0,  0,
  10, 20, 10, 10, 10, 10, 30, 50, 60, 10,  0,  0,  0,
   0,  0,  0, 10, 10, 10, 10, 20, 10,  0,  0, 10,  0), nrow=7, byrow=TRUE)
# Coeficientes do RHS (Right hand side) das restrições             -> B
B <- c(1, 1, 1, 50, 100, 100, 20)
# Direção das restrições
R  <- c(">=", ">=", ">=", ">=", ">=", ">=", ">=")
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Solução usando o pacote lpSolve
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Carrega o pacote lpSolve
if(!require(lpSolve)){
  install.packages('lpSolve')
  require(lpSolve)
}
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Definição dos argumentos da função lp() para busca da solução ótima
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
solotima <-  lp(direction="min",       # problema de minimização
                objective.in = C,      # coef da f objetivo
                const.mat = A,         # coef téc das restrições
                const.dir = R,         # direção das restrições
                const.rhs = B,         # valores do RHS
               all.int = FALSE)        # as var não são inteiras
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Mostra solução
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Chama status da solução: 0 = successo, 2 = inviável
print(solotima$status)
# Resgata solução, nomeia variáveis e exibe solução
melhor_sol <- solotima$solution
names(melhor_sol) <- c("ER", "FE", "QU", "MI", "TO", "AR", "FR", "BI", "PE", "LA", "MA", "PU", "GE") 
print(melhor_sol)
# Confere valor da função objetivo
print(paste("Custo total: ", solotima$objval, sep=""))

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Solução usando pacote lpSolveAPI
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Carrega o pacote lpSolveAPI
if(!require(lpSolveAPI)){
  install.packages('lpSolveAPI')
  require(lpSolveAPI)
}
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Definição dos coeficientes e parâmetros do problema de PL
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Nomeia o problema e define 4 restrições e 3 variáveis de decisão
lpprob <- make.lp(nrow = 7, ncol = 13)
# Define o tipo de problema
lp.control(lpprob, sense="min")
# Definição do tipo para cada variável de decisão
set.type(lpprob, 1:13, type=c("real"))
# Definição dos coeficientes da função objetivo
set.objfn(lpprob, C)
# Acréscimo das restrições
add.constraint(lpprob, A[1, ], ">=", B[1])
add.constraint(lpprob, A[2, ], ">=", B[2])
add.constraint(lpprob, A[3, ], ">=", B[3])
add.constraint(lpprob, A[4, ], ">=", B[4])
add.constraint(lpprob, A[5, ], ">=", B[5])
add.constraint(lpprob, A[6, ], ">=", B[6])
add.constraint(lpprob, A[7, ], ">=", B[7])
# Mostra a matrix de entrada de dados do lpSolve
lpprob
# Resolve o problema de PL
solve(lpprob)
# Mostra os valores das variáveis de decisão
get.variables(lpprob)
# Mostra o valor da função objetivo
get.objective(lpprob)
# Obs: limites default das variáveis de decisão são c(0, 0, 0 ...) e c(Inf, Inf, Inf ...)
get.bounds(lpprob)