Skip to content

Commit

Permalink
Merge pull request #51 from sstroemer/feature-write-to-file
Browse files Browse the repository at this point in the history
feat: expose writing problem files to file
  • Loading branch information
sstroemer authored Jan 10, 2025
2 parents 91d38b2 + 5906e8c commit 90235d4
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 31 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.vscode/

*.jl.*.cov
*.jl.cov
*.jl.mem
Expand Down
4 changes: 3 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "IESopt"
uuid = "ed3f0a38-8ad9-4cf8-877e-929e8d190fe9"
version = "2.2.2"
version = "2.3.0"

[deps]
ArgCheck = "dce04be8-c92d-5529-be00-80e4d2c0e197"
Expand All @@ -27,6 +27,7 @@ Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
ProgressMeter = "92933f4c-e287-5a05-a399-4b506db050ca"
RelocatableFolders = "05181044-ff0b-4ac5-8273-598c1e38db00"
RuntimeGeneratedFunctions = "7e49a35a-f44a-4d26-94aa-eba1b4ca6b47"
SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce"
Suppressor = "fd094767-a336-5f1f-9728-57cf17d0bbfb"
TestItems = "1c621080-faea-4a02-84b6-bbd5e436b8fe"
YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6"
Expand Down Expand Up @@ -79,6 +80,7 @@ ProgressMeter = "1.10"
RelocatableFolders = "1.0.1"
RuntimeGeneratedFunctions = "0.5.13"
SCIP = "0.11.14, 0.12"
SHA = "0.7.0"
Suppressor = "0.2"
TestItems = "1.0.0"
YAML = "0.4"
Expand Down
119 changes: 119 additions & 0 deletions src/IESopt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,125 @@ function build!(model::JuMP.Model)
return nothing
end

"""
write_to_file(model::JuMP.Model, filename::String; format::JuMP.MOI.FileFormats.FileFormat = JuMP.MOI.FileFormats.FORMAT_AUTOMATIC, kwargs...)
Write the given IESopt model to a file with the specified filename and format.
Be aware, that this function will overwrite any existing file with the same name!
# Arguments
- `model::JuMP.Model`: The IESopt model to be written to a file.
- `filename::String`: The name of the file to which the model should be written. Note that if the format is set to
`FORMAT_AUTOMATIC`, the the file extension will be forced to lower case to allow detection.
- `format::JuMP.MOI.FileFormats.FileFormat` (optional): The format in which the model should be written. The default is
`JuMP.MOI.FileFormats.FORMAT_AUTOMATIC`; if left as that, it will try to automatically determine the format based on
the file extension.
All additional keyword arguments are passed to the `JuMP.write_to_file` function.
# Returns
- `String`: The absolute path to the file to which the model was written.
# Example
```julia
import IESopt
model = IESopt.generate!("config.iesopt.yaml")
IESopt.write_to_file(model, "model.lp")
```
"""
function write_to_file(
model::JuMP.Model,
filename::String;
format::JuMP.MOI.FileFormats.FileFormat=JuMP.MOI.FileFormats.FORMAT_AUTOMATIC,
kwargs...,
)
if format == JuMP.MOI.FileFormats.FORMAT_AUTOMATIC
fn, ext = splitext(filename)
filename = "$(fn)$(lowercase(ext))"
end

JuMP.write_to_file(model, filename; format, kwargs...)

@debug "[write_to_file] Model written to file" filename
return abspath(filename)
end

"""
write_to_file(model::JuMP.Model)
Write the given IESopt model to a file for later use. The filename and location is based on the model's scenario name,
and will be written to the general "results" path that is configured.
# Arguments
- `model::JuMP.Model`: The IESopt model to be written to a file.
# Returns
- `String`: The absolute path to the file to which the model was written.
# Example
```julia
import IESopt
model = IESopt.generate!("config.iesopt.yaml")
IESopt.write_to_file(model)
```
"""
function write_to_file(model::JuMP.Model)
folder = @config(model, paths.results)
scenario = @config(model, general.name.scenario)

filename = normpath(folder, "$(scenario).iesopt.mps")
mkpath(dirname(filename))

