///|
/// Runnable example: a two-product production plan.
///
/// max 5x + 4y
/// s.t. 6x + 4y <= 24 (machine hours available)
/// x + 2y <= 6 (labour hours available)
/// x, y >= 0
///
/// The optimum is 21 at (3, 1.5), which is not a vertex of the bounding box,
/// so it exercises a real two-row pivot rather than a trivial case.
///
/// Run with: `moon run examples/production_plan`
fn main {
let m = @model.Model::new(@model.Sense::Maximize)
let x = m.add_var("x")
let y = m.add_var("y")
m.set_objective([(x, 5.0), (y, 4.0)])
m.add_named_constraint(
[(x, 6.0), (y, 4.0)],
@model.Rel::LessEqual,
24.0,
"machine_hours",
)
m.add_named_constraint(
[(x, 1.0), (y, 2.0)],
@model.Rel::LessEqual,
6.0,
"labour_hours",
)
let sol = @moonopt.solve(m)
println("production plan: " + status_text(sol.status))
if sol.status == @moonopt.SolveStatus::Optimal {
println(" x = " + sol.values[0].to_string())
println(" y = " + sol.values[1].to_string())
println(" objective = " + sol.objective.to_string())
println(" iterations = " + sol.iterations.to_string())
} else {
println(" " + sol.message)
}
}
///|
/// Small local helper so the example stays readable.
fn status_text(status : @moonopt.SolveStatus) -> String {
match status {
@moonopt.SolveStatus::Optimal => "optimal"
@moonopt.SolveStatus::Infeasible => "infeasible"
@moonopt.SolveStatus::Unbounded => "unbounded"
@moonopt.SolveStatus::NodeLimit => "stopped at the node budget"
@moonopt.SolveStatus::NotSolved => "not solved"
}
}