Skip to content

Commit

Permalink
Dev branch updates (#61)
Browse files Browse the repository at this point in the history
* Nested dataclasses / param namespaces

* Update core

* Fix _get_sweep_length method

* Update radCAD hook logic

* Update software architecture with SimulationExecution class

* Update software architecture with SimulationExecution class

* Enable initialisation of first timestep from initial state

* Enable initialisation of first timestep from initial state: test

* Fix assert statement

* Fix before_step() method to handle initial state

* Fix get_sweep_lengths() to not traverse dictionaries when parent is a dataclass

* Handle nested dataclass params

* Update core.py (#64)

* Update version and CHANGELOG

* Update core.py

* Updated README

* Update python.yml

* Update python.yml

* Update python.yml

* Update CHANGELOG.md

* Update README

* Update pyproject

* Fix Python3.10 dependency on
  • Loading branch information
BenSchZA authored Dec 27, 2023
1 parent 82dd012 commit 1acfe42
Show file tree
Hide file tree
Showing 22 changed files with 4,169 additions and 2,087 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.7, 3.8, 3.9]
python-version: [3.8, 3.9, '3.10']

steps:
- uses: actions/checkout@v2
Expand All @@ -25,7 +25,7 @@ jobs:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade pip setuptools wheel
python -m pip install poetry
poetry install -E compat
- name: Test with pytest
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.13.0] - 2023-10-26
### Added
- Ability to override the method used for performing deep copies, e.g. using Pickle instead of standard library for better performance
- Ability to use dataclasses instead of dictionaries to configure System Parameters, enabling much better developer experience including typing of System Parameters
- Ability to use nested dataclasses to configure System Parameters to enable creating categories or namespaces of System Parameters for better management of large models, see tests for examples of how this works
- Better typing of all core radCAD code, see `radcad.types`

### Changed
- End of support for Python 3.7, due to dependecies we now only support >= 3.8
- Major refactor of core code to use specification for simulation execution in the form of an abstract base class named `SimulationExecutionSpecification`, enabling much better understanding, customisation, and extension of radCAD core code

## [0.12.0] - 2022-09-05
### Added
- Add typing
Expand Down
89 changes: 87 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Goals:
* [Testing](#testing)
* [Jupyter Notebooks](#jupyter-notebooks)
* [Benchmarking](#benchmarking)
* [Acknowledgements](#acknowledgements)

## Open-source Models Using radCAD

Expand Down Expand Up @@ -125,7 +126,7 @@ result = experiment.run()
* [x] Distributed computing and remote execution in a cluster (AWS, GCP, Kubernetes, ...) using [Ray - Fast and Simple Distributed Computing](https://ray.io/)
* [x] Hooks to easily extend the functionality - e.g. save results to HDF5 file format after completion
* [x] Model classes are iterable, so you can iterate over them step-by-step from one state to the next (useful for gradient descent, live digital twins)
* [x] Parameters can be a dataclass! This enables typing and dot notation for accessing parameters.
* [x] Parameters can be configured using nested dataclasses! This enables typing and dot notation for accessing parameters, and the creation of parameter namespaces.

## Installation

Expand Down Expand Up @@ -157,6 +158,53 @@ result = simulation.run()
df = pd.DataFrame(result)
```

### Model Parameters

A unique feature of radCAD is being able to use nested dataclasses to configure the model's parameters. This enables typing and dot notation for accessing parameters, and the creation of parameter namespaces, demonstrated below.

```python
from dataclasses import dataclass
from radcad.utils import default
from radcad.types import StateVariables, PolicySignal

...

@dataclass
class LiquidityPoolParameters:
initial_liquidity: int = 100_000


@dataclass
class ProtocolParameters:
liquidity_pool: LiquidityPoolParameters = default(LiquidityPoolParameters())
...


@dataclass
class Parameters:
protocol: ProtocolParameters = default(ProtocolParameters())
agents: AgentParameters = default(AgentParameters())
...


models.params = Parameters()

...

def update_liquidity(
params: Parameters,
substep: int,
state_history: List[List[StateVariables]],
previous_state: StateVariables,
policy_input: PolicySignal
) -> Tuple[str, int]:
if not previous_state["liquidity"]:
updated_liquidity = params.protocol.liquidity_pool.initial_liquidity
else:
updated_liquidity = ...
return "liquidity", updated_liquidity
```

### cadCAD Compatibility

#### Migrating from cadCAD to radCAD
Expand Down Expand Up @@ -234,6 +282,7 @@ df = pd.DataFrame(result)
```

#### cadCAD Compatibility Mode

radCAD is already compatible with the cadCAD generalized dynamical systems model structure; existing state update blocks, policies, and state update functions should work as is. But to more easily refactor existing cadCAD models to use radCAD without changing the cadCAD API and configuration process, there is a compatibility mode. The compatibility mode doesn't guarrantee to handle all cadCAD options, but should work for most cadCAD models by translating the configuration and execution processes into radCAD behind the scenes.

To use the compatibility mode, install radCAD with the `compat` dependencies:
Expand Down Expand Up @@ -332,6 +381,27 @@ To improve performance, at the cost of mutability, the `Engine` module has the `
experiment.engine = Engine(deepcopy=False)
```

#### Selecting alternative state `deepcopy` method

The `deepcopy` method used for creating deepcopies of state during the simulation can be customised by creating a custom `SimulationExecution` class. This is useful when trying to optimise simulation performance, where certain types of state are better suited to specific `deepcopy` methods.

```python
class CustomSimulationExecution(SimulationExecution):
def __init_subclass__(cls) -> None:
return super().__init_subclass__()

@staticmethod
def deepcopy_method(obj) -> Any:
"""
Use copy.deepcopy instead of default Pickle dumps/loads for deepcopy operations.
"""
return copy.deepcopy(obj)

experiment.engine.simulation_execution = CustomSimulationExecution
```

This same technique can be used for overriding any of the other simulation methods.

#### Dropping state substeps

If you don't need the substeps in post-processing, you can both improve simulation performance and save post-processing time and dataset size by dropping the substeps:
Expand Down Expand Up @@ -455,11 +525,20 @@ See https://stackoverflow.com/questions/24756712/deepcopy-is-extremely-slow for
Set up and enter the Python environment with [Poetry](https://python-poetry.org/):
```bash
poetry --help
poetry install
poetry env use python3
poetry install
poetry shell
```

### Common issues

```
ERROR:: Could not find a local HDF5 installation.
You may need to explicitly state where your local HDF5 headers and
library can be found by setting the ``HDF5_DIR`` environment
variable or by using the ``--hdf5`` command-line option.
```

### Publishing to PyPI

```bash
Expand Down Expand Up @@ -517,6 +596,12 @@ poetry run python3 -m mprof run benchmarks/benchmark_memory_radcad.py
poetry run python3 -m mprof plot
```

## Acknowledgements

* [@danlessa](https://github.com/danlessa): Thank you for contribution of Predator-Prey example
* [@rogervs](https://github.com/rogervs): Thank you for contribution of Harmonic Oscillator example
* [abzaremba](https://github.com/abzaremba): Thank you for contribution to documentation

## Star History

[![Star History Chart](https://api.star-history.com/svg?repos=CADLabs/radCAD&type=Date)](https://star-history.com/#CADLabs/radCAD&Date)
Loading

0 comments on commit 1acfe42

Please sign in to comment.