Updating
This page collects information about updating the project between specific versions.
Pre-2.13 to 2.13.0
Version 2.13.0 introduced an updated IESopt.jl version, which requires a note on how to upgrade existing environments.
The most important change is a mandatory move to Julia 1.12 and Python 3.14; the latter could be relaxed in the
future if needed, but using >= 3.14 simplifies matching OpenSSL versions between Julia and Python by a lot (many
“versions” of CPython make use of an outdated OpenSSL with some “crucial insecurities”, which breaks using Julia/Python
together).
Follow these steps, but please report any issues you encounter immediately to the dev chat, so that we can fix/document problems that might arise with slightly differing initial setups:
First, make sure your uv is up-to-date, by running:
uv self update
Update the required Python version in your pyproject.toml by setting it to:
requires-python = ">=3.14"
Set a specific Python version in your .python-version file (note: this version prevents pulling an outdated CPython
build as of 17.02.2026; might require a different version in the future), by changing its content to:
3.14.3
Update the iesopt version in your pyproject.toml to (at least) 2.13.0 by running
uv add "iesopt >= 2.13.0"
Caution
If this step fails with an error that mentions pandas>=3.0.0 being required by your project, run
uv add "pandas < 3.0" first, then rerun the above command.
You should now be able to run:
uv run python
>>> import iesopt
If this succeeds (after some time to precompile the new version), then you are good to run any model as you are used to.
Read on: JuliaUp
If you encounter a log message like this:
WARNING: About to install Julia ... to ...
If you use juliapkg in more than one environment, you are likely to
have Julia installed in multiple locations. It is recommended to
install JuliaUp (https://github.com/JuliaLang/juliaup) or Julia
(https://julialang.org/downloads) yourself.
we highly recommend following that advice and installing juliaup. This is nowadays done automatically when you install
Julia from the official homepage julialang.org/:
juliaup is the recommended way to install Julia. It automatically installs the latest stable julia binary and helps keep it up to date. It also supports installing and using different versions of Julia simultaneously.
This most importantly means that if you have juliaup installed, IESopt can reuse this across different projects that
you work on, heavily reducing the setup time since there’s no need to download a full Julia for each project and a lot
of precompilation stuff can be shared.
2.6.3 to 2.6.4 or 2.6.5
When upgrading from a version between 2.0.0 and 2.6.3 to either 2.6.4 or 2.6.5 you may run into an error looking similar to
Exception: 'version' entries have empty intersection:
- '=1.25.0' at <YOUR_PROJECT>/.iesopt/juliapkg.json
- '=1.24.0' at <YOUR_PROJECT>/.venv/lib/site-packages/iesopt/juliapkg.json
where <YOUR_PROJECT> is the path to your project that uses iesopt.
You can fix this manually by deleting the old file at <YOUR_PROJECT>/.venv/lib/site-packages/iesopt/juliapkg.json.
If you upgrade to 2.6.6 or higher you will not run into this issue.
1.x.y to 2.0.0
The 2.0.0 release follows the breaking change of IESopt.jl going to v2.0.0. This was mainly triggered by a proper rework of how addons work, including a new internal handling for more complex expressions (allowing more flexibility in configuring conversion, or cost settings), as well as better support around templates (e.g. the introduction of Virtuals). A few breaking changes that were planned for quite some time are part of this.
Changes to the top-level config
The structure of the config section in the top-level configuration file changed. Overall it’s highly similar, but:
A
generalsection was added that properly groups “general” settings, that were previous keyword arguments.Small adjustments were made to account for that.
The
resultssection changed slightly.
See the respective section(s) in the YAML/Top-level config documentation. The most important changes relate to the following (sub-)sections:
nameversionhigh_performanceconstraint_safetyis now calledsoft_constraintsand part of theoptimizationsection.
Changes to keyword arguments
Previously we allowed passing arbitrary keyword arguments to public functions, like iesopt.Model.generate() or iesopt.run(). This can lead to problems with latency on previously unseen types of arguments, especially now that we support arbitrary dictionaries as model parameters. This now works differently:
There are no arbitrary keyword arguments anymore.
Model parameters have to be passed as dictionary, using
parameters = {foo: 1.0, bar: "austria"}.There is a new and “powerful”
configkeyword argument, explained below.
config
Besides model parameters, specific keyword arguments existed, e.g., verbosity. These are gone and now first-class options in the model’s top-level config (see YAML/Top-level config). With that a way to change them programmatically was in need, which is what the config argument does. Take the following example:
import iesopt
iesopt.run("my_config.iesopt.yaml", config = {
"general.verbosity.core": "error",
"optimization.snapshots.count": 168,
"files.data_in": "scenario17/data.csv",
})
The passed dictionary modifies the top-level configuration during the parsing step. That means you are able to overwrite / set each configuration option programmatically. The access pattern follows the structure of the config section in the top-level configuration file. For example, the verbosity in the YAML looks like:
To modify / set this, general.verbosity.core is used. As you can see that opens the possibility to modify, e.g., files that are loaded based on (for example) which scenario we are in by modifying the files section, using files.data_in. Here data_in is the “name” used in the model later on (using some_col@data_in).
Further, this means you no longer need to use “model parameters” for stuff that is actually part of the config section, e.g., the number of Snapshots in your model. Instead of coming up with a parameter, e.g., my_snapshot_count, using it as count: <my_snapshot_count>, and then passing it as iesopt.run("...", my_snapshot_count = 168), you can now just modify that as shown above by setting it using the accessor optimization.snapshots.count.
parameters
Any dictionary passed to this will be used in the same way as keyword arguments were used before: Parameters given there are replaced in the parameters section (which might be based on an external *.iesopt.param.yaml file).
Changes to result extraction
We saw increasing interest in actively “filtering” results of various models. This triggered the implementation of a new result backend (initially only JLD2) supported by DuckDB. This is (as of 2.0.0) not enabled as default, since it does not fully support the functionality that the Python wrapper iesopt provides. However, we plan on switching to this backend in the future.
Changes to addons
To be written: Link to addon page/docs as soon as they are done.
Changes to examples, and more
Everything that was previously part of IESoptLib.jl is now integrated into IESopt.jl. Functionality around this can be accessed using IESopt.Assets.