I am playing around with JuMP to compare its performance to pyomo. This is the model I am using:
using JuMP
using GLPK
using LinearAlgebra
using BenchmarkTools
function run_market_opt(max_production::AbstractVector{T}, bids::AbstractVector{T}, demand::T) where T <: Real
n_plants = length(max_production)
model = Model(GLPK.Optimizer, add_bridges=false)
set_string_names_on_creation(model, false)
set_silent(model)
@variable(model, production[1:n_plants] >= zero(T))
@constraint(model, production .<= max_production)
@constraint(model, sum(production) == demand)
@objective(model, Min, dot(production, bids))
optimize!(model)
@assert is_solved_and_feasible(model)
return value.(production)
end
##
n_plants = 10000
max_production = 100 .* rand(Float64, n_plants)
bids = rand(Float64, n_plants)
demand = 30.0 * n_plants
@btime production_jump = run_market_opt(max_production, bids, demand);
with this I get:
1.018 s (350848 allocations: 25.42 MiB)
I was expecting JuMP to be faster than pyomo. This is the equivalent pyomo model:
import numpy as np
import pyomo.environ as pyo
from time import time
def run_market_opt(max_production, bids, demand):
n_plants = len(max_production)
model = pyo.ConcreteModel()
model.I = pyo.RangeSet(0, n_plants - 1)
model.production = pyo.Var(model.I, domain=pyo.NonNegativeReals)
def max_prod_rule(model, i):
return model.production[i] <= max_production[i]
model.max_production_constraint = pyo.Constraint(model.I, rule=max_prod_rule)
def demand_rule(model):
return sum(model.production[i] for i in model.I) == demand
model.demand_constraint = pyo.Constraint(rule=demand_rule)
def obj_rule(model):
return sum(model.production[i] * bids[i] for i in model.I)
model.objective = pyo.Objective(rule=obj_rule, sense=pyo.minimize)
solver = pyo.SolverFactory("glpk")
results = solver.solve(model, tee=False)
if (results.solver.status == pyo.SolverStatus.ok) and (
results.solver.termination_condition == pyo.TerminationCondition.optimal
):
return np.array([pyo.value(model.production[i]) for i in model.I])
else:
raise RuntimeError("Optimization failed to find a solution")
# %%
n_plants = 10000
max_production = 100 * np.random.rand(n_plants)
bids = np.random.rand(n_plants)
demand = 30 * n_plants
# %%
t1 = time()
production_pyomo = run_market_opt(max_production, bids, demand)
t2 = time()
print(f"Pyomo took {t2 - t1} seconds")
which gives
Pyomo took 0.874971866607666 seconds
Is there something I can do to speed-up the JuMP version? Could I do something to help reduce the number of allocations?
Thanks!