From 076a1547745b96bead4292c69d5a8c6de0bd308e Mon Sep 17 00:00:00 2001 From: sstroemer Date: Wed, 8 Jan 2025 23:52:53 +0100 Subject: [PATCH 1/7] chore: ignore `.vscode` --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index f6b3687b..9736158e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.vscode/ + *.jl.*.cov *.jl.cov *.jl.mem From 8b501fd99c8c8a61c6f75ac34a0b1ab71c646a23 Mon Sep 17 00:00:00 2001 From: sstroemer Date: Wed, 8 Jan 2025 23:53:47 +0100 Subject: [PATCH 2/7] chore: add SHA dependency Was in use previously anyways (currently commented out) to hash input files. Now "only" used in tests (could be added there), but expected to be a dependency anyways. --- Project.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Project.toml b/Project.toml index 499dc651..ae65ad6e 100644 --- a/Project.toml +++ b/Project.toml @@ -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" @@ -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" From 16e32f4f3fdbfe54903ae92e37047f3e750e09ee Mon Sep 17 00:00:00 2001 From: sstroemer Date: Wed, 8 Jan 2025 23:54:28 +0100 Subject: [PATCH 3/7] test: move file cleanup from examples to end of runtests to better align with other test sets that might construct model files --- test/runtests.jl | 6 ++++++ test/src/examples.jl | 6 ------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index da5a16c5..830219ce 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -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 diff --git a/test/src/examples.jl b/test/src/examples.jl index 1e2ace11..e35f9d9b 100644 --- a/test/src/examples.jl +++ b/test/src/examples.jl @@ -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 From 89728ebbfe5c6d898d779e6f386e24576b275907 Mon Sep 17 00:00:00 2001 From: sstroemer Date: Wed, 8 Jan 2025 23:55:25 +0100 Subject: [PATCH 4/7] feat: implement `write_to_file` that allows sharing / solving models after writing them to common problem files --- src/IESopt.jl | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/src/IESopt.jl b/src/IESopt.jl index ad638248..78e540ad 100644 --- a/src/IESopt.jl +++ b/src/IESopt.jl @@ -529,6 +529,122 @@ 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 + using SHA: sha1 + + check_hash(f, h) = + open(f, "r") do io + return bytes2hex(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...) From 42f7a204871f422c6d15b0021f00675108dcc502 Mon Sep 17 00:00:00 2001 From: sstroemer Date: Thu, 9 Jan 2025 00:14:06 +0100 Subject: [PATCH 5/7] test: update manifest --- test/Manifest.toml | 47 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/test/Manifest.toml b/test/Manifest.toml index dab3406b..9600622a 100644 --- a/test/Manifest.toml +++ b/test/Manifest.toml @@ -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"] @@ -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"] @@ -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"] @@ -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"] @@ -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" @@ -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" @@ -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"] @@ -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" @@ -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" From 2fa8ab5d8ca9b85d0161f33ee514901355cfd968 Mon Sep 17 00:00:00 2001 From: sstroemer Date: Thu, 9 Jan 2025 00:14:44 +0100 Subject: [PATCH 6/7] fix: imports in testitem and (temporarily) disable hash based file checks --- src/IESopt.jl | 7 +++++-- src/imports.jl | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/IESopt.jl b/src/IESopt.jl index 78e540ad..7f85c272 100644 --- a/src/IESopt.jl +++ b/src/IESopt.jl @@ -605,11 +605,14 @@ function write_to_file(model::JuMP.Model) end @testitem "write_to_file" tags = [:unittest] begin - using SHA: sha1 + import IESopt.JuMP + import IESopt.SHA check_hash(f, h) = open(f, "r") do io - return bytes2hex(sha1(read(io, String))) == h + 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"))) diff --git a/src/imports.jl b/src/imports.jl index 46fd5de7..e090cdfc 100644 --- a/src/imports.jl +++ b/src/imports.jl @@ -53,6 +53,7 @@ import JSON import CSV import DataFrames import ZipFile +import SHA # Used in Benders/Stochastic. import Printf From 5906e8cb30403d3c7318a9e57dbfbfe976febc4e Mon Sep 17 00:00:00 2001 From: sstroemer Date: Thu, 9 Jan 2025 01:39:59 +0100 Subject: [PATCH 7/7] chore: prep for v2.3.0 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index ae65ad6e..3f272636 100644 --- a/Project.toml +++ b/Project.toml @@ -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"