diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a27bf5..97f3fff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,21 @@ # Changelog -## [Unreleased] +## [0.2.0] - [Unreleased] ### Added -- Implement sub-hourly unit commitment +- Sub-hourly unit commitment ### Changed - Renamed "Time (h)" parameter to "Time horizon (h)" +- `UnitCommitment.build_model` now returns a plain JuMP model. The + struct `UnitCommitmentModel` has been completely removed. Accessing model elements can now be accomplished as follows: + - `model.vars.x[idx]` becomes `model[:x][idx]` + - `model.eqs.y[idx]` becomes `model[:eq_y][idx]` + - `model.expr.z[idx]` becomes `model[:expr_z][idx]` + - `model.obj` becomes `model[:obj]` + - `model.isf` becomes `model[:isf]` + - `model.lodf` becomes `model[:lodf]` +- Function `UnitCommitment.get_solution` has been renamed to `UnitCommitment.solution` ## [0.1.1] - 2020-11-16 diff --git a/Manifest.toml b/Manifest.toml index 24f70e4..e6b20eb 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -1,25 +1,25 @@ # This file is machine-generated - editing it directly is not advised +[[ArgTools]] +uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" + [[Artifacts]] -deps = ["Pkg"] -git-tree-sha1 = "c30985d8821e0cd73870b17b0ed0ce6dc44cb744" uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" -version = "1.3.0" [[Base64]] uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" [[BenchmarkTools]] deps = ["JSON", "Logging", "Printf", "Statistics", "UUIDs"] -git-tree-sha1 = "9e62e66db34540a0c919d72172cc2f642ac71260" +git-tree-sha1 = "01ca3823217f474243cc2c8e6e1d1f45956fe872" uuid = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" -version = "0.5.0" +version = "1.0.0" [[Bzip2_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "c3598e525718abcc440f69cc6d5f60dda0a1b61e" +git-tree-sha1 = "19a35467a82e236ff51bc17a3a44b69ef35185a2" uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0" -version = "1.0.6+5" +version = "1.0.8+0" [[Calculus]] deps = ["LinearAlgebra"] @@ -29,9 +29,9 @@ version = "0.5.1" [[ChainRulesCore]] deps = ["Compat", "LinearAlgebra", "SparseArrays"] -git-tree-sha1 = "de4f08843c332d355852721adb1592bce7924da3" +git-tree-sha1 = "b391f22252b8754f4440de1f37ece49d8a7314bb" uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" -version = "0.9.29" +version = "0.9.44" [[CodecBzip2]] deps = ["Bzip2_jll", "Libdl", "TranscodingStreams"] @@ -53,15 +53,13 @@ version = "0.3.0" [[Compat]] deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"] -git-tree-sha1 = "919c7f3151e79ff196add81d7f4e45d91bbf420b" +git-tree-sha1 = "e4e2b39db08f967cc1360951f01e8a75ec441cab" uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" -version = "3.25.0" +version = "3.30.0" [[CompilerSupportLibraries_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "8e695f735fca77e9708e795eda62afdb869cbb70" +deps = ["Artifacts", "Libdl"] uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" -version = "0.3.4+0" [[DataStructures]] deps = ["Compat", "InteractiveUtils", "OrderedCollections"] @@ -93,11 +91,21 @@ version = "1.0.2" deps = ["Random", "Serialization", "Sockets"] uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" +[[DocStringExtensions]] +deps = ["LibGit2", "Markdown", "Pkg", "Test"] +git-tree-sha1 = "9d4f64f79012636741cf01133158a54b24924c32" +uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" +version = "0.8.4" + +[[Downloads]] +deps = ["ArgTools", "LibCURL", "NetworkOptions"] +uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" + [[ForwardDiff]] -deps = ["CommonSubexpressions", "DiffResults", "DiffRules", "NaNMath", "Random", "SpecialFunctions", "StaticArrays"] -git-tree-sha1 = "d48a40c0f54f29a5c8748cfb3225719accc72b77" +deps = ["CommonSubexpressions", "DiffResults", "DiffRules", "LinearAlgebra", "NaNMath", "Printf", "Random", "SpecialFunctions", "StaticArrays"] +git-tree-sha1 = "e2af66012e08966366a43251e1fd421522908be6" uuid = "f6369f11-7733-5829-9624-2563aa707210" -version = "0.10.16" +version = "0.10.18" [[GZip]] deps = ["Libdl"] @@ -107,9 +115,9 @@ version = "0.5.1" [[HTTP]] deps = ["Base64", "Dates", "IniFile", "MbedTLS", "NetworkOptions", "Sockets", "URIs"] -git-tree-sha1 = "c9f380c76d8aaa1fa7ea9cf97bddbc0d5b15adc2" +git-tree-sha1 = "1fd26bc48f96adcdd8823f7fc300053faf3d7ba1" uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3" -version = "0.9.5" +version = "0.9.9" [[IniFile]] deps = ["Test"] @@ -122,9 +130,10 @@ deps = ["Markdown"] uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" [[JLLWrappers]] -git-tree-sha1 = "a431f5f2ca3f4feef3bd7a5e94b8b8d4f2f647a0" +deps = ["Preferences"] +git-tree-sha1 = "642a199af8b68253517b80bd3bfd17eb4e84df6e" uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" -version = "1.2.0" +version = "1.3.0" [[JSON]] deps = ["Dates", "Mmap", "Parsers", "Unicode"] @@ -139,15 +148,27 @@ uuid = "7d188eb4-7ad8-530c-ae41-71a32a6d4692" version = "0.3.3" [[JuMP]] -deps = ["Calculus", "DataStructures", "ForwardDiff", "JSON", "LinearAlgebra", "MathOptInterface", "MutableArithmetics", "NaNMath", "Random", "SparseArrays", "SpecialFunctions", "Statistics"] -git-tree-sha1 = "e952f49e2242fa21edcf27bbd6c67041685bee5d" +deps = ["Calculus", "DataStructures", "ForwardDiff", "JSON", "LinearAlgebra", "MathOptInterface", "MutableArithmetics", "NaNMath", "Printf", "Random", "SparseArrays", "SpecialFunctions", "Statistics"] +git-tree-sha1 = "8dfc5df8aad9f2cfebc8371b69700efd02060827" uuid = "4076af6c-e467-56ae-b986-b466b2749572" -version = "0.21.6" +version = "0.21.8" + +[[LibCURL]] +deps = ["LibCURL_jll", "MozillaCACerts_jll"] +uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" + +[[LibCURL_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] +uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" [[LibGit2]] -deps = ["Printf"] +deps = ["Base64", "NetworkOptions", "Printf", "SHA"] uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" +[[LibSSH2_jll]] +deps = ["Artifacts", "Libdl", "MbedTLS_jll"] +uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" + [[Libdl]] uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" @@ -155,6 +176,12 @@ uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" deps = ["Libdl"] uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +[[LogExpFunctions]] +deps = ["DocStringExtensions", "LinearAlgebra"] +git-tree-sha1 = "1ba664552f1ef15325e68dc4c05c3ef8c2d5d885" +uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688" +version = "0.2.4" + [[Logging]] uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" @@ -170,9 +197,9 @@ uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" [[MathOptInterface]] deps = ["BenchmarkTools", "CodecBzip2", "CodecZlib", "JSON", "JSONSchema", "LinearAlgebra", "MutableArithmetics", "OrderedCollections", "SparseArrays", "Test", "Unicode"] -git-tree-sha1 = "606efe4246da5407d7505265a1ead72467528996" +git-tree-sha1 = "575644e3c05b258250bb599e57cf73bbf1062901" uuid = "b8f27783-ece8-5eb3-8dc8-9495eed66fee" -version = "0.9.20" +version = "0.9.22" [[MbedTLS]] deps = ["Dates", "MbedTLS_jll", "Random", "Sockets"] @@ -181,19 +208,20 @@ uuid = "739be429-bea8-5141-9913-cc70e7f3736d" version = "1.0.3" [[MbedTLS_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "0eef589dd1c26a3ac9d753fe1a8bcad63f956fa6" +deps = ["Artifacts", "Libdl"] uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" -version = "2.16.8+1" [[Mmap]] uuid = "a63ad114-7e13-5084-954f-fe012c677804" +[[MozillaCACerts_jll]] +uuid = "14a3606d-f60d-562e-9121-12d972cd8159" + [[MutableArithmetics]] deps = ["LinearAlgebra", "SparseArrays", "Test"] -git-tree-sha1 = "6b6bb8f550dc38310afd4a0af0786dc3222459e2" +git-tree-sha1 = "ad9b2bce6021631e0e20706d361972343a03e642" uuid = "d8a4904e-b15c-11e9-3269-09a3773c0cb0" -version = "0.2.14" +version = "0.2.19" [[NaNMath]] git-tree-sha1 = "bfe47e760d60b82b66b61d2d44128b62e3a369fb" @@ -201,20 +229,18 @@ uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" version = "0.3.5" [[NetworkOptions]] -git-tree-sha1 = "ed3157f48a05543cce9b241e1f2815f7e843d96e" uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" -version = "1.2.0" [[OpenSpecFun_jll]] deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "9db77584158d0ab52307f8c04f8e7c08ca76b5b3" +git-tree-sha1 = "b9b8b8ed236998f91143938a760c2112dceeb2b4" uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e" -version = "0.5.3+4" +version = "0.5.4+0" [[OrderedCollections]] -git-tree-sha1 = "4fa2ba51070ec13fcc7517db714445b4ab986bdf" +git-tree-sha1 = "85f8e6578bf1f9ee0d11e7bb1b1456435479d47c" uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" -version = "1.4.0" +version = "1.4.1" [[PackageCompiler]] deps = ["Libdl", "Pkg", "UUIDs"] @@ -224,20 +250,26 @@ version = "1.2.5" [[Parsers]] deps = ["Dates"] -git-tree-sha1 = "223a825cccef2228f3fdbf2ecc7ca93363059073" +git-tree-sha1 = "c8abc88faa3f7a3950832ac5d6e690881590d6dc" uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" -version = "1.0.16" +version = "1.1.0" [[Pkg]] -deps = ["Dates", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"] +deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +[[Preferences]] +deps = ["TOML"] +git-tree-sha1 = "00cfd92944ca9c760982747e9a1d0d5d86ab1e5a" +uuid = "21216c6a-2e73-6563-6e65-726566657250" +version = "1.2.2" + [[Printf]] deps = ["Unicode"] uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" [[REPL]] -deps = ["InteractiveUtils", "Markdown", "Sockets"] +deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" [[Random]] @@ -262,23 +294,31 @@ deps = ["LinearAlgebra", "Random"] uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" [[SpecialFunctions]] -deps = ["ChainRulesCore", "OpenSpecFun_jll"] -git-tree-sha1 = "5919936c0e92cff40e57d0ddf0ceb667d42e5902" +deps = ["ChainRulesCore", "LogExpFunctions", "OpenSpecFun_jll"] +git-tree-sha1 = "371204984184315ed7228bcc604d08e1bbc18f31" uuid = "276daf66-3868-5448-9aa4-cd146d93841b" -version = "1.3.0" +version = "1.4.2" [[StaticArrays]] deps = ["LinearAlgebra", "Random", "Statistics"] -git-tree-sha1 = "9da72ed50e94dbff92036da395275ed114e04d49" +git-tree-sha1 = "a1f226ebe197578c25fcf948bfff3d0d12f2ff20" uuid = "90137ffa-7385-5640-81b9-e52037218182" -version = "1.0.1" +version = "1.2.1" [[Statistics]] deps = ["LinearAlgebra", "SparseArrays"] uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +[[TOML]] +deps = ["Dates"] +uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" + +[[Tar]] +deps = ["ArgTools", "SHA"] +uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" + [[Test]] -deps = ["Distributed", "InteractiveUtils", "Logging", "Random"] +deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [[TranscodingStreams]] @@ -288,9 +328,9 @@ uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa" version = "0.9.5" [[URIs]] -git-tree-sha1 = "7855809b88d7b16e9b029afd17880930626f54a2" +git-tree-sha1 = "97bbe755a53fe859669cd907f2d96aee8d2c1355" uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" -version = "1.2.0" +version = "1.3.0" [[UUIDs]] deps = ["Random", "SHA"] @@ -306,7 +346,13 @@ uuid = "a5390f91-8eb1-5f08-bee0-b1d1ffed6cea" version = "0.9.3" [[Zlib_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "320228915c8debb12cb434c59057290f0834dbf6" +deps = ["Libdl"] uuid = "83775a58-1f1d-513f-b197-d71354ab007a" -version = "1.2.11+18" + +[[nghttp2_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" + +[[p7zip_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" diff --git a/benchmark/Manifest.toml b/benchmark/Manifest.toml index c319e25..2dacf58 100644 --- a/benchmark/Manifest.toml +++ b/benchmark/Manifest.toml @@ -1,30 +1,30 @@ # This file is machine-generated - editing it directly is not advised +[[ArgTools]] +uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" + +[[Artifacts]] +uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" + [[Base64]] uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" [[BenchmarkTools]] deps = ["JSON", "Logging", "Printf", "Statistics", "UUIDs"] -git-tree-sha1 = "9e62e66db34540a0c919d72172cc2f642ac71260" +git-tree-sha1 = "01ca3823217f474243cc2c8e6e1d1f45956fe872" uuid = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" -version = "0.5.0" - -[[BinaryProvider]] -deps = ["Libdl", "Logging", "SHA"] -git-tree-sha1 = "ecdec412a9abc8db54c0efc5548c64dfce072058" -uuid = "b99e7846-7c00-51b0-8f62-c81ae34c0232" -version = "0.5.10" +version = "1.0.0" [[Bzip2_jll]] -deps = ["Libdl", "Pkg"] -git-tree-sha1 = "3663bfffede2ef41358b6fc2e1d8a6d50b3c3904" +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "19a35467a82e236ff51bc17a3a44b69ef35185a2" uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0" -version = "1.0.6+2" +version = "1.0.8+0" [[CEnum]] -git-tree-sha1 = "1b77a77c3b28e0b3f413f7567c9bb8dd9bdccd14" +git-tree-sha1 = "215a9aa4a1f23fbd05b92769fdd62559488d70e9" uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82" -version = "0.3.0" +version = "0.4.1" [[Calculus]] deps = ["LinearAlgebra"] @@ -32,35 +32,11 @@ git-tree-sha1 = "f641eb0a4f00c343bbc32346e1217b86f3ce9dad" uuid = "49dc2e85-a5d0-5ad3-a950-438e2897f1b9" version = "0.5.1" -[[Cbc]] -deps = ["BinaryProvider", "CEnum", "Cbc_jll", "Libdl", "MathOptInterface", "SparseArrays"] -git-tree-sha1 = "72e4299de0995a60a6230079adc7e47580870815" -uuid = "9961bab8-2fa3-5c5a-9d89-47fab24efd76" -version = "0.7.0" - -[[Cbc_jll]] -deps = ["Cgl_jll", "Clp_jll", "CoinUtils_jll", "CompilerSupportLibraries_jll", "Libdl", "OpenBLAS32_jll", "Osi_jll", "Pkg"] -git-tree-sha1 = "16b8ffa56b3ded6b201aa2f50623f260448aa205" -uuid = "38041ee0-ae04-5750-a4d2-bb4d0d83d27d" -version = "2.10.3+4" - -[[Cgl_jll]] -deps = ["Clp_jll", "CompilerSupportLibraries_jll", "Libdl", "Pkg"] -git-tree-sha1 = "32be20ec1e4c40e5c5d1bbf949ba9918a92a7569" -uuid = "3830e938-1dd0-5f3e-8b8e-b3ee43226782" -version = "0.60.2+5" - -[[Clp_jll]] -deps = ["CoinUtils_jll", "CompilerSupportLibraries_jll", "Libdl", "OpenBLAS32_jll", "Osi_jll", "Pkg"] -git-tree-sha1 = "70fe9e52fd95fa37f645e3d30f08f436cc5b1457" -uuid = "06985876-5285-5a41-9fcb-8948a742cc53" -version = "1.17.6+5" - -[[CodeTracking]] -deps = ["InteractiveUtils", "UUIDs"] -git-tree-sha1 = "cab4da992adc0a64f63fa30d2db2fd8bec40cab4" -uuid = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2" -version = "0.5.11" +[[ChainRulesCore]] +deps = ["Compat", "LinearAlgebra", "SparseArrays"] +git-tree-sha1 = "b391f22252b8754f4440de1f37ece49d8a7314bb" +uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" +version = "0.9.44" [[CodecBzip2]] deps = ["Bzip2_jll", "Libdl", "TranscodingStreams"] @@ -74,45 +50,47 @@ git-tree-sha1 = "ded953804d019afa9a3f98981d99b33e3db7b6da" uuid = "944b1d66-785c-5afd-91f1-9de20f533193" version = "0.7.0" -[[CoinUtils_jll]] -deps = ["CompilerSupportLibraries_jll", "Libdl", "OpenBLAS32_jll", "Pkg"] -git-tree-sha1 = "ee1f06ab89337b7f194c29377ab174e752cdf60d" -uuid = "be027038-0da8-5614-b30d-e42594cb92df" -version = "2.11.3+3" - [[CommonSubexpressions]] deps = ["MacroTools", "Test"] git-tree-sha1 = "7b8a93dba8af7e3b42fecabf646260105ac373f7" uuid = "bbf7d656-a473-5ed7-a52c-81e309532950" version = "0.3.0" +[[Compat]] +deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"] +git-tree-sha1 = "e4e2b39db08f967cc1360951f01e8a75ec441cab" +uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" +version = "3.30.0" + [[CompilerSupportLibraries_jll]] -deps = ["Libdl", "Pkg"] -git-tree-sha1 = "7c4f882c41faa72118841185afc58a2eb00ef612" +deps = ["Artifacts", "Libdl"] uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" -version = "0.3.3+0" [[DataStructures]] -deps = ["InteractiveUtils", "OrderedCollections"] -git-tree-sha1 = "edad9434967fdc0a2631a65d902228400642120c" +deps = ["Compat", "InteractiveUtils", "OrderedCollections"] +git-tree-sha1 = "4437b64df1e0adccc3e5d1adbc3ac741095e4677" uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" -version = "0.17.19" +version = "0.18.9" [[Dates]] deps = ["Printf"] uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" +[[DelimitedFiles]] +deps = ["Mmap"] +uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab" + [[DiffResults]] deps = ["StaticArrays"] -git-tree-sha1 = "da24935df8e0c6cf28de340b958f6aac88eaa0cc" +git-tree-sha1 = "c18e98cba888c6c25d1c3b048e4b3380ca956805" uuid = "163ba53b-c6d8-5494-b064-1a9d43ac40c5" -version = "1.0.2" +version = "1.0.3" [[DiffRules]] deps = ["NaNMath", "Random", "SpecialFunctions"] -git-tree-sha1 = "eb0c34204c8410888844ada5359ac8b96292cfd1" +git-tree-sha1 = "214c3fcac57755cfda163d91c58893a8723f93e9" uuid = "b552c78f-8df3-52c6-915a-8e097449b14b" -version = "1.0.1" +version = "1.0.2" [[Distributed]] deps = ["Random", "Serialization", "Sockets"] @@ -120,42 +98,19 @@ uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" [[DocStringExtensions]] deps = ["LibGit2", "Markdown", "Pkg", "Test"] -git-tree-sha1 = "c5714d9bcdba66389612dc4c47ed827c64112997" +git-tree-sha1 = "9d4f64f79012636741cf01133158a54b24924c32" uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" -version = "0.8.2" +version = "0.8.4" -[[Documenter]] -deps = ["Base64", "Dates", "DocStringExtensions", "InteractiveUtils", "JSON", "LibGit2", "Logging", "Markdown", "REPL", "Test", "Unicode"] -git-tree-sha1 = "1c593d1efa27437ed9dd365d1143c594b563e138" -uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4" -version = "0.25.1" - -[[FileWatching]] -uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" +[[Downloads]] +deps = ["ArgTools", "LibCURL", "NetworkOptions"] +uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" [[ForwardDiff]] -deps = ["CommonSubexpressions", "DiffResults", "DiffRules", "NaNMath", "Random", "SpecialFunctions", "StaticArrays"] -git-tree-sha1 = "1d090099fb82223abc48f7ce176d3f7696ede36d" +deps = ["CommonSubexpressions", "DiffResults", "DiffRules", "LinearAlgebra", "NaNMath", "Printf", "Random", "SpecialFunctions", "StaticArrays"] +git-tree-sha1 = "e2af66012e08966366a43251e1fd421522908be6" uuid = "f6369f11-7733-5829-9624-2563aa707210" -version = "0.10.12" - -[[GLPK]] -deps = ["BinaryProvider", "GLPK_jll", "Libdl", "MathOptInterface", "SparseArrays"] -git-tree-sha1 = "86573ecb852e303b209212046af44871f1c0e49c" -uuid = "60bf3e95-4087-53dc-ae20-288a0d20c6a6" -version = "0.13.0" - -[[GLPK_jll]] -deps = ["GMP_jll", "Libdl", "Pkg"] -git-tree-sha1 = "ccc855de74292e478d4278e3a6fdd8212f75e81e" -uuid = "e8aa6df9-e6ca-548a-97ff-1f85fc5b8b98" -version = "4.64.0+0" - -[[GMP_jll]] -deps = ["Libdl", "Pkg"] -git-tree-sha1 = "4dd9301d3a027c05ec403e756ee7a60e3c367e5d" -uuid = "781609d7-10c4-51f6-84f2-b8444358ff6d" -version = "6.1.2+5" +version = "0.10.18" [[GZip]] deps = ["Libdl"] @@ -164,16 +119,16 @@ uuid = "92fee26a-97fe-5a0c-ad85-20a5f3185b63" version = "0.5.1" [[Gurobi]] -deps = ["Libdl", "LinearAlgebra", "MathOptInterface", "MathProgBase", "SparseArrays"] -git-tree-sha1 = "f36a2fa62909675681aec582ccfc4a4a629406e4" +deps = ["CEnum", "Libdl", "MathOptInterface"] +git-tree-sha1 = "e923b82319aee3c7c5b64302b3a3aecc981382b9" uuid = "2e9cd046-0924-5485-92f1-d5272153d98b" -version = "0.8.1" +version = "0.9.13" [[HTTP]] -deps = ["Base64", "Dates", "IniFile", "MbedTLS", "Sockets"] -git-tree-sha1 = "2ac03263ce44be4222342bca1c51c36ce7566161" +deps = ["Base64", "Dates", "IniFile", "MbedTLS", "NetworkOptions", "Sockets", "URIs"] +git-tree-sha1 = "1fd26bc48f96adcdd8823f7fc300053faf3d7ba1" uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3" -version = "0.8.17" +version = "0.9.9" [[IniFile]] deps = ["Test"] @@ -185,34 +140,46 @@ version = "0.5.0" deps = ["Markdown"] uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" +[[JLLWrappers]] +deps = ["Preferences"] +git-tree-sha1 = "642a199af8b68253517b80bd3bfd17eb4e84df6e" +uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" +version = "1.3.0" + [[JSON]] deps = ["Dates", "Mmap", "Parsers", "Unicode"] -git-tree-sha1 = "b34d7cef7b337321e97d22242c3c2b91f476748e" +git-tree-sha1 = "81690084b6198a2e1da36fcfda16eeca9f9f24e4" uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" -version = "0.21.0" +version = "0.21.1" [[JSONSchema]] deps = ["HTTP", "JSON", "ZipFile"] -git-tree-sha1 = "832a4d327d9dafdae55a6ecae04f9997c83615cc" +git-tree-sha1 = "b84ab8139afde82c7c65ba2b792fe12e01dd7307" uuid = "7d188eb4-7ad8-530c-ae41-71a32a6d4692" -version = "0.3.0" +version = "0.3.3" [[JuMP]] -deps = ["Calculus", "DataStructures", "ForwardDiff", "LinearAlgebra", "MathOptInterface", "MutableArithmetics", "NaNMath", "Random", "SparseArrays", "Statistics"] -git-tree-sha1 = "cbab42e2e912109d27046aa88f02a283a9abac7c" +deps = ["Calculus", "DataStructures", "ForwardDiff", "JSON", "LinearAlgebra", "MathOptInterface", "MutableArithmetics", "NaNMath", "Printf", "Random", "SparseArrays", "SpecialFunctions", "Statistics"] +git-tree-sha1 = "8dfc5df8aad9f2cfebc8371b69700efd02060827" uuid = "4076af6c-e467-56ae-b986-b466b2749572" -version = "0.21.3" +version = "0.21.8" + +[[LibCURL]] +deps = ["LibCURL_jll", "MozillaCACerts_jll"] +uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" -[[JuliaInterpreter]] -deps = ["CodeTracking", "InteractiveUtils", "Random", "UUIDs"] -git-tree-sha1 = "79e4496b79e8af45198f8c291f26d4514d6b06d6" -uuid = "aa1ae85d-cabe-5617-a682-6adf51b2e16a" -version = "0.7.24" +[[LibCURL_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] +uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" [[LibGit2]] -deps = ["Printf"] +deps = ["Base64", "NetworkOptions", "Printf", "SHA"] uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" +[[LibSSH2_jll]] +deps = ["Artifacts", "Libdl", "MbedTLS_jll"] +uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" + [[Libdl]] uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" @@ -220,138 +187,116 @@ uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" deps = ["Libdl"] uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +[[LogExpFunctions]] +deps = ["DocStringExtensions", "LinearAlgebra"] +git-tree-sha1 = "1ba664552f1ef15325e68dc4c05c3ef8c2d5d885" +uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688" +version = "0.2.4" + [[Logging]] uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" -[[LoweredCodeUtils]] -deps = ["JuliaInterpreter"] -git-tree-sha1 = "1b632dc108106101a9909db7be8f8b32ed8d02f7" -uuid = "6f1432cf-f94c-5a45-995e-cdbf5db27b0b" -version = "0.4.6" - [[MacroTools]] deps = ["Markdown", "Random"] -git-tree-sha1 = "f7d2e3f654af75f01ec49be82c231c382214223a" +git-tree-sha1 = "6a8a2a625ab0dea913aba95c11370589e0239ff0" uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" -version = "0.5.5" +version = "0.5.6" [[Markdown]] deps = ["Base64"] uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" -[[MathOptFormat]] -deps = ["CodecZlib", "DataStructures", "HTTP", "JSON", "JSONSchema", "MathOptInterface"] -git-tree-sha1 = "0206edd9310b863c222af23f71fde5d09e95c20c" -uuid = "f4570300-c277-12e8-125c-4912f86ce65d" -version = "0.2.2" - [[MathOptInterface]] deps = ["BenchmarkTools", "CodecBzip2", "CodecZlib", "JSON", "JSONSchema", "LinearAlgebra", "MutableArithmetics", "OrderedCollections", "SparseArrays", "Test", "Unicode"] -git-tree-sha1 = "cd2049c055c7d192a235670d50faa375361624ba" +git-tree-sha1 = "575644e3c05b258250bb599e57cf73bbf1062901" uuid = "b8f27783-ece8-5eb3-8dc8-9495eed66fee" -version = "0.9.14" - -[[MathProgBase]] -deps = ["LinearAlgebra", "SparseArrays"] -git-tree-sha1 = "9abbe463a1e9fc507f12a69e7f29346c2cdc472c" -uuid = "fdba3010-5040-5b88-9595-932c9decdf73" -version = "0.7.8" +version = "0.9.22" [[MbedTLS]] deps = ["Dates", "MbedTLS_jll", "Random", "Sockets"] -git-tree-sha1 = "426a6978b03a97ceb7ead77775a1da066343ec6e" +git-tree-sha1 = "1c38e51c3d08ef2278062ebceade0e46cefc96fe" uuid = "739be429-bea8-5141-9913-cc70e7f3736d" -version = "1.0.2" +version = "1.0.3" [[MbedTLS_jll]] -deps = ["Libdl", "Pkg"] -git-tree-sha1 = "a0cb0d489819fa7ea5f9fa84c7e7eba19d8073af" +deps = ["Artifacts", "Libdl"] uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" -version = "2.16.6+1" [[Mmap]] uuid = "a63ad114-7e13-5084-954f-fe012c677804" +[[MozillaCACerts_jll]] +uuid = "14a3606d-f60d-562e-9121-12d972cd8159" + [[MutableArithmetics]] deps = ["LinearAlgebra", "SparseArrays", "Test"] -git-tree-sha1 = "6cf09794783b9de2e662c4e8b60d743021e338d0" +git-tree-sha1 = "ad9b2bce6021631e0e20706d361972343a03e642" uuid = "d8a4904e-b15c-11e9-3269-09a3773c0cb0" -version = "0.2.10" +version = "0.2.19" [[NaNMath]] -git-tree-sha1 = "c84c576296d0e2fbb3fc134d3e09086b3ea617cd" +git-tree-sha1 = "bfe47e760d60b82b66b61d2d44128b62e3a369fb" uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" -version = "0.3.4" +version = "0.3.5" -[[OpenBLAS32_jll]] -deps = ["CompilerSupportLibraries_jll", "Libdl", "Pkg"] -git-tree-sha1 = "793b33911239d2651c356c823492b58d6490d36a" -uuid = "656ef2d0-ae68-5445-9ca0-591084a874a2" -version = "0.3.9+4" +[[NetworkOptions]] +uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" [[OpenSpecFun_jll]] -deps = ["CompilerSupportLibraries_jll", "Libdl", "Pkg"] -git-tree-sha1 = "d51c416559217d974a1113522d5919235ae67a87" +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "b9b8b8ed236998f91143938a760c2112dceeb2b4" uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e" -version = "0.5.3+3" +version = "0.5.4+0" [[OrderedCollections]] -git-tree-sha1 = "293b70ac1780f9584c89268a6e2a560d938a7065" +git-tree-sha1 = "85f8e6578bf1f9ee0d11e7bb1b1456435479d47c" uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" -version = "1.3.0" - -[[Osi_jll]] -deps = ["CoinUtils_jll", "CompilerSupportLibraries_jll", "Libdl", "OpenBLAS32_jll", "Pkg"] -git-tree-sha1 = "bd436a97280df40938e66ae8d18e57aceb072856" -uuid = "7da25872-d9ce-5375-a4d3-7a845f58efdd" -version = "0.108.5+3" +version = "1.4.1" [[PackageCompiler]] deps = ["Libdl", "Pkg", "UUIDs"] -git-tree-sha1 = "98aa9c653e1dc3473bb5050caf8501293db9eee1" +git-tree-sha1 = "d448727c4b86be81b225b738c88d30334fda6779" uuid = "9b87118b-4619-50d2-8e1e-99f35a4d4d9d" -version = "1.2.1" +version = "1.2.5" [[Parsers]] -deps = ["Dates", "Test"] -git-tree-sha1 = "10134f2ee0b1978ae7752c41306e131a684e1f06" +deps = ["Dates"] +git-tree-sha1 = "c8abc88faa3f7a3950832ac5d6e690881590d6dc" uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" -version = "1.0.7" +version = "1.1.0" [[Pkg]] -deps = ["Dates", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"] +deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +[[Preferences]] +deps = ["TOML"] +git-tree-sha1 = "00cfd92944ca9c760982747e9a1d0d5d86ab1e5a" +uuid = "21216c6a-2e73-6563-6e65-726566657250" +version = "1.2.2" + [[Printf]] deps = ["Unicode"] uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" [[REPL]] -deps = ["InteractiveUtils", "Markdown", "Sockets"] +deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" [[Random]] deps = ["Serialization"] uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" -[[Requires]] -deps = ["UUIDs"] -git-tree-sha1 = "d37400976e98018ee840e0ca4f9d20baa231dc6b" -uuid = "ae029012-a4dd-5104-9daa-d747884805df" -version = "1.0.1" - -[[Revise]] -deps = ["CodeTracking", "Distributed", "FileWatching", "JuliaInterpreter", "LibGit2", "LoweredCodeUtils", "OrderedCollections", "Pkg", "REPL", "UUIDs", "Unicode"] -git-tree-sha1 = "0992d4643e27b2deb9f2e4ec7a56b7033813a027" -uuid = "295af30f-e4ad-537b-8983-00126c2a3abe" -version = "2.7.3" - [[SHA]] uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" [[Serialization]] uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" +[[SharedArrays]] +deps = ["Distributed", "Mmap", "Random", "Serialization"] +uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383" + [[Sockets]] uuid = "6462fe0b-24de-5631-8697-dd941f90decc" @@ -360,37 +305,44 @@ deps = ["LinearAlgebra", "Random"] uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" [[SpecialFunctions]] -deps = ["OpenSpecFun_jll"] -git-tree-sha1 = "d8d8b8a9f4119829410ecd706da4cc8594a1e020" +deps = ["ChainRulesCore", "LogExpFunctions", "OpenSpecFun_jll"] +git-tree-sha1 = "371204984184315ed7228bcc604d08e1bbc18f31" uuid = "276daf66-3868-5448-9aa4-cd146d93841b" -version = "0.10.3" +version = "1.4.2" [[StaticArrays]] deps = ["LinearAlgebra", "Random", "Statistics"] -git-tree-sha1 = "016d1e1a00fabc556473b07161da3d39726ded35" +git-tree-sha1 = "a1f226ebe197578c25fcf948bfff3d0d12f2ff20" uuid = "90137ffa-7385-5640-81b9-e52037218182" -version = "0.12.4" +version = "1.2.1" [[Statistics]] deps = ["LinearAlgebra", "SparseArrays"] uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +[[TOML]] +deps = ["Dates"] +uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" + +[[Tar]] +deps = ["ArgTools", "SHA"] +uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" + [[Test]] -deps = ["Distributed", "InteractiveUtils", "Logging", "Random"] +deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" -[[TimerOutputs]] -deps = ["Printf"] -git-tree-sha1 = "f458ca23ff80e46a630922c555d838303e4b9603" -uuid = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f" -version = "0.5.6" - [[TranscodingStreams]] deps = ["Random", "Test"] git-tree-sha1 = "7c53c35547de1c5b9d46a4797cf6d8253807108c" uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa" version = "0.9.5" +[[URIs]] +git-tree-sha1 = "97bbe755a53fe859669cd907f2d96aee8d2c1355" +uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" +version = "1.3.0" + [[UUIDs]] deps = ["Random", "SHA"] uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" @@ -399,19 +351,25 @@ uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" [[UnitCommitment]] -deps = ["Cbc", "DataStructures", "Documenter", "GLPK", "GZip", "JSON", "JuMP", "LinearAlgebra", "Logging", "MathOptFormat", "MathOptInterface", "PackageCompiler", "Printf", "Requires", "Revise", "SparseArrays", "Test", "TimerOutputs"] +deps = ["DataStructures", "GZip", "JSON", "JuMP", "LinearAlgebra", "Logging", "MathOptInterface", "PackageCompiler", "Printf", "SparseArrays"] path = ".." uuid = "64606440-39ea-11e9-0f29-3303a1d3d877" -version = "2.1.0" +version = "0.2.0" [[ZipFile]] deps = ["Libdl", "Printf", "Zlib_jll"] -git-tree-sha1 = "254975fef2fc526583bb9b7c9420fe66ffe09f2f" +git-tree-sha1 = "c3a5637e27e914a7a445b8d0ad063d701931e9f7" uuid = "a5390f91-8eb1-5f08-bee0-b1d1ffed6cea" -version = "0.9.2" +version = "0.9.3" [[Zlib_jll]] -deps = ["Libdl", "Pkg"] -git-tree-sha1 = "622d8b6dc0c7e8029f17127703de9819134d1b71" +deps = ["Libdl"] uuid = "83775a58-1f1d-513f-b197-d71354ab007a" -version = "1.2.11+14" + +[[nghttp2_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" + +[[p7zip_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" diff --git a/benchmark/run.jl b/benchmark/run.jl index b3c6fb9..783dabe 100644 --- a/benchmark/run.jl +++ b/benchmark/run.jl @@ -28,11 +28,15 @@ function main() @info @sprintf("Read problem in %.2f seconds", time_read) time_model = @elapsed begin - model = build_model(instance=instance, - optimizer=optimizer_with_attributes(Gurobi.Optimizer, - "Threads" => 4, - "Seed" => rand(1:1000), - )) + model = build_model( + instance=instance, + optimizer=optimizer_with_attributes( + Gurobi.Optimizer, + "Threads" => 4, + "Seed" => rand(1:1000), + ), + variable_names=true, + ) end @info "Optimizing..." @@ -43,7 +47,7 @@ function main() @info @sprintf("Total time was %.2f seconds", total_time) @info "Writing: $solution_filename" - solution = UnitCommitment.get_solution(model) + solution = UnitCommitment.solution(model) open(solution_filename, "w") do file JSON.print(file, solution, 2) end @@ -51,11 +55,8 @@ function main() @info "Verifying solution..." UnitCommitment.validate(instance, solution) - @info "Setting variable names..." - UnitCommitment.set_variable_names!(model) - @info "Exporting model..." - JuMP.write_to_file(model.mip, model_filename) + JuMP.write_to_file(model, model_filename) end main() diff --git a/docs/usage.md b/docs/usage.md index d6dab96..a670b66 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -53,7 +53,7 @@ model = UnitCommitment.build_model( UnitCommitment.optimize!(model) # Extract solution and write it to a file -solution = UnitCommitment.get_solution(model) +solution = UnitCommitment.solution(model) open("/path/to/output.json", "w") do file JSON.print(file, solution, 2) end diff --git a/src/UnitCommitment.jl b/src/UnitCommitment.jl index 7c335d3..cda6e23 100644 --- a/src/UnitCommitment.jl +++ b/src/UnitCommitment.jl @@ -4,7 +4,6 @@ module UnitCommitment include("log.jl") - include("dotdict.jl") include("instance.jl") include("screening.jl") include("model.jl") diff --git a/src/dotdict.jl b/src/dotdict.jl deleted file mode 100644 index 061a63c..0000000 --- a/src/dotdict.jl +++ /dev/null @@ -1,68 +0,0 @@ -# UnitCommitment.jl: Optimization Package for Security-Constrained Unit Commitment -# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. -# Released under the modified BSD license. See COPYING.md for more details. - -struct DotDict - inner::Dict -end - -DotDict() = DotDict(Dict()) - -function Base.setproperty!(d::DotDict, key::Symbol, value) - setindex!(getfield(d, :inner), value, key) -end - -function Base.getproperty(d::DotDict, key::Symbol) - (key == :inner ? getfield(d, :inner) : d.inner[key]) -end - -function Base.getindex(d::DotDict, key::Int64) - d.inner[Symbol(key)] -end - -function Base.getindex(d::DotDict, key::Symbol) - d.inner[key] -end - -function Base.keys(d::DotDict) - keys(d.inner) -end - -function Base.values(d::DotDict) - values(d.inner) -end - -function Base.iterate(d::DotDict) - iterate(values(d.inner)) -end - -function Base.iterate(d::DotDict, v::Int64) - iterate(values(d.inner), v) -end - -function Base.length(d::DotDict) - length(values(d.inner)) -end - -function Base.show(io::IO, d::DotDict) - print(io, "DotDict with $(length(keys(d.inner))) entries:\n") - count = 0 - for k in keys(d.inner) - count += 1 - if count > 10 - print(io, " ...\n") - break - end - print(io, " :$(k) => $(d.inner[k])\n") - end -end - -function recursive_to_dot_dict(el) - if typeof(el) == Dict{String, Any} - return DotDict(Dict(Symbol(k) => recursive_to_dot_dict(el[k]) for k in keys(el))) - else - return el - end -end - -export recursive_to_dot_dict \ No newline at end of file diff --git a/src/instance.jl b/src/instance.jl index cdde384..5bb8dcd 100644 --- a/src/instance.jl +++ b/src/instance.jl @@ -13,8 +13,8 @@ mutable struct Bus name::String offset::Int load::Vector{Float64} - units::Array - price_sensitive_loads::Array + units::Vector + price_sensitive_loads::Vector end diff --git a/src/model.jl b/src/model.jl index 4cea576..136359e 100644 --- a/src/model.jl +++ b/src/model.jl @@ -20,30 +20,16 @@ function set_name(x::Float64, n::String) # nop end - -mutable struct UnitCommitmentModel - mip::JuMP.Model - vars::DotDict - eqs::DotDict - exprs::DotDict - instance::UnitCommitmentInstance - isf::Matrix{Float64} - lodf::Matrix{Float64} - obj::AffExpr -end - - function build_model(; - filename::Union{String, Nothing}=nothing, - instance::Union{UnitCommitmentInstance, Nothing}=nothing, - isf::Union{Array{Float64,2}, Nothing}=nothing, - lodf::Union{Array{Float64,2}, Nothing}=nothing, - isf_cutoff::Float64=0.005, - lodf_cutoff::Float64=0.001, - optimizer=nothing, - model=nothing, - variable_names::Bool=false, - ) :: UnitCommitmentModel + filename::Union{String, Nothing}=nothing, + instance::Union{UnitCommitmentInstance, Nothing}=nothing, + isf::Union{Matrix{Float64}, Nothing}=nothing, + lodf::Union{Matrix{Float64}, Nothing}=nothing, + isf_cutoff::Float64=0.005, + lodf_cutoff::Float64=0.001, + optimizer=nothing, + variable_names::Bool=false, +)::JuMP.Model if (filename === nothing) && (instance === nothing) error("Either filename or instance must be specified") @@ -64,16 +50,20 @@ function build_model(; if isf === nothing @info "Computing injection shift factors..." time_isf = @elapsed begin - isf = UnitCommitment.injection_shift_factors(lines=instance.lines, - buses=instance.buses) + isf = UnitCommitment.injection_shift_factors( + lines=instance.lines, + buses=instance.buses, + ) end @info @sprintf("Computed ISF in %.2f seconds", time_isf) @info "Computing line outage factors..." time_lodf = @elapsed begin - lodf = UnitCommitment.line_outage_factors(lines=instance.lines, - buses=instance.buses, - isf=isf) + lodf = UnitCommitment.line_outage_factors( + lines=instance.lines, + buses=instance.buses, + isf=isf, + ) end @info @sprintf("Computed LODF in %.2f seconds", time_lodf) @@ -85,109 +75,138 @@ function build_model(; @info "Building model..." time_model = @elapsed begin - if model === nothing - if optimizer === nothing - mip = Model() - else - mip = Model(optimizer) - end - else - mip = model - end - model = UnitCommitmentModel(mip, - DotDict(), # vars - DotDict(), # eqs - DotDict(), # exprs - instance, - isf, - lodf, - AffExpr(), # obj - ) - for field in [:prod_above, :segprod, :reserve, :is_on, :switch_on, :switch_off, - :net_injection, :curtail, :overflow, :loads, :startup] - setproperty!(model.vars, field, OrderedDict()) + model = Model() + if optimizer !== nothing + set_optimizer(model, optimizer) end - for field in [:startup_choose, :startup_restrict, :segprod_limit, :prod_above_def, - :prod_limit, :binary_link, :switch_on_off, :ramp_up, :ramp_down, - :startup_limit, :shutdown_limit, :min_uptime, :min_downtime, :power_balance, - :net_injection_def, :min_reserve] - setproperty!(model.eqs, field, OrderedDict()) - end - for field in [:inj, :reserve, :net_injection] - setproperty!(model.exprs, field, OrderedDict()) + model[:obj] = AffExpr() + model[:instance] = instance + model[:isf] = isf + model[:lodf] = lodf + for field in [ + :prod_above, + :segprod, + :reserve, + :is_on, + :switch_on, + :switch_off, + :net_injection, + :curtail, + :overflow, + :loads, + :startup, + :eq_startup_choose, + :eq_startup_restrict, + :eq_segprod_limit, + :eq_prod_above_def, + :eq_prod_limit, + :eq_binary_link, + :eq_switch_on_off, + :eq_ramp_up, + :eq_ramp_down, + :eq_startup_limit, + :eq_shutdown_limit, + :eq_min_uptime, + :eq_min_downtime, + :eq_power_balance, + :eq_net_injection_def, + :eq_min_reserve, + :expr_inj, + :expr_reserve, + :expr_net_injection, + ] + model[field] = OrderedDict() end for lm in instance.lines - add_transmission_line!(model, lm) + _add_transmission_line!(model, lm) end for b in instance.buses - add_bus!(model, b) + _add_bus!(model, b) end for g in instance.units - add_unit!(model, g) + _add_unit!(model, g) end for ps in instance.price_sensitive_loads - add_price_sensitive_load!(model, ps) + _add_price_sensitive_load!(model, ps) end - build_net_injection_eqs!(model) - build_reserve_eqs!(model) - build_obj_function!(model) + _build_net_injection_eqs!(model) + _build_reserve_eqs!(model) + _build_obj_function!(model) end @info @sprintf("Built model in %.2f seconds", time_model) if variable_names - set_variable_names!(model) + _set_names!(model) end return model end -function add_transmission_line!(model, lm) - vars, obj, T = model.vars, model.obj, model.instance.time +function _add_transmission_line!(model, lm) + obj, T = model[:obj], model[:instance].time + overflow = model[:overflow] for t in 1:T - overflow = vars.overflow[lm.name, t] = @variable(model.mip, lower_bound=0) - add_to_expression!(obj, overflow, lm.flow_limit_penalty[t]) + v = overflow[lm.name, t] = @variable(model, lower_bound=0) + add_to_expression!(obj, v, lm.flow_limit_penalty[t]) end end -function add_bus!(model::UnitCommitmentModel, b::Bus) - mip, vars, exprs = model.mip, model.vars, model.exprs - for t in 1:model.instance.time +function _add_bus!(model::JuMP.Model, b::Bus) + mip = model + net_injection = model[:expr_net_injection] + reserve = model[:expr_reserve] + curtail = model[:curtail] + for t in 1:model[:instance].time # Fixed load - exprs.net_injection[b.name, t] = AffExpr(-b.load[t]) + net_injection[b.name, t] = AffExpr(-b.load[t]) # Reserves - exprs.reserve[b.name, t] = AffExpr() + reserve[b.name, t] = AffExpr() # Load curtailment - vars.curtail[b.name, t] = @variable(mip, lower_bound=0, upper_bound=b.load[t]) - add_to_expression!(exprs.net_injection[b.name, t], vars.curtail[b.name, t], 1.0) - add_to_expression!(model.obj, - vars.curtail[b.name, t], - model.instance.power_balance_penalty[t]) + curtail[b.name, t] = @variable(mip, lower_bound=0, upper_bound=b.load[t]) + add_to_expression!(net_injection[b.name, t], curtail[b.name, t], 1.0) + add_to_expression!( + model[:obj], + curtail[b.name, t], + model[:instance].power_balance_penalty[t], + ) end end -function add_price_sensitive_load!(model::UnitCommitmentModel, ps::PriceSensitiveLoad) - mip, vars = model.mip, model.vars - for t in 1:model.instance.time +function _add_price_sensitive_load!(model::JuMP.Model, ps::PriceSensitiveLoad) + mip = model + loads = model[:loads] + net_injection = model[:expr_net_injection] + for t in 1:model[:instance].time # Decision variable - vars.loads[ps.name, t] = @variable(mip, lower_bound=0, upper_bound=ps.demand[t]) + loads[ps.name, t] = @variable(mip, lower_bound=0, upper_bound=ps.demand[t]) # Objective function terms - add_to_expression!(model.obj, vars.loads[ps.name, t], -ps.revenue[t]) + add_to_expression!(model[:obj], loads[ps.name, t], -ps.revenue[t]) # Net injection - add_to_expression!(model.exprs.net_injection[ps.bus.name, t], vars.loads[ps.name, t], -1.0) + add_to_expression!(net_injection[ps.bus.name, t], loads[ps.name, t], -1.0) end end -function add_unit!(model::UnitCommitmentModel, g::Unit) - mip, vars, eqs, exprs, T = model.mip, model.vars, model.eqs, model.exprs, model.instance.time +function _add_unit!(model::JuMP.Model, g::Unit) + mip, T = model, model[:instance].time gi, K, S = g.name, length(g.cost_segments), length(g.startup_categories) + + segprod = model[:segprod] + prod_above = model[:prod_above] + reserve = model[:reserve] + startup = model[:startup] + is_on = model[:is_on] + switch_on = model[:switch_on] + switch_off = model[:switch_off] + expr_net_injection = model[:expr_net_injection] + expr_reserve = model[:expr_reserve] if !all(g.must_run) && any(g.must_run) error("Partially must-run units are not currently supported") @@ -202,25 +221,25 @@ function add_unit!(model::UnitCommitmentModel, g::Unit) # Decision variables for t in 1:T for k in 1:K - model.vars.segprod[gi, t, k] = @variable(model.mip, lower_bound=0) + segprod[gi, t, k] = @variable(model, lower_bound=0) end - model.vars.prod_above[gi, t] = @variable(model.mip, lower_bound=0) + prod_above[gi, t] = @variable(model, lower_bound=0) if g.provides_spinning_reserves[t] - model.vars.reserve[gi, t] = @variable(model.mip, lower_bound=0) + reserve[gi, t] = @variable(model, lower_bound=0) else - model.vars.reserve[gi, t] = 0.0 + reserve[gi, t] = 0.0 end for s in 1:S - model.vars.startup[gi, t, s] = @variable(model.mip, binary=true) + startup[gi, t, s] = @variable(model, binary=true) end if g.must_run[t] - model.vars.is_on[gi, t] = 1.0 - model.vars.switch_on[gi, t] = (t == 1 ? 1.0 - is_initially_on : 0.0) - model.vars.switch_off[gi, t] = 0.0 + is_on[gi, t] = 1.0 + switch_on[gi, t] = (t == 1 ? 1.0 - is_initially_on : 0.0) + switch_off[gi, t] = 0.0 else - model.vars.is_on[gi, t] = @variable(model.mip, binary=true) - model.vars.switch_on[gi, t] = @variable(model.mip, binary=true) - model.vars.switch_off[gi, t] = @variable(model.mip, binary=true) + is_on[gi, t] = @variable(model, binary=true) + switch_on[gi, t] = @variable(model, binary=true) + switch_off[gi, t] = @variable(model, binary=true) end end @@ -228,224 +247,244 @@ function add_unit!(model::UnitCommitmentModel, g::Unit) # Time-dependent start-up costs for s in 1:S # If unit is switching on, we must choose a startup category - eqs.startup_choose[gi, t, s] = - @constraint(mip, vars.switch_on[gi, t] == sum(vars.startup[gi, t, s] for s in 1:S)) + model[:eq_startup_choose][gi, t, s] = + @constraint(mip, switch_on[gi, t] == sum(startup[gi, t, s] for s in 1:S)) # If unit has not switched off in the last `delay` time periods, startup category is forbidden. # The last startup category is always allowed. if s < S range = (t - g.startup_categories[s + 1].delay + 1):(t - g.startup_categories[s].delay) initial_sum = (g.initial_status < 0 && (g.initial_status + 1 in range) ? 1.0 : 0.0) - eqs.startup_restrict[gi, t, s] = - @constraint(mip, vars.startup[gi, t, s] - <= initial_sum + sum(vars.switch_off[gi, i] for i in range if i >= 1)) + model[:eq_startup_restrict][gi, t, s] = + @constraint(mip, startup[gi, t, s] + <= initial_sum + sum(switch_off[gi, i] for i in range if i >= 1)) end # Objective function terms for start-up costs - add_to_expression!(model.obj, - vars.startup[gi, t, s], - g.startup_categories[s].cost) + add_to_expression!( + model[:obj], + startup[gi, t, s], + g.startup_categories[s].cost, + ) end # Objective function terms for production costs - add_to_expression!(model.obj, vars.is_on[gi, t], g.min_power_cost[t]) + add_to_expression!(model[:obj], is_on[gi, t], g.min_power_cost[t]) for k in 1:K - add_to_expression!(model.obj, vars.segprod[gi, t, k], g.cost_segments[k].cost[t]) + add_to_expression!(model[:obj], segprod[gi, t, k], g.cost_segments[k].cost[t]) end # Production limits (piecewise-linear segments) for k in 1:K - eqs.segprod_limit[gi, t, k] = - @constraint(mip, vars.segprod[gi, t, k] <= g.cost_segments[k].mw[t] * vars.is_on[gi, t]) + model[:eq_segprod_limit][gi, t, k] = + @constraint(mip, segprod[gi, t, k] <= g.cost_segments[k].mw[t] * is_on[gi, t]) end # Definition of production - eqs.prod_above_def[gi, t] = - @constraint(mip, vars.prod_above[gi, t] == sum(vars.segprod[gi, t, k] for k in 1:K)) + model[:eq_prod_above_def][gi, t] = + @constraint(mip, prod_above[gi, t] == sum(segprod[gi, t, k] for k in 1:K)) # Production limit - eqs.prod_limit[gi, t] = + model[:eq_prod_limit][gi, t] = @constraint(mip, - vars.prod_above[gi, t] + vars.reserve[gi, t] - <= (g.max_power[t] - g.min_power[t]) * vars.is_on[gi, t]) + prod_above[gi, t] + reserve[gi, t] + <= (g.max_power[t] - g.min_power[t]) * is_on[gi, t]) # Binary variable equations for economic units if !g.must_run[t] # Link binary variables if t == 1 - eqs.binary_link[gi, t] = + model[:eq_binary_link][gi, t] = @constraint(mip, - vars.is_on[gi, t] - is_initially_on == - vars.switch_on[gi, t] - vars.switch_off[gi, t]) + is_on[gi, t] - is_initially_on == + switch_on[gi, t] - switch_off[gi, t]) else - eqs.binary_link[gi, t] = + model[:eq_binary_link][gi, t] = @constraint(mip, - vars.is_on[gi, t] - vars.is_on[gi, t-1] == - vars.switch_on[gi, t] - vars.switch_off[gi, t]) + is_on[gi, t] - is_on[gi, t-1] == + switch_on[gi, t] - switch_off[gi, t]) end # Cannot switch on and off at the same time - eqs.switch_on_off[gi, t] = - @constraint(mip, vars.switch_on[gi, t] + vars.switch_off[gi, t] <= 1) + model[:eq_switch_on_off][gi, t] = + @constraint(mip, switch_on[gi, t] + switch_off[gi, t] <= 1) end # Ramp up limit if t == 1 if is_initially_on == 1 - eqs.ramp_up[gi, t] = + model[:eq_ramp_up][gi, t] = @constraint(mip, - vars.prod_above[gi, t] + vars.reserve[gi, t] <= + prod_above[gi, t] + reserve[gi, t] <= (g.initial_power - g.min_power[t]) + g.ramp_up_limit) end else - eqs.ramp_up[gi, t] = + model[:eq_ramp_up][gi, t] = @constraint(mip, - vars.prod_above[gi, t] + vars.reserve[gi, t] <= - vars.prod_above[gi, t-1] + g.ramp_up_limit) + prod_above[gi, t] + reserve[gi, t] <= + prod_above[gi, t-1] + g.ramp_up_limit) end # Ramp down limit if t == 1 if is_initially_on == 1 - eqs.ramp_down[gi, t] = + model[:eq_ramp_down][gi, t] = @constraint(mip, - vars.prod_above[gi, t] >= + prod_above[gi, t] >= (g.initial_power - g.min_power[t]) - g.ramp_down_limit) end else - eqs.ramp_down[gi, t] = + model[:eq_ramp_down][gi, t] = @constraint(mip, - vars.prod_above[gi, t] >= - vars.prod_above[gi, t-1] - g.ramp_down_limit) + prod_above[gi, t] >= + prod_above[gi, t-1] - g.ramp_down_limit) end # Startup limit - eqs.startup_limit[gi, t] = + model[:eq_startup_limit][gi, t] = @constraint(mip, - vars.prod_above[gi, t] + vars.reserve[gi, t] <= - (g.max_power[t] - g.min_power[t]) * vars.is_on[gi, t] - - max(0, g.max_power[t] - g.startup_limit) * vars.switch_on[gi, t]) + prod_above[gi, t] + reserve[gi, t] <= + (g.max_power[t] - g.min_power[t]) * is_on[gi, t] + - max(0, g.max_power[t] - g.startup_limit) * switch_on[gi, t]) # Shutdown limit if g.initial_power > g.shutdown_limit - eqs.shutdown_limit[gi, 0] = - @constraint(mip, vars.switch_off[gi, 1] <= 0) + model[:eq_shutdown_limit][gi, 0] = + @constraint(mip, switch_off[gi, 1] <= 0) end if t < T - eqs.shutdown_limit[gi, t] = + model[:eq_shutdown_limit][gi, t] = @constraint(mip, - vars.prod_above[gi, t] <= - (g.max_power[t] - g.min_power[t]) * vars.is_on[gi, t] - - max(0, g.max_power[t] - g.shutdown_limit) * vars.switch_off[gi, t+1]) + prod_above[gi, t] <= + (g.max_power[t] - g.min_power[t]) * is_on[gi, t] + - max(0, g.max_power[t] - g.shutdown_limit) * switch_off[gi, t+1]) end # Minimum up-time - eqs.min_uptime[gi, t] = + model[:eq_min_uptime][gi, t] = @constraint(mip, - sum(vars.switch_on[gi, i] + sum(switch_on[gi, i] for i in (t - g.min_uptime + 1):t if i >= 1 - ) <= vars.is_on[gi, t]) + ) <= is_on[gi, t]) # # Minimum down-time - eqs.min_downtime[gi, t] = + model[:eq_min_downtime][gi, t] = @constraint(mip, - sum(vars.switch_off[gi, i] + sum(switch_off[gi, i] for i in (t - g.min_downtime + 1):t if i >= 1 - ) <= 1 - vars.is_on[gi, t]) + ) <= 1 - is_on[gi, t]) # Minimum up/down-time for initial periods if t == 1 if g.initial_status > 0 - eqs.min_uptime[gi, 0] = - @constraint(mip, sum(vars.switch_off[gi, i] + model[:eq_min_uptime][gi, 0] = + @constraint(mip, sum(switch_off[gi, i] for i in 1:(g.min_uptime - g.initial_status) if i <= T) == 0) else - eqs.min_downtime[gi, 0] = - @constraint(mip, sum(vars.switch_on[gi, i] + model[:eq_min_downtime][gi, 0] = + @constraint(mip, sum(switch_on[gi, i] for i in 1:(g.min_downtime + g.initial_status) if i <= T) == 0) end end # Add to net injection expression - add_to_expression!(exprs.net_injection[g.bus.name, t], vars.prod_above[g.name, t], 1.0) - add_to_expression!(exprs.net_injection[g.bus.name, t], vars.is_on[g.name, t], g.min_power[t]) + add_to_expression!(expr_net_injection[g.bus.name, t], prod_above[g.name, t], 1.0) + add_to_expression!(expr_net_injection[g.bus.name, t], is_on[g.name, t], g.min_power[t]) # Add to reserves expression - add_to_expression!(exprs.reserve[g.bus.name, t], vars.reserve[gi, t], 1.0) + add_to_expression!(expr_reserve[g.bus.name, t], reserve[gi, t], 1.0) end end -function build_obj_function!(model::UnitCommitmentModel) - @objective(model.mip, Min, model.obj) +function _build_obj_function!(model::JuMP.Model) + @objective(model, Min, model[:obj]) end -function build_net_injection_eqs!(model::UnitCommitmentModel) - T = model.instance.time - for t in 1:T, b in model.instance.buses - net = model.vars.net_injection[b.name, t] = @variable(model.mip) - model.eqs.net_injection_def[t, b.name] = - @constraint(model.mip, net == model.exprs.net_injection[b.name, t]) +function _build_net_injection_eqs!(model::JuMP.Model) + T = model[:instance].time + net_injection = model[:net_injection] + for t in 1:T, b in model[:instance].buses + n = net_injection[b.name, t] = @variable(model) + model[:eq_net_injection_def][t, b.name] = + @constraint(model, n == model[:expr_net_injection][b.name, t]) end for t in 1:T - model.eqs.power_balance[t] = - @constraint(model.mip, sum(model.vars.net_injection[b.name, t] - for b in model.instance.buses) == 0) + model[:eq_power_balance][t] = + @constraint( + model, + sum( + net_injection[b.name, t] + for b in model[:instance].buses + ) == 0 + ) end end -function build_reserve_eqs!(model::UnitCommitmentModel) - reserves = model.instance.reserves - for t in 1:model.instance.time - model.eqs.min_reserve[t] = - @constraint(model.mip, sum(model.exprs.reserve[b.name, t] - for b in model.instance.buses) >= reserves.spinning[t]) +function _build_reserve_eqs!(model::JuMP.Model) + reserves = model[:instance].reserves + for t in 1:model[:instance].time + model[:eq_min_reserve][t] = + @constraint( + model, + sum( + model[:expr_reserve][b.name, t] + for b in model[:instance].buses + ) >= reserves.spinning[t] + ) end end -function enforce_transmission(; - model::UnitCommitmentModel, - violation::Violation, - isf::Matrix{Float64}, - lodf::Matrix{Float64})::Nothing - - instance, mip, vars = model.instance, model.mip, model.vars +function enforce_transmission( + ; + model::JuMP.Model, + violation::Violation, + isf::Matrix{Float64}, + lodf::Matrix{Float64}, +)::Nothing + instance = model[:instance] limit::Float64 = 0.0 + overflow = model[:overflow] + net_injection = model[:net_injection] if violation.outage_line === nothing limit = violation.monitored_line.normal_flow_limit[violation.time] - @info @sprintf(" %8.3f MW overflow in %-5s time %3d (pre-contingency)", - violation.amount, - violation.monitored_line.name, - violation.time) + @info @sprintf( + " %8.3f MW overflow in %-5s time %3d (pre-contingency)", + violation.amount, + violation.monitored_line.name, + violation.time, + ) else limit = violation.monitored_line.emergency_flow_limit[violation.time] - @info @sprintf(" %8.3f MW overflow in %-5s time %3d (outage: line %s)", - violation.amount, - violation.monitored_line.name, - violation.time, - violation.outage_line.name) + @info @sprintf( + " %8.3f MW overflow in %-5s time %3d (outage: line %s)", + violation.amount, + violation.monitored_line.name, + violation.time, + violation.outage_line.name, + ) end fm = violation.monitored_line.name t = violation.time - flow = @variable(mip, base_name="flow[$fm,$t]") + flow = @variable(model, base_name="flow[$fm,$t]") - overflow = vars.overflow[violation.monitored_line.name, violation.time] - @constraint(mip, flow <= limit + overflow) - @constraint(mip, -flow <= limit + overflow) + v = overflow[violation.monitored_line.name, violation.time] + @constraint(model, flow <= limit + v) + @constraint(model, -flow <= limit + v) if violation.outage_line === nothing - @constraint(mip, flow == sum(vars.net_injection[b.name, violation.time] * + @constraint(model, flow == sum(net_injection[b.name, violation.time] * isf[violation.monitored_line.offset, b.offset] for b in instance.buses if b.offset > 0)) else - @constraint(mip, flow == sum(vars.net_injection[b.name, violation.time] * ( + @constraint(model, flow == sum(net_injection[b.name, violation.time] * ( isf[violation.monitored_line.offset, b.offset] + ( lodf[violation.monitored_line.offset, violation.outage_line.offset] * isf[violation.outage_line.offset, b.offset] @@ -458,19 +497,22 @@ function enforce_transmission(; end -function set_variable_names!(model::UnitCommitmentModel) +function _set_names!(model::JuMP.Model) @info "Setting variable and constraint names..." time_varnames = @elapsed begin - set_jump_names!(model.vars) - set_jump_names!(model.eqs) + _set_names!(object_dictionary(model)) end @info @sprintf("Set names in %.2f seconds", time_varnames) end -function set_jump_names!(dict) +function _set_names!(dict::Dict) for name in keys(dict) + dict[name] isa AbstractDict || continue for idx in keys(dict[name]) + if dict[name][idx] isa AffExpr + continue + end idx_str = join(map(string, idx), ",") set_name(dict[name][idx], "$name[$idx_str]") end @@ -478,27 +520,41 @@ function set_jump_names!(dict) end -function get_solution(model::UnitCommitmentModel) - instance, T = model.instance, model.instance.time +function solution(model::JuMP.Model) + instance, T = model[:instance], model[:instance].time function timeseries(vars, collection) - return OrderedDict(b.name => [round(value(vars[b.name, t]), digits=5) for t in 1:T] - for b in collection) + return OrderedDict( + b.name => [round(value(vars[b.name, t]), digits=5) for t in 1:T] + for b in collection + ) end function production_cost(g) - return [value(model.vars.is_on[g.name, t]) * g.min_power_cost[t] + - sum(Float64[value(model.vars.segprod[g.name, t, k]) * g.cost_segments[k].cost[t] - for k in 1:length(g.cost_segments)]) - for t in 1:T] + return [ + value(model[:is_on][g.name, t]) * g.min_power_cost[t] + + sum( + Float64[ + value(model[:segprod][g.name, t, k]) * g.cost_segments[k].cost[t] + for k in 1:length(g.cost_segments) + ] + ) + for t in 1:T + ] end function production(g) - return [value(model.vars.is_on[g.name, t]) * g.min_power[t] + - sum(Float64[value(model.vars.segprod[g.name, t, k]) - for k in 1:length(g.cost_segments)]) - for t in 1:T] + return [ + value(model[:is_on][g.name, t]) * g.min_power[t] + + sum( + Float64[ + value(model[:segprod][g.name, t, k]) + for k in 1:length(g.cost_segments) + ] + ) + for t in 1:T + ] end function startup_cost(g) S = length(g.startup_categories) - return [sum(g.startup_categories[s].cost * value(model.vars.startup[g.name, t, s]) + return [sum(g.startup_categories[s].cost * value(model[:startup][g.name, t, s]) for s in 1:S) for t in 1:T] end @@ -506,69 +562,80 @@ function get_solution(model::UnitCommitmentModel) sol["Production (MW)"] = OrderedDict(g.name => production(g) for g in instance.units) sol["Production cost (\$)"] = OrderedDict(g.name => production_cost(g) for g in instance.units) sol["Startup cost (\$)"] = OrderedDict(g.name => startup_cost(g) for g in instance.units) - sol["Is on"] = timeseries(model.vars.is_on, instance.units) - sol["Switch on"] = timeseries(model.vars.switch_on, instance.units) - sol["Switch off"] = timeseries(model.vars.switch_off, instance.units) - sol["Reserve (MW)"] = timeseries(model.vars.reserve, instance.units) - sol["Net injection (MW)"] = timeseries(model.vars.net_injection, instance.buses) - sol["Load curtail (MW)"] = timeseries(model.vars.curtail, instance.buses) + sol["Is on"] = timeseries(model[:is_on], instance.units) + sol["Switch on"] = timeseries(model[:switch_on], instance.units) + sol["Switch off"] = timeseries(model[:switch_off], instance.units) + sol["Reserve (MW)"] = timeseries(model[:reserve], instance.units) + sol["Net injection (MW)"] = timeseries(model[:net_injection], instance.buses) + sol["Load curtail (MW)"] = timeseries(model[:curtail], instance.buses) if !isempty(instance.lines) - sol["Line overflow (MW)"] = timeseries(model.vars.overflow, instance.lines) + sol["Line overflow (MW)"] = timeseries(model[:overflow], instance.lines) end if !isempty(instance.price_sensitive_loads) - sol["Price-sensitive loads (MW)"] = timeseries(model.vars.loads, instance.price_sensitive_loads) + sol["Price-sensitive loads (MW)"] = timeseries(model[:loads], instance.price_sensitive_loads) end return sol end -function fix!(model::UnitCommitmentModel, solution)::Nothing - vars, instance, T = model.vars, model.instance, model.instance.time +function fix!(model::JuMP.Model, solution)::Nothing + instance, T = model[:instance], model[:instance].time + is_on = model[:is_on] + prod_above = model[:prod_above] + reserve = model[:reserve] for g in instance.units for t in 1:T - is_on = round(solution["Is on"][g.name][t]) - production = round(solution["Production (MW)"][g.name][t], digits=5) - reserve = round(solution["Reserve (MW)"][g.name][t], digits=5) - JuMP.fix(vars.is_on[g.name, t], is_on, force=true) - JuMP.fix(vars.prod_above[g.name, t], production - is_on * g.min_power[t], force=true) - JuMP.fix(vars.reserve[g.name, t], reserve, force=true) + is_on_value = round(solution["Is on"][g.name][t]) + production_value = round(solution["Production (MW)"][g.name][t], digits=5) + reserve_value = round(solution["Reserve (MW)"][g.name][t], digits=5) + JuMP.fix(is_on[g.name, t], is_on_value, force=true) + JuMP.fix( + prod_above[g.name, t], + production_value - is_on_value * g.min_power[t], + force=true, + ) + JuMP.fix(reserve[g.name, t], reserve_value, force=true) end end end -function set_warm_start!(model::UnitCommitmentModel, solution)::Nothing - vars, instance, T = model.vars, model.instance, model.instance.time +function set_warm_start!(model::JuMP.Model, solution)::Nothing + instance, T = model[:instance], model[:instance].time + is_on = model[:is_on] + prod_above = model[:prod_above] + reserve = model[:reserve] for g in instance.units for t in 1:T - JuMP.set_start_value(vars.is_on[g.name, t], solution["Is on"][g.name][t]) - JuMP.set_start_value(vars.switch_on[g.name, t], solution["Switch on"][g.name][t]) - JuMP.set_start_value(vars.switch_off[g.name, t], solution["Switch off"][g.name][t]) + JuMP.set_start_value(is_on[g.name, t], solution["Is on"][g.name][t]) + JuMP.set_start_value(switch_on[g.name, t], solution["Switch on"][g.name][t]) + JuMP.set_start_value(switch_off[g.name, t], solution["Switch off"][g.name][t]) end end end -function optimize!(model::UnitCommitmentModel; - time_limit=3600, - gap_limit=1e-4, - two_phase_gap=true, - )::Nothing +function optimize!( + model::JuMP.Model; + time_limit=3600, + gap_limit=1e-4, + two_phase_gap=true, +)::Nothing function set_gap(gap) try - JuMP.set_optimizer_attribute(model.mip, "MIPGap", gap) + JuMP.set_optimizer_attribute(model, "MIPGap", gap) @info @sprintf("MIP gap tolerance set to %f", gap) catch @warn "Could not change MIP gap tolerance" end end - instance = model.instance + instance = model[:instance] initial_time = time() large_gap = false - has_transmission = (length(model.isf) > 0) + has_transmission = (length(model[:isf]) > 0) if has_transmission && two_phase_gap set_gap(1e-2) @@ -586,10 +653,10 @@ function optimize!(model::UnitCommitmentModel; end @info @sprintf("Setting MILP time limit to %.2f seconds", time_remaining) - JuMP.set_time_limit_sec(model.mip, time_remaining) + JuMP.set_time_limit_sec(model, time_remaining) @info "Solving MILP..." - JuMP.optimize!(model.mip) + JuMP.optimize!(model) has_transmission || break @@ -611,36 +678,49 @@ function optimize!(model::UnitCommitmentModel; end -function find_violations(model::UnitCommitmentModel) - instance, vars = model.instance, model.vars +function find_violations(model::JuMP.Model) + instance = model[:instance] + net_injection = model[:net_injection] + overflow = model[:overflow] length(instance.buses) > 1 || return [] violations = [] @info "Verifying transmission limits..." time_screening = @elapsed begin non_slack_buses = [b for b in instance.buses if b.offset > 0] - net_injections = [value(vars.net_injection[b.name, t]) - for b in non_slack_buses, t in 1:instance.time] - overflow = [value(vars.overflow[lm.name, t]) - for lm in instance.lines, t in 1:instance.time] - violations = UnitCommitment.find_violations(instance=instance, - net_injections=net_injections, - overflow=overflow, - isf=model.isf, - lodf=model.lodf) + net_injection_values = [ + value(net_injection[b.name, t]) + for b in non_slack_buses, t in 1:instance.time + ] + overflow_values = [ + value(overflow[lm.name, t]) + for lm in instance.lines, t in 1:instance.time + ] + violations = UnitCommitment.find_violations( + instance=instance, + net_injections=net_injection_values, + overflow=overflow_values, + isf=model[:isf], + lodf=model[:lodf], + ) end @info @sprintf("Verified transmission limits in %.2f seconds", time_screening) return violations end -function enforce_transmission(model::UnitCommitmentModel, violations::Array{Violation, 1}) +function enforce_transmission( + model::JuMP.Model, + violations::Vector{Violation}, +)::Nothing for v in violations - enforce_transmission(model=model, - violation=v, - isf=model.isf, - lodf=model.lodf) - end + enforce_transmission( + model=model, + violation=v, + isf=model[:isf], + lodf=model[:lodf], + ) + end + return end - -export UnitCommitmentModel, build_model, get_solution, optimize! +export build_model \ No newline at end of file diff --git a/test/model_test.jl b/test/model_test.jl index 7d75d2e..1257173 100644 --- a/test/model_test.jl +++ b/test/model_test.jl @@ -11,15 +11,19 @@ using UnitCommitment, LinearAlgebra, Cbc, JuMP line.normal_flow_limit[t] = 10.0 end optimizer = optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0) - model = build_model(instance=instance, - optimizer=optimizer, - variable_names=true) + model = build_model( + instance=instance, + optimizer=optimizer, + variable_names=true, + ) - JuMP.write_to_file(model.mip, "test.mps") + @test name(model[:is_on]["g1", 1]) == "is_on[g1,1]" + + JuMP.write_to_file(model, "test.mps") # Optimize and retrieve solution UnitCommitment.optimize!(model) - solution = get_solution(model) + solution = UnitCommitment.solution(model) # Verify solution @test UnitCommitment.validate(instance, solution)