From 76fa7e11fdd3ba0c47d3816d0070c778665165c6 Mon Sep 17 00:00:00 2001 From: odow Date: Wed, 15 Dec 2021 16:31:56 +1300 Subject: [PATCH] [perf] add time-to-first-solve benchmark --- perf/time_to_first_solve/Project.toml | 4 ++ perf/time_to_first_solve/README.md | 13 +++++ perf/time_to_first_solve/script.jl | 82 +++++++++++++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 perf/time_to_first_solve/Project.toml create mode 100644 perf/time_to_first_solve/README.md create mode 100644 perf/time_to_first_solve/script.jl diff --git a/perf/time_to_first_solve/Project.toml b/perf/time_to_first_solve/Project.toml new file mode 100644 index 0000000000..1a5c781414 --- /dev/null +++ b/perf/time_to_first_solve/Project.toml @@ -0,0 +1,4 @@ +[deps] +Clp = "e2554f3b-3117-50c0-817c-e040a3ddf72d" +GLPK = "60bf3e95-4087-53dc-ae20-288a0d20c6a6" +MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee" diff --git a/perf/time_to_first_solve/README.md b/perf/time_to_first_solve/README.md new file mode 100644 index 0000000000..7783711c51 --- /dev/null +++ b/perf/time_to_first_solve/README.md @@ -0,0 +1,13 @@ +# Tracking the time-to-first-solve + +This script is used to benchmark the +[time-to-first-solve issue](https://github.com/jump-dev/MathOptInterface.jl/issues/1313). + +It can be run as follows: +``` +cd ~/.julia/dev/MathOptInterface/perf/time_to_first_solve +julia --project=. script.jl clp +julia --project=. script.jl clp --no-bridge +julia --project=. script.jl glpk +julia --project=. script.jl glpk --no-bridge +``` diff --git a/perf/time_to_first_solve/script.jl b/perf/time_to_first_solve/script.jl new file mode 100644 index 0000000000..ffea63701a --- /dev/null +++ b/perf/time_to_first_solve/script.jl @@ -0,0 +1,82 @@ +using MathOptInterface +import GLPK +import Clp +const MOI = MathOptInterface + +function example_diet(optimizer, bridge) + category_data = [ + 1800.0 2200.0 + 91.0 Inf + 0.0 65.0 + 0.0 1779.0 + ] + cost = [2.49, 2.89, 1.50, 1.89, 2.09, 1.99, 2.49, 0.89, 1.59] + food_data = [ + 410 24 26 730 + 420 32 10 1190 + 560 20 32 1800 + 380 4 19 270 + 320 12 10 930 + 320 15 12 820 + 320 31 12 1230 + 100 8 2.5 125 + 330 8 10 180 + ] + bridge_model = if bridge + MOI.instantiate(optimizer; with_bridge_type=Float64) + else + MOI.instantiate(optimizer) + end + model = MOI.Utilities.CachingOptimizer( + MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()), + MOI.Utilities.AUTOMATIC, + ) + MOI.Utilities.reset_optimizer(model, bridge_model) + MOI.set(model, MOI.Silent(), true) + nutrition = MOI.add_variables(model, size(category_data, 1)) + for (i, v) in enumerate(nutrition) + MOI.add_constraint(model, v, MOI.GreaterThan(category_data[i, 1])) + MOI.add_constraint(model, v, MOI.LessThan(category_data[i, 2])) + end + buy = MOI.add_variables(model, size(food_data, 1)) + MOI.add_constraint.(model, buy, MOI.GreaterThan(0.0)) + MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE) + f = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(cost, buy), 0.0) + MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f) + for (j, n) in enumerate(nutrition) + f = MOI.ScalarAffineFunction( + MOI.ScalarAffineTerm.(food_data[:, j], buy), + 0.0, + ) + push!(f.terms, MOI.ScalarAffineTerm(-1.0, n)) + MOI.add_constraint(model, f, MOI.EqualTo(0.0)) + end + MOI.optimize!(model) + term_status = MOI.get(model, MOI.TerminationStatus()) + @assert term_status == MOI.OPTIMAL + MOI.add_constraint( + model, + MOI.ScalarAffineFunction( + MOI.ScalarAffineTerm.(1.0, [buy[end-1], buy[end]]), + 0.0, + ), + MOI.LessThan(6.0), + ) + MOI.optimize!(model) + @assert MOI.get(model, MOI.TerminationStatus()) == MOI.INFEASIBLE + return +end + +if length(ARGS) > 0 + bridge = get(ARGS, 2, "") != "--no-bridge" + println("Running: $(ARGS[1]) $(get(ARGS, 2, ""))") + if ARGS[1] == "clp" + @time example_diet(Clp.Optimizer, bridge) + @time example_diet(Clp.Optimizer, bridge) + else + @assert ARGS[1] == "glpk" + @time example_diet(GLPK.Optimizer, bridge) + @time example_diet(GLPK.Optimizer, bridge) + end + exit(0) +end