return write_to_file(model, filename)
end

@testitem "write_to_file" tags = [:unittest] begin
import IESopt.JuMP
import IESopt.SHA

check_hash(f, h) =
open(f, "r") do io
return true
# TODO: Files are (YAML?) not deterministic => hashes may change
# return bytes2hex(SHA.sha1(read(io, String))) == h
end

model = generate!(String(Assets.get_path("examples", "01_basic_single_node.iesopt.yaml")))

comparisons = [
(fn="test_write_to_file.iesopt.lp", hash="15f3782fa4f38d814d0b247853d4a166c1d7e486"),
(fn="test_write_to_file.iesopt.LP", hash="15f3782fa4f38d814d0b247853d4a166c1d7e486"),
(fn="test_write_to_file.lp", hash="15f3782fa4f38d814d0b247853d4a166c1d7e486"),
(fn="test_write_to_file.iesopt.MPS", hash="2214cbf5df222484d0842043b89f4e5581882f7d"),
]

# Test various file names.
for c in comparisons
target = normpath(tempdir(), c.fn)
file = write_to_file(model, target)
@test isfile(file)
@test check_hash(file, c.hash)
rm(file)
end

# Test writing to custom file format (including keeping case).
file =
write_to_file(model, normpath(tempdir(), "test_write_to_file.IESOPT"); format=JuMP.MOI.FileFormats.FORMAT_MOF)
@test isfile(file)
@test endswith(file, ".IESOPT")
@test check_hash(file, "789a1df6f7a2fc587f80e590dff4e3a88a4e0e8f")
rm(file)

# Test automatically determining the filename.
file = write_to_file(model)
@test isfile(file)
@test check_hash(file, "2214cbf5df222484d0842043b89f4e5581882f7d")
rm(file)
end

"""
optimize!(model::JuMP.Model; kwargs...)
Expand Down
1 change: 1 addition & 0 deletions src/imports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import JSON
import CSV
import DataFrames
import ZipFile
import SHA

# Used in Benders/Stochastic.
import Printf
Expand Down
47 changes: 23 additions & 24 deletions test/Manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@ uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
version = "1.11.0"

[[deps.BenchmarkTools]]
deps = ["JSON", "Logging", "Printf", "Profile", "Statistics", "UUIDs"]
git-tree-sha1 = "f1dff6729bc61f4d49e140da1af55dcd1ac97b2f"
deps = ["Compat", "JSON", "Logging", "Printf", "Profile", "Statistics", "UUIDs"]
git-tree-sha1 = "e38fbc49a620f5d0b660d7f543db1009fe0f8336"
uuid = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
version = "1.5.0"
version = "1.6.0"

[[deps.Bzip2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "8873e196c2eb87962a2048b3b8e08946535864a1"
uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0"
version = "1.0.8+2"
version = "1.0.8+4"

[[deps.CodeTracking]]
deps = ["InteractiveUtils", "UUIDs"]
Expand All @@ -42,9 +42,9 @@ version = "1.3.6"

[[deps.CodecBzip2]]
deps = ["Bzip2_jll", "TranscodingStreams"]
git-tree-sha1 = "e7c529cc31bb85b97631b922fa2e6baf246f5905"
git-tree-sha1 = "84990fa864b7f2b4901901ca12736e45ee79068c"
uuid = "523fee87-0ab8-5b00-afb7-3ecf72e48cfd"
version = "0.8.4"
version = "0.8.5"

[[deps.CodecZlib]]
deps = ["TranscodingStreams", "Zlib_jll"]
Expand Down Expand Up @@ -125,15 +125,15 @@ version = "0.10.38"

[[deps.HiGHS]]
deps = ["HiGHS_jll", "MathOptInterface", "PrecompileTools", "SparseArrays"]
git-tree-sha1 = "5360ef81c3952f29624ec75ad0045d079c6379f3"
git-tree-sha1 = "b07cf87cb3bcbd65d1d3fcf4143d4a44abe33d20"
uuid = "87dc4568-4c63-4d18-b0c0-bb2238e4078b"
version = "1.12.2"
version = "1.13.0"

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

[[deps.InteractiveUtils]]
deps = ["Markdown"]
Expand Down Expand Up @@ -161,9 +161,9 @@ version = "0.9.12"

[[deps.JLLWrappers]]
deps = ["Artifacts", "Preferences"]
git-tree-sha1 = "be3dc50a92e5a386872a493a10050136d4703f9b"
git-tree-sha1 = "a007feb38b422fbdab534406aeca1b86823cb4d6"
uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210"
version = "1.6.1"
version = "1.7.0"

[[deps.JSON]]
deps = ["Dates", "Mmap", "Parsers", "Unicode"]
Expand All @@ -173,9 +173,9 @@ version = "0.21.4"

[[deps.JuMP]]
deps = ["LinearAlgebra", "MacroTools", "MathOptInterface", "MutableArithmetics", "OrderedCollections", "PrecompileTools", "Printf", "SparseArrays"]
git-tree-sha1 = "866dd0bf0474f0d5527c2765c71889762ba90a27"
git-tree-sha1 = "02b6e65736debc1f47b40b0f7d5dfa0217ee1f09"
uuid = "4076af6c-e467-56ae-b986-b466b2749572"
version = "1.23.5"
version = "1.23.6"

[deps.JuMP.extensions]
JuMPDimensionalDataExt = "DimensionalData"
Expand Down Expand Up @@ -225,9 +225,9 @@ version = "1.11.0"

[[deps.LogExpFunctions]]
deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"]
git-tree-sha1 = "a2d09619db4e765091ee5c6ffe8872849de0feea"
git-tree-sha1 = "13ca9e2586b89836fd20cccf56e57e2b9ae7f38f"
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
version = "0.3.28"
version = "0.3.29"

[deps.LogExpFunctions.extensions]
LogExpFunctionsChainRulesCoreExt = "ChainRulesCore"
Expand All @@ -250,10 +250,9 @@ uuid = "6f1432cf-f94c-5a45-995e-cdbf5db27b0b"
version = "3.1.0"

[[deps.MacroTools]]
deps = ["Markdown", "Random"]
git-tree-sha1 = "2fa9ee3e63fd3a4f7a9a4f4744a52f4856de82df"
git-tree-sha1 = "72aebe0b5051e5143a079a4685a46da330a40472"
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
version = "0.5.13"
version = "0.5.15"

[[deps.Markdown]]
deps = ["Base64"]
Expand Down Expand Up @@ -306,10 +305,10 @@ uuid = "05823500-19ac-5b8b-9628-191a04bc5112"
version = "0.8.1+2"

[[deps.OpenSpecFun_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1"
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl"]
git-tree-sha1 = "1346c9208249809840c91b26703912dff463d335"
uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e"
version = "0.5.5+0"
version = "0.5.6+0"

[[deps.OrderedCollections]]
git-tree-sha1 = "12f1439c4f986bb868acda6ea33ebc78e19b95ad"
Expand Down Expand Up @@ -374,9 +373,9 @@ version = "1.11.0"

[[deps.SpecialFunctions]]
deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"]
git-tree-sha1 = "2f5d4697f21388cbe1ff299430dd169ef97d7e14"
git-tree-sha1 = "64cca0c26b4f31ba18f13f6c12af7c85f478cfde"
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
version = "2.4.0"
version = "2.5.0"

[deps.SpecialFunctions.extensions]
SpecialFunctionsChainRulesCoreExt = "ChainRulesCore"
Expand Down
6 changes: 6 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,9 @@ include("src/examples.jl")

@run_package_tests verbose = true filter = ti -> (:examples in ti.tags)
end

try
# Clean up output files after testing is done.
rm(normpath(IESopt.Assets.get_path("examples"), "out"); force=true, recursive=true)
catch
end
6 changes: 0 additions & 6 deletions test/src/examples.jl
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,3 @@ end
@test minimum(setpoint) -4.65 atol = 0.01
@test maximum(setpoint) 3.58 atol = 0.01
end

try
# Clean up output files after testing is done.
rm(normpath(IESopt.Assets.get_path("examples"), "out"); force=true, recursive=true)
catch
end

0 comments on commit 90235d4

Please sign in to comment.