library(ROI.plugin.highs)
library(ompr.roi)
library(ompr)
1 Giapetto Example
1.1 Problem
This example is taken from Winston’s Operations Research (4th Edition) Book
“Giapetto’s Woodcarving, Inc., manufactures two types of wooden toys: soldiers and trains.
A soldier sells for $27 and uses $10 worth of raw materials. Each soldier that is manufactured increases Giapetto’s variable labor and overhead costs by $14. A train sells for $21 and uses $9 worth of raw materials. Each train built increases Giapetto’s variable labor and overhead costs by $10.
The manufacture of wooden soldiers and trains requires two types of skilled labor: carpentry and finishing. A soldier requires 2 hours of finishing labor and 1 hour of carpentry labor. A train requires 1 hour of finishing labor and 1 hour of carpentry labor.
Each week, Giapetto can acquire all of the needed raw material, but he is only allotted 100 finishing hours and 80 carpentry hours. There is an unlimited demand for trains. However, at most, 40 soldiers are sold each week.
Giapetto wants to maximize his weekly profit (Revenues - Costs). Formulate a mathematical model for Giapetto’s situation that can be used to maximize Giapetto’s weekly profit.”
1.2 Mathematical Model
This problem’s mathematical model is deeply examined in the OR Primer main document. So we will only copy the model.
\[\begin{gather} \max z = 3x_{1} + 2x_{2} \label{eq:obj.fun} \\ s.t. \nonumber \\ 2x_{1} + x_{2} \le 100 \label{eq:finishing.constraint} \\ x_{1} + x_{2} \le 80 \label{eq:carpentry.constraint}\\ x_{1} \le 40 \label{eq:demand.constraint}\\ x_{1},x_{2} \ge 0 \\ \end{gather}\]
1.3 Code
<-
model_obj MIPModel() |>
add_variable(x1, type = "continuous",lb=0) |>
add_variable(x2, type = "continuous",lb=0) |>
add_constraint(2*x1 + x2 <= 100) |>
add_constraint(x1 + x2 <= 80) |>
add_constraint(x1 <= 40) |>
set_objective(3*x1 + 2*x2, "max") |>
solve_model(with_ROI(solver = "highs",verbose=TRUE))
<SOLVER MSG> ----
WARNING: No semi-integer/integer variables in model with non-empty integrality
Presolving model
2 rows, 2 cols, 4 nonzeros
2 rows, 2 cols, 4 nonzeros
Presolve : Reductions: rows 2(-1); columns 2(-0); elements 4(-1)
Solving the presolved LP
Using EKK dual simplex solver - serial
Iteration Objective Infeasibilities num(sum)
0 -1.9999937513e+00 Ph1: 2(2); Du: 1(1.99999) 0s
2 -1.8000000000e+02 Pr: 0(0) 0s
Solving the original LP from the solution after postsolve
Model status : Optimal
Simplex iterations: 2
Objective value : 1.8000000000e+02
HiGHS run time : 0.00
<!SOLVER MSG> ----
1.4 Results
First let’s check the status of the model.
|> solver_status() model_obj
[1] "success"
Then let’s get the number of soldiers (x1) and trains (x2) to be produced to get the optimal value.
|> get_solution(x1) model_obj
x1
20
|> get_solution(x2) model_obj
x2
60
Finally let’s check the objective function value of the solution.
|> objective_value() model_obj
[1] 180
The optimal solution is to manufacture 20 soldiers and 60 trains to get $180 net profit. In the following examples, we are going to solve problems with more variables and constraints.
1.5 More Detail
There are also some solver specific outputs as well as model details.
|> additional_solver_output() model_obj
$ROI
$ROI$status
$ROI$status$code
[1] 0
$ROI$status$msg
solver highs
code 7
symbol OPTIMAL
message Optimal
roi_code 0
$ROI$message
$ROI$message$primal_solution
[1] 20 60
$ROI$message$objective_value
[1] 180
$ROI$message$status
[1] 7
$ROI$message$status_message
[1] "Optimal"
$ROI$message$solver_msg
$ROI$message$solver_msg$value_valid
[1] TRUE
$ROI$message$solver_msg$dual_valid
[1] TRUE
$ROI$message$solver_msg$col_value
[1] 20 60
$ROI$message$solver_msg$col_dual
[1] 0 0
$ROI$message$solver_msg$row_value
[1] 100 80 20
$ROI$message$solver_msg$row_dual
[1] 1 1 0
$ROI$message$info
$ROI$message$info$valid
[1] TRUE
$ROI$message$info$mip_node_count
[1] -1
$ROI$message$info$simplex_iteration_count
[1] 2
$ROI$message$info$ipm_iteration_count
[1] 0
$ROI$message$info$qp_iteration_count
[1] 0
$ROI$message$info$crossover_iteration_count
[1] 0
$ROI$message$info$primal_solution_status
[1] "Feasible"
$ROI$message$info$dual_solution_status
[1] "Feasible"
$ROI$message$info$basis_validity
[1] 1
$ROI$message$info$objective_function_value
[1] 180
$ROI$message$info$mip_dual_bound
[1] 0
$ROI$message$info$mip_gap
[1] Inf
$ROI$message$info$num_primal_infeasibilities
[1] 0
$ROI$message$info$max_primal_infeasibility
[1] 0
$ROI$message$info$sum_primal_infeasibilities
[1] 0
$ROI$message$info$num_dual_infeasibilities
[1] 0
$ROI$message$info$max_dual_infeasibility
[1] 0
$ROI$message$info$sum_dual_infeasibilities
[1] 0
$ROI$message$objval
[1] 180