Skip to content

Commit

Permalink
Merge pull request #8 from ait-energy/dev
Browse files Browse the repository at this point in the history
Refactor dynamic loading of solvers (and IESoptLib) to using extensions (this currently "disables" precompile - since IESoptLib examples are not loaded anymore).
  • Loading branch information
sstroemer authored Jun 9, 2024
2 parents a3eec3d + 45cdf43 commit 0dea0be
Show file tree
Hide file tree
Showing 17 changed files with 160 additions and 46 deletions.
14 changes: 13 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,19 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.0.0] - 2023-06-01
## [1.0.1] - 2024-06-09

Added extensions to properly handle loading `IESoptLib` and various solvers.

### Changed

- `IESoptLib` and `HiGHS` are no longer required dependencies.

### Fixed

- Dynamic loading of weakdeps now works properly.

## [1.0.0] - 2024-06-01

### Added

Expand Down
20 changes: 11 additions & 9 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
name = "IESopt"
uuid = "ed3f0a38-8ad9-4cf8-877e-929e8d190fe9"
version = "1.0.0"
version = "1.0.1"

[deps]
ArgCheck = "dce04be8-c92d-5529-be00-80e4d2c0e197"
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
HiGHS = "87dc4568-4c63-4d18-b0c0-bb2238e4078b"
IESoptLib = "b98f706d-40ec-4ce6-a66c-1c6e71d3cef6"
JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819"
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
Expand All @@ -33,16 +31,20 @@ CPLEX = "a076750e-1247-5638-91d2-ce28b192dca0"
Cbc = "9961bab8-2fa3-5c5a-9d89-47fab24efd76"
GLPK = "60bf3e95-4087-53dc-ae20-288a0d20c6a6"
Gurobi = "2e9cd046-0924-5485-92f1-d5272153d98b"
HiGHS = "87dc4568-4c63-4d18-b0c0-bb2238e4078b"
IESoptLib = "b98f706d-40ec-4ce6-a66c-1c6e71d3cef6"
Ipopt = "b6b21f68-93f8-5de0-b562-5493be1d77c9"
SCIP = "82193955-e24f-5292-bf16-6f2c5261a85f"

[extensions]
CPLEX = "CPLEX"
Cbc = "Cbc"
GLPK = "GLPK"
Gurobi = "Gurobi"
Ipopt = "Ipopt"
SCIP = "SCIP"
LoadIESoptLib = "IESoptLib"
OptExtCbc = "Cbc"
OptExtCPLEX = "CPLEX"
OptExtGLPK = "GLPK"
OptExtGurobi = "Gurobi"
OptExtHiGHS = "HiGHS"
OptExtIpopt = "Ipopt"
OptExtSCIP = "SCIP"

[compat]
ArgCheck = "2.3.0"
Expand Down
9 changes: 9 additions & 0 deletions ext/LoadIESoptLib/LoadIESoptLib.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module LoadIESoptLib

import IESopt, IESoptLib

function IESopt._load_IESoptLib(::Bool)
return IESoptLib
end

end
11 changes: 11 additions & 0 deletions ext/OptExtCPLEX/OptExtCPLEX.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module OptExtCPLEX

import IESopt, CPLEX

struct OptType end

function IESopt._get_solver_module(::OptType)
return CPLEX
end

end
11 changes: 11 additions & 0 deletions ext/OptExtCbc/OptExtCbc.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module OptExtCbc

import IESopt, Cbc

struct OptType end

function IESopt._get_solver_module(::OptType)
return Cbc
end

end
11 changes: 11 additions & 0 deletions ext/OptExtGLPK/OptExtGLPK.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module OptExtGLPK

import IESopt, GLPK

struct OptType end

function IESopt._get_solver_module(::OptType)
return GLPK
end

end
11 changes: 11 additions & 0 deletions ext/OptExtGurobi/OptExtGurobi.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module OptExtGurobi

import IESopt, Gurobi

struct OptType end

function IESopt._get_solver_module(::OptType)
return Gurobi
end

end
11 changes: 11 additions & 0 deletions ext/OptExtHiGHS/OptExtHiGHS.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module OptExtHiGHS

import IESopt, HiGHS

struct OptType end

function IESopt._get_solver_module(::OptType)
return HiGHS
end

end
11 changes: 11 additions & 0 deletions ext/OptExtIpopt/OptExtIpopt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module OptExtIpopt

import IESopt, Ipopt

struct OptType end

function IESopt._get_solver_module(::OptType)
return Ipopt
end

end
11 changes: 11 additions & 0 deletions ext/OptExtSCIP/OptExtSCIP.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module OptExtSCIP

import IESopt, SCIP

struct OptType end

function IESopt._get_solver_module(::OptType)
return SCIP
end

end
35 changes: 20 additions & 15 deletions src/IESopt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ using PrecompileTools: @setup_workload, @compile_workload
_is_precompiling() = ccall(:jl_generating_output, Cint, ()) == 1

# Setup `IESoptLib.jl`, if available.
import IESoptLib
const Library = IESoptLib
_load_IESoptLib(::Any) = nothing
const Library = _load_IESoptLib(true)

# Constant paths that might be used somewhere.
const _dummy_path = normpath(@__DIR__, "utils", "dummy")
Expand Down Expand Up @@ -386,23 +386,28 @@ function _attach_optimizer(model::JuMP.Model)
@critical "Can't determine proper solver" solver
end

try
Base.require(IESopt, Symbol(solver))
catch
@error "It seems the requested solver is not installed; trying to install and precompile it" solver
solver_module = (
try
Pkg.add(solver)
Base.require(IESopt, Symbol(solver))
@info "Trying to activate solver extension" solver
Base.retry_load_extensions()
opt_ext = Base.get_extension(@__MODULE__, Symbol("OptExt$(solver)"))
_get_solver_module(opt_ext.OptType())
catch
@critical "Could not install the requested solver" solver
@error "It seems the requested solver is not installed; trying to install and precompile it" solver
try
Pkg.add(solver)
@info "Trying again to activate solver extension" solver
Base.retry_load_extensions()
opt_ext = Base.get_extension(@__MODULE__, Symbol("OptExt$(solver)"))
_get_solver_module(opt_ext.OptType())
catch
@critical "Could not install the requested solver" solver
end
@critical "Solver installed, but can not proceed from here; please execute your code again"
end
@critical "Solver installed, but can not proceed from here; please execute your code again"
end

# withpkg(f, pkgid::Base.PkgId) = Base.invokelatest(f, IESopt.require(pkgid))
)

# withpkg(Base.PkgId(Pkg.Types.Context().env.project.deps[solver], solver)) do s
let s = getfield(IESopt, Symbol(solver))
let s = solver_module
if !_is_multiobjective(model)
if _iesopt_config(model).optimization.solver.mode == "direct"
@critical "Automatic direct mode is currently not supported"
Expand Down
12 changes: 7 additions & 5 deletions src/precompile/precompile_tools.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
const dir = _PATHS[:examples]

@compile_workload begin
model = IESopt.generate!(normpath(dir, "01_basic_single_node.iesopt.yaml"); verbosity=false)
IESopt.optimize!(model)
if !isnothing(Library)
model = IESopt.generate!(normpath(dir, "01_basic_single_node.iesopt.yaml"); verbosity=false)
IESopt.optimize!(model)

IESopt.generate!(normpath(dir, "08_basic_investment.iesopt.yaml"); verbosity=false)
IESopt.generate!(normpath(dir, "09_csv_only.iesopt.yaml"); verbosity=false)
IESopt.generate!(normpath(dir, "46_constants_in_objective.iesopt.yaml"); verbosity=false)
IESopt.generate!(normpath(dir, "08_basic_investment.iesopt.yaml"); verbosity=false)
IESopt.generate!(normpath(dir, "09_csv_only.iesopt.yaml"); verbosity=false)
IESopt.generate!(normpath(dir, "46_constants_in_objective.iesopt.yaml"); verbosity=false)
end
end
end
15 changes: 2 additions & 13 deletions src/utils/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,10 @@ macro critical(msg, args...)
end)
end

function _try_loading_solver()
_try_import(solver::String) = IESopt.eval(Meta.parse("""try; import $(solver); true; catch; false; end;"""))
active = join([s for s in _ALL_SOLVER_INTERFACES if _try_import(s)], ", ")

if _is_precompiling()
else
@info "Activating solver interfaces" active
end

return active
function _get_solver_module(solver::Any)
@critical "No solver extension prepared" solver
end

# Immediately try to load solver interfaces.
const ACTIVE_SOLVER_INTERFACES = _try_loading_solver()

include("general.jl")
include("logging.jl")
include("packing.jl")
Expand Down
19 changes: 18 additions & 1 deletion test/Manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

julia_version = "1.10.3"
manifest_format = "2.0"
project_hash = "0f16b3954517e2989a6dcca15fd8260750ad1699"
project_hash = "9607dd83595c424ac800baa2c8a1382aa8a1b1e7"

[[deps.Aqua]]
deps = ["Compat", "Pkg", "Test"]
Expand Down Expand Up @@ -119,6 +119,23 @@ version = "0.10.36"
[deps.ForwardDiff.weakdeps]
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"

[[deps.HiGHS]]
deps = ["HiGHS_jll", "MathOptInterface", "PrecompileTools", "SparseArrays"]
git-tree-sha1 = "a216e32299172b83abfe699604584f413ffbb045"
uuid = "87dc4568-4c63-4d18-b0c0-bb2238e4078b"
version = "1.9.0"

[[deps.HiGHS_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Zlib_jll"]
git-tree-sha1 = "9a550d55c49334beb538c5ad9504f07fc29a13dc"
uuid = "8fd58aa0-07eb-5a78-9b36-339c94fd15ea"
version = "1.7.0+0"

[[deps.IESoptLib]]
git-tree-sha1 = "495ca907bf5587464b386b573828db8d5d3aa885"
uuid = "b98f706d-40ec-4ce6-a66c-1c6e71d3cef6"
version = "0.1.0"

[[deps.InteractiveUtils]]
deps = ["Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
Expand Down
2 changes: 2 additions & 0 deletions test/Project.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
[deps]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
HiGHS = "87dc4568-4c63-4d18-b0c0-bb2238e4078b"
IESoptLib = "b98f706d-40ec-4ce6-a66c-1c6e71d3cef6"
JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b"
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
Suppressor = "fd094767-a336-5f1f-9728-57cf17d0bbfb"
Expand Down
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import HiGHS
using IESopt, Suppressor
using Test, Aqua, JET
import JuMP
Expand Down
2 changes: 0 additions & 2 deletions test/src/examples.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
const HiGHS = IESopt.HiGHS

function _test_example_default_solver(filename::String; obj::Float64, verbosity::Union{Bool, String}=false, kwargs...)
@testset "$(split(filename, ".")[1])" begin
model = @suppress generate!(joinpath(PATH_EXAMPLES, filename); verbosity=verbosity, kwargs...)
Expand Down

2 comments on commit 0dea0be

@sstroemer
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/108581

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v1.0.1 -m "<description of version>" 0dea0be8b7ace3ca3532c04dc0233c2bbb2691fc
git push origin v1.0.1

Please sign in to comment.