Skip to content

Commit

Permalink
Bump version to 1.2.0 (#61)
Browse files Browse the repository at this point in the history
* chore: update version

* docs: small docs improvements

* docs: changelog update

* docs: changelog for 1.2.0

* fix: update custom objective doc name in tests

* docs: changelog fun
  • Loading branch information
ADGEfficiency authored Dec 3, 2023
1 parent 269204f commit 5cf24e2
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 24 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ test: setup-test test-docs
create-test-docs: setup-test clean-test-docs
mkdir -p ./tests/phmdoctest
python -m phmdoctest README.md --outfile tests/phmdoctest/test_readme.py
python -m phmdoctest ./docs/docs/how-to/custom-objective.md --outfile tests/phmdoctest/test_custom_objective.py
python -m phmdoctest ./docs/docs/how-to/custom-objectives.md --outfile tests/phmdoctest/test_custom_objectives.py
python -m phmdoctest ./docs/docs/validation/battery.md --outfile tests/phmdoctest/test_validate_battery.py
python -m phmdoctest ./docs/docs/validation/evs.md --outfile tests/phmdoctest/test_validate_evs.py
python -m phmdoctest ./docs/docs/validation/heat-pump.md --outfile tests/phmdoctest/test_validate_heat-pump.py
Expand Down
97 changes: 96 additions & 1 deletion docs/docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,101 @@
# Changelog

## [1.1.1](https://github.com/ADGEfficiency/energy-py-linear/releases/tag/v1.1.0)
## [1.2.0](https://github.com/ADGEfficiency/energy-py-linear/releases/tag/v1.2.0)

### Custom Objective Functions

A custom objective function allows users to create their own objective functions in the linear program.

This allows users to optimize for a custom set of revenues and costs. The objective function can target assets by type or name, and can include multiplication by interval data and/or a coefficient.

The example below shows how to include a cost for battery use (a cycle cost) applied to the battery discharge:

```python
import numpy as np
import energypylinear as epl

assets = [
epl.Battery(power_mw=20, capacity_mwh=20)
]
site = epl.Site(
assets=assets,
electricity_prices=np.random.normal(0, 1000, 48)
)
terms=[
{
"asset_type":"site",
"variable":"import_power_mwh",
"interval_data":"electricity_prices"
},
{
"asset_type":"site",
"variable":"export_power_mwh",
"interval_data":"electricity_prices",
"coefficient":-1
},
{
"asset_type": "battery",
"variable": "electric_discharge_mwh",
"interval_data": "electricity_prices",
"coefficient": 0.25
}
]
site.optimize(objective={"terms": terms})
```

See [Custom Objectives](https://energypylinear.adgefficiency.com/latest/how-to/custom-objectives/) in the documentation for more examples.

### Logging Improvements

The dependency on `structlog` has been removed - we now only use `rich.logging.Console` to log to STDOUT. The ability to log to a file has been removed.

The `verbose` flag now accepts either a `bool` or an `int`. The mapping of `verbose` to log levels is as follows:

| `verbose` | Log Level |
|-----------|-----------|
| True | INFO |
| False | ERROR |
| 1 | DEBUG |
| 2 | INFO |
| 3 | WARNING |
| 4 | ERROR |

```python
import energypylinear as epl
asset = epl.Battery(electricity_prices=[10, -50, 200, -50, 200])
simulation = asset.optimize(verbose=2)
```

```
INFO assets.site.optimize: cfg=<SiteConfig name=site, freq_mins=60,
import_limit_mw=10000.0, export_limit_mw=10000.0>
INFO assets.site.optimize: cfg=<SiteConfig name=site, freq_mins=60,
import_limit_mw=10000.0, export_limit_mw=10000.0>
INFO assets.site.optimize: assets=['battery', 'spill']
INFO assets.site.optimize: assets=['battery', 'spill']
INFO optimizer.solve: status='Optimal'
INFO optimizer.solve: status='Optimal'
```

### Tighten Optimizer Tolerance

The default relative tolerance of the CBC optimizer has been reduced to `0.0`.

### Optimizer Config can be a Dictionary

It's now possible to use a dictionary in place of the `epl.OptimizerConfig` object:

```python
asset.optimize(optimizer_config={"timeout": 2, "relative_tolerance": 0.1})
```

### Other Changes

We have upgraded Poetry to 1.7.0 and Mypy to 1.7.0.

Plausible analytics added to the documentation.

## [1.1.1](https://github.com/ADGEfficiency/energy-py-linear/releases/tag/v1.1.1)

### Bugs

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
## Custom Objective Functions
`energypylinear` has two different objective functions (price or carbon) built into the library.

`energypylinear` can optimize for two different objective functions (price or carbon) built into the library.
However you may want to optimize for a different objective function in the linear program. You may have a business problem with a different set of revenues and costs than are included by default.

However you may want to optimize for a different objective function in the linear program.

**A custom objective function allows you to construct an objective function as you see fit** - allowing you to optimize a site and assets for the incentives and costs that are important to you.
**A custom objective function allows you to construct an objective function as you see fit** - allowing you to optimize a site and assets for the revenues and costs that are important to you.

Core to the custom objective function is the `epl.Term` - representing a single term in the objective function:

Expand All @@ -21,9 +19,9 @@ class Term:
coefficient: float = 1.0
```

Each term can target either many assets by type or one asset by name. It can also include multiplication by interval data or by a coefficient.
A term can target either many assets by type or one asset by name. It can also include multiplication by interval data or by a coefficient.

A custom objective function is a list of `epl.Term` - the sum of these terms becomes the objective function.
A custom objective function is a list of terms:

<!--phmdoctest-share-names-->
```python
Expand All @@ -32,11 +30,13 @@ class CustomObjectiveFunction:
terms: list[Term]
```

The objective function used in the linear program is the sum of these terms.

### Price and Carbon

In this example we will show how to optimize a battery for an objective optimizes for both profit and carbon at the same time.
This example shows how to optimize a battery for an objective that includes terms for both price and carbon.

The example below creates an objective function where we incentive a site to:
Below we create an objective function where we incentive a site to:

- reduce import when the electricity price or carbon intensity is high,
- increase export when the electricity price or carbon intensity is low.
Expand All @@ -52,9 +52,9 @@ def simulate(
carbon_price: int,
seed: int,
n: int,
verbose: int = 2
verbose: int = 3
) -> epl.SimulationResult:
"""Runs one battery simulation at a given carbon price with a custom objective function."""
"""Run a battery simulation with a custom objective function."""
np.random.seed(seed)
site = epl.Site(
assets=[epl.Battery(power_mw=10, capacity_mwh=20)],
Expand Down Expand Up @@ -100,14 +100,10 @@ print(simulate(carbon_price=50, seed=42, n=72))
```

```
INFO assets.site.optimize: cfg=<SiteConfig name=site, freq_mins=60,
import_limit_mw=10000.0, export_limit_mw=10000.0>
INFO assets.site.optimize: assets=['battery']
INFO optimizer.solve: status='Optimal'
<energypylinear.SimulationResult feasible:True, rows:72, cols:28>
```

We can validate that our custom objective function is working as expected by running simulations across many carbon prices, and see the effect on the profit and emissions of our site:
We can validate that our custom objective function is working as expected by running simulations across many carbon prices:

<!--phmdoctest-share-names-->
```python
Expand Down Expand Up @@ -148,7 +144,7 @@ In the previous example we used a custom objective function to apply incentives

An example of this is a renewable energy certificate scheme, where the generation from one asset receives additional income for each MWh generated.

In the example below, our `solar` asset receives additional income for each MWh generated.
In the example below, our `solar` asset receives additional income for each MWh generated.

The site has a constrained export limit, which limits how much both generators can output. The site electric load increases in each interval, which allows us to see which generator is called first:

Expand Down Expand Up @@ -213,15 +209,15 @@ print(
4 50.0 50.0
```

As expected, the first generator that is called is the `solar` generator, as it receives additional income for it's output.
As expected, the first generator that is called is the `solar` generator, as it receives additional income for it's output.

As the site demand increases, the `wind` generator is called to make up the remaining demand.

### Synthetic PPA

A synthetic PPA is a financial instrument that allows swapping of the output of a wholesale exposed generator to a fixed price.

This can be modelled as a custom objective function.
This can be modelled as a custom objective function.

In the example below, we model a site with wholesale exposed import and export, and swap the output of our `wind` generator from the wholesale to a fixed price:

Expand Down Expand Up @@ -356,7 +352,7 @@ terms=[
]
```

We can validate that this works by applying a stronger cycle cost and seeing the battery use descrease:
We can validate that this works by applying a stronger cycle cost and seeing the battery use decrease:

<!--phmdoctest-share-names-->
```python
Expand Down
2 changes: 1 addition & 1 deletion docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ nav:
- Optimize Multiple Assets: how-to/dispatch-site.md
- Optimize for Carbon: how-to/price-carbon.md
- Optimize for a Forecast: how-to/dispatch-forecast.md
- Use a Custom Objective Function: how-to/custom-objective.md
- Custom Objective Functions: how-to/custom-objectives.md
- Validation:
- Battery: validation/battery.md
# - Combined Heat & Power: validation/chp.md
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "energypylinear"
version = "1.1.1"
version = "1.2.0"
description = "Optimizing energy assets with mixed-integer linear programming."
authors = ["Adam Green <[email protected]>"]
license = "MIT"
Expand Down

0 comments on commit 5cf24e2

Please sign in to comment.