Skip to content

Commit 4f41650

Browse files
authored
Refactor status dicts into functions (#210)
1 parent 66abf3d commit 4f41650

File tree

1 file changed

+111
-88
lines changed

1 file changed

+111
-88
lines changed

src/MOI_wrapper/MOI_wrapper.jl

+111-88
Original file line numberDiff line numberDiff line change
@@ -1517,110 +1517,133 @@ function _raw_simplex_string(status::Int32)
15171517
MOI.INFEASIBLE,
15181518
"The LP problem instance has no primal feasible solution (only if the LP presolver is used).",
15191519
)
1520-
elseif status == GLP_ENODFS
1520+
else
1521+
@assert status == GLP_ENODFS
15211522
return (
15221523
MOI.DUAL_INFEASIBLE,
15231524
"The LP problem instance has no dual feasible solution (only if the LP presolver is used).",
15241525
)
1526+
end
1527+
end
1528+
1529+
function _raw_exact_string(status::Int32)
1530+
if status == GLP_EBADB
1531+
return (
1532+
MOI.INVALID_MODEL,
1533+
"Unable to start the search, because the initial basis specified in the problem object is invalid—the number of basic (auxiliary and structural) variables is not the same as the number of rows in the problem object.",
1534+
)
1535+
elseif status == GLP_ESING
1536+
return (
1537+
MOI.NUMERICAL_ERROR,
1538+
"Unable to start the search, because the basis matrix corresponding to the initial basis is exactly singular.",
1539+
)
1540+
elseif status == GLP_EBOUND
1541+
return (
1542+
MOI.INVALID_MODEL,
1543+
"Unable to start the search, because some double-bounded (auxiliary or structural) variables have incorrect bounds.",
1544+
)
1545+
elseif status == GLP_EFA
1546+
(MOI.INVALID_MODEL, "The problem instance has no rows/columns.")
1547+
elseif status == GLP_EITLIM
1548+
return (
1549+
MOI.ITERATION_LIMIT,
1550+
"The search was prematurely terminated, because the simplex iteration limit has been exceeded.",
1551+
)
15251552
else
1526-
error("unknown status")
1527-
end
1528-
end
1529-
1530-
const _RAW_EXACT_STRINGS = Dict{Int32,Tuple{MOI.TerminationStatusCode,String}}(
1531-
GLP_EBADB => (
1532-
MOI.INVALID_MODEL,
1533-
"Unable to start the search, because the initial basis specified in the problem object is invalid—the number of basic (auxiliary and structural) variables is not the same as the number of rows in the problem object.",
1534-
),
1535-
GLP_ESING => (
1536-
MOI.NUMERICAL_ERROR,
1537-
"Unable to start the search, because the basis matrix corresponding to the initial basis is exactly singular.",
1538-
),
1539-
GLP_EBOUND => (
1540-
MOI.INVALID_MODEL,
1541-
"Unable to start the search, because some double-bounded (auxiliary or structural) variables have incorrect bounds.",
1542-
),
1543-
GLP_EFAIL =>
1544-
(MOI.INVALID_MODEL, "The problem instance has no rows/columns."),
1545-
GLP_EITLIM => (
1546-
MOI.ITERATION_LIMIT,
1547-
"The search was prematurely terminated, because the simplex iteration limit has been exceeded.",
1548-
),
1549-
GLP_ETMLIM => (
1550-
MOI.TIME_LIMIT,
1551-
"The search was prematurely terminated, because the time limit has been exceeded.",
1552-
),
1553-
)
1553+
@assert status == GLP_ETMLIM
1554+
return (
1555+
MOI.TIME_LIMIT,
1556+
"The search was prematurely terminated, because the time limit has been exceeded.",
1557+
)
1558+
end
1559+
end
15541560

1555-
const _RAW_INTERIOR_STRINGS =
1556-
Dict{Int32,Tuple{MOI.TerminationStatusCode,String}}(
1557-
GLP_EFAIL =>
1558-
(MOI.INVALID_MODEL, "The problem instance has no rows/columns."),
1559-
GLP_ENOCVG =>
1560-
(MOI.SLOW_PROGRESS, "Very slow convergence or divergence."),
1561-
GLP_EITLIM => (MOI.ITERATION_LIMIT, "Iteration limit exceeded."),
1562-
GLP_EINSTAB => (
1561+
function _raw_interior_string(status::Int32)
1562+
if status == GLP_EFAIL
1563+
return (MOI.INVALID_MODEL, "The problem instance has no rows/columns.")
1564+
elseif status == GLP_ENOCVG
1565+
return (MOI.SLOW_PROGRESS, "Very slow convergence or divergence.")
1566+
elseif status == GLP_EITLIM
1567+
return (MOI.ITERATION_LIMIT, "Iteration limit exceeded.")
1568+
else
1569+
@assert status == GLP_EINSTAB
1570+
return (
15631571
MOI.NUMERICAL_ERROR,
15641572
"Numerical instability on solving Newtonian system.",
1565-
),
1566-
)
1573+
)
1574+
end
1575+
end
15671576

1568-
const _RAW_INTOPT_STRINGS = Dict{Int32,Tuple{MOI.TerminationStatusCode,String}}(
1569-
GLP_EBOUND => (
1570-
MOI.INVALID_MODEL,
1571-
"Unable to start the search, because some double-bounded (auxiliary or structural) variables have incorrect bounds.",
1572-
),
1573-
GLP_ENOPFS => (
1574-
MOI.INFEASIBLE,
1575-
"Unable to start the search, because LP relaxation of the MIP problem instance has no primal feasible solution. (This code may appear only if the presolver is enabled.)",
1576-
),
1577-
GLP_ENODFS => (
1578-
MOI.DUAL_INFEASIBLE,
1579-
"Unable to start the search, because LP relaxation of the MIP problem instance has no dual feasible solution. In other word, this code means that if the LP relaxation has at least one primal feasible solution, its optimal solution is unbounded, so if the MIP problem has at least one integer feasible solution, its (integer) optimal solution is also unbounded. (This code may appear only if the presolver is enabled.)",
1580-
),
1581-
GLP_EFAIL => (
1582-
MOI.INVALID_MODEL,
1583-
"The search was prematurely terminated due to the solver failure.",
1584-
),
1585-
GLP_EMIPGAP => (
1586-
MOI.OPTIMAL,
1587-
"The search was prematurely terminated, because the relative mip gap tolerance has been reached.",
1588-
),
1589-
GLP_ETMLIM => (
1590-
MOI.TIME_LIMIT,
1591-
"The search was prematurely terminated, because the time limit has been exceeded.",
1592-
),
1593-
GLP_ESTOP => (
1594-
MOI.INTERRUPTED,
1595-
"The search was prematurely terminated by application. (This code may appear only if the advanced solver interface is used.)",
1596-
),
1597-
)
1577+
function _raw_intopt_string(status::Int32)
1578+
if status == GLP_EBOUND
1579+
return (
1580+
MOI.INVALID_MODEL,
1581+
"Unable to start the search, because some double-bounded (auxiliary or structural) variables have incorrect bounds.",
1582+
)
1583+
elseif status == GLP_ENOPFS
1584+
return (
1585+
MOI.INFEASIBLE,
1586+
"Unable to start the search, because LP relaxation of the MIP problem instance has no primal feasible solution. (This code may appear only if the presolver is enabled.)",
1587+
)
1588+
elseif status == GLP_ENODFS
1589+
return (
1590+
MOI.DUAL_INFEASIBLE,
1591+
"Unable to start the search, because LP relaxation of the MIP problem instance has no dual feasible solution. In other word, this code means that if the LP relaxation has at least one primal feasible solution, its optimal solution is unbounded, so if the MIP problem has at least one integer feasible solution, its (integer) optimal solution is also unbounded. (This code may appear only if the presolver is enabled.)",
1592+
)
1593+
elseif status == GLP_EFAIL
1594+
return (
1595+
MOI.INVALID_MODEL,
1596+
"The search was prematurely terminated due to the solver failure.",
1597+
)
1598+
elseif status == GLP_EMIPGAP
1599+
return (
1600+
MOI.OPTIMAL,
1601+
"The search was prematurely terminated, because the relative mip gap tolerance has been reached.",
1602+
)
1603+
elseif status == GLP_ETMLIM
1604+
return (
1605+
MOI.TIME_LIMIT,
1606+
"The search was prematurely terminated, because the time limit has been exceeded.",
1607+
)
1608+
else
1609+
@assert status == GLP_ESTOP
1610+
return (
1611+
MOI.INTERRUPTED,
1612+
"The search was prematurely terminated by application. (This code may appear only if the advanced solver interface is used.)",
1613+
)
1614+
end
1615+
end
15981616

1599-
const _RAW_SOLUTION_STATUS =
1600-
Dict{Int32,Tuple{MOI.TerminationStatusCode,String}}(
1601-
GLP_OPT => (MOI.OPTIMAL, "Solution is optimal"),
1602-
GLP_FEAS => (MOI.LOCALLY_SOLVED, "Solution is feasible"),
1603-
GLP_INFEAS => (MOI.LOCALLY_INFEASIBLE, "Solution is infeasible"),
1604-
GLP_NOFEAS =>
1605-
(MOI.INFEASIBLE, "No feasible primal-dual solution exists."),
1606-
GLP_UNBND => (MOI.DUAL_INFEASIBLE, "Problem has unbounded solution"),
1607-
GLP_UNDEF => (MOI.OTHER_ERROR, "Solution is undefined"),
1608-
)
1617+
function _raw_solution_string(status::Int32)
1618+
if status == GLP_OPT
1619+
return (MOI.OPTIMAL, "Solution is optimal")
1620+
elseif status == GLP_FEAS
1621+
return (MOI.LOCALLY_SOLVED, "Solution is feasible")
1622+
elseif status == GLP_INFEAS
1623+
return (MOI.LOCALLY_INFEASIBLE, "Solution is infeasible")
1624+
elseif status == GLP_NOFEAS
1625+
return (MOI.INFEASIBLE, "No feasible primal-dual solution exists.")
1626+
elseif status == GLP_UNBND
1627+
return (MOI.DUAL_INFEASIBLE, "Problem has unbounded solution")
1628+
else
1629+
@assert status == GLP_UNDEF
1630+
return (MOI.OTHER_ERROR, "Solution is undefined")
1631+
end
1632+
end
16091633

16101634
function MOI.get(model::Optimizer, attr::MOI.RawStatusString)
16111635
_throw_if_optimize_in_progress(model, attr)
16121636
if model.solver_status == Int32(0)
1613-
(_, msg) = _get_status(model)
1614-
return msg
1637+
return _get_status(model)[2]
16151638
elseif model.last_solved_by_mip
1616-
return _RAW_INTOPT_STRINGS[model.solver_status][2]
1639+
return _raw_intopt_string(model.solver_status)[2]
16171640
elseif model.method == SIMPLEX
16181641
return _raw_simplex_string(model.solver_status)[2]
16191642
elseif model.method == EXACT
1620-
return _RAW_EXACT_STRINGS[model.solver_status][2]
1643+
return _raw_exact_string(model.solver_status)[2]
16211644
else
16221645
@assert model.method == INTERIOR
1623-
return _RAW_INTERIOR_STRINGS[model.solver_status][2]
1646+
return _raw_interior_string(model.solver_status)[2]
16241647
end
16251648
end
16261649

@@ -1633,7 +1656,7 @@ function _get_status(model::Optimizer)
16331656
@assert model.method == INTERIOR
16341657
glp_ipt_status(model)
16351658
end
1636-
return _RAW_SOLUTION_STATUS[status_code]
1659+
return _raw_solution_string(status_code)
16371660
end
16381661

16391662
"""
@@ -1660,14 +1683,14 @@ function MOI.get(model::Optimizer, attr::MOI.TerminationStatus)
16601683
elseif model.solver_status != Int32(0)
16611684
# The solver did not exit successfully for some reason.
16621685
if model.last_solved_by_mip
1663-
return _RAW_INTOPT_STRINGS[model.solver_status][1]
1686+
return _raw_intopt_string(model.solver_status)[1]
16641687
elseif model.method == SIMPLEX
16651688
return _raw_simplex_string(model.solver_status)[1]
16661689
elseif model.method == INTERIOR
1667-
return _RAW_INTERIOR_STRINGS[model.solver_status][1]
1690+
return _raw_interior_string(model.solver_status)[1]
16681691
else
16691692
@assert model.method == EXACT
1670-
return _RAW_EXACT_STRINGS[model.solver_status][1]
1693+
return _raw_exact_string(model.solver_status)[1]
16711694
end
16721695
else
16731696
(status, _) = _get_status(model)

0 commit comments

Comments
 (0)