Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
mcw92 committed Feb 6, 2024
2 parents 39e54e0 + 6fe4267 commit 7a6a707
Show file tree
Hide file tree
Showing 16 changed files with 319 additions and 18 deletions.
55 changes: 55 additions & 0 deletions .github/workflows/python-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Python test

on: [push]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up MPI
uses: mpi4py/setup-mpi@v1
with:
mpi: 'openmpi'
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install ruff pytest pytest-cov
pip install coverage-badge
pip install -r requirements.txt
pip install .
- name: Lint with ruff
run: |
# stop the build if there are Python syntax errors or undefined names
ruff --output-format=github --select=E9,F63,F7,F82 --target-version=py39 .
# default set of ruff rules with GitHub Annotations
ruff --output-format=github --target-version=py39 .
- name: Test with pytest
run: |
pytest --cov=propulate
coverage-badge -fo coverage.svg
- name: Verify Changed files
uses: tj-actions/verify-changed-files@v16
id: verify-changed-files
with:
files: coverage.svg

- name: Commit files
if: steps.verify-changed-files.outputs.files_changed == 'true'
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add coverage.svg
git commit -m "Updated coverage.svg"
- name: Push changes
if: steps.verify-changed-files.outputs.files_changed == 'true'
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.github_token }}
branch: ${{ github.ref }}
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7785/badge)](https://www.bestpractices.dev/projects/7785)
[![](https://img.shields.io/badge/Contact-marie.weiel%40kit.edu-orange)](mailto:[email protected])
[![Documentation Status](https://readthedocs.org/projects/propulate/badge/?version=latest)](https://propulate.readthedocs.io/en/latest/?badge=latest)
![](./coverage.svg)

# **Click [here](https://www.scc.kit.edu/en/aboutus/16956.php) to watch our 3 min introduction video!**

Expand Down
21 changes: 21 additions & 0 deletions coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 1 addition & 2 deletions propulate/propagators/cmaes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import copy
import random
from typing import List, Dict, Union, Tuple
from typing import List, Dict, Tuple

import numpy as np

Expand Down
4 changes: 2 additions & 2 deletions propulate/propagators/pso.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ def _prepare_data(
else:
particles.append(make_particle(individual))
logging.warning(
f"Got Individual instead of Particle. If this is on purpose, you can ignore this warning. "
f"Converted the Individual to Particle. Continuing."
"Got Individual instead of Particle. If this is on purpose, you can ignore this warning. "
"Converted the Individual to Particle. Continuing."
)

own_p = [
Expand Down
29 changes: 29 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
[tool.ruff]
select = ["E", "F"]
ignore = ["E501"]

exclude = [
".bzr",
".direnv",
".eggs",
".git",
".git-rewrite",
".hg",
".mypy_cache",
".nox",
".pants.d",
".pytype",
".ruff_cache",
".svn",
".tox",
".venv",
"__pypackages__",
"_build",
"buck-out",
"build",
"dist",
"node_modules",
"venv",
]

line-length = 88
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
cycler==0.11.0
deepdiff>=5.8.0
kiwisolver==1.4.2
matplotlib==3.2.1
mpi4py==3.0.3
numpy
ordered-set==4.1.0
Expand Down
6 changes: 3 additions & 3 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,13 @@ install_requires =
cycler #==0.11.0
deepdiff #==5.8.0
kiwisolver #==1.4.2
matplotlib #==3.2.1
mpi4py #==3.0.3
numpy #==1.22.3
ordered-set #==4.1.0
pyparsing #==3.0.7
python-dateutil #==2.8.2
six #==1.16.0
colorlog
colorlog

# The usage of test_requires is discouraged, see `Dependency Management` docs
# tests_require = pytest; pytest-cov
Expand Down Expand Up @@ -102,7 +101,8 @@ exclude =
dist
.eggs
docs/conf.py
max-line-length = 250
max-line-length = 88
extend-ignore = E203, E501

[semantic_release]
branch = "release"
Expand Down
Empty file added tests/__init__.py
Empty file.
6 changes: 0 additions & 6 deletions tests/dummy_test.py

This file was deleted.

60 changes: 60 additions & 0 deletions tests/test_cmaes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import random
import tempfile
from typing import Dict
from operator import attrgetter

import numpy as np

from propulate import Propulator
from propulate.propagators import CMAPropagator, BasicCMA


def sphere(params: Dict[str, float]) -> float:
"""
Sphere function: continuous, convex, separable, differentiable, unimodal
Input domain: -5.12 <= x, y <= 5.12
Global minimum 0 at (x, y) = (0, 0)
Parameters
----------
params: dict[str, float]
function parameters
Returns
-------
float
function value
"""
return np.sum(np.array(list(params.values())) ** 2)


def test_PSO():
"""
Test single worker using Propulator to optimize sphere using a PSO propagator.
"""
rng = random.Random(42) # Separate random number generator for optimization.
limits = {
"a": (-5.12, 5.12),
"b": (-5.12, 5.12),
}
with tempfile.TemporaryDirectory() as checkpoint_path:
# Set up evolutionary operator.

adapter = BasicCMA()
propagator = CMAPropagator(adapter, limits, rng=rng)

# Set up propulator performing actual optimization.
propulator = Propulator(
loss_fn=sphere,
propagator=propagator,
generations=10,
checkpoint_path=checkpoint_path,
rng=rng,
)

# Run optimization and print summary of results.
propulator.propulate()
propulator.summarize()
best = min(propulator.population, key=attrgetter("loss"))

assert best.loss < 10.0
73 changes: 73 additions & 0 deletions tests/test_propulator_sphere.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import random
import tempfile
from typing import Dict
from operator import attrgetter
import logging

import numpy as np

from propulate import Propulator
from propulate.utils import get_default_propagator, set_logger_config


def sphere(params: Dict[str, float]) -> float:
"""
Sphere function: continuous, convex, separable, differentiable, unimodal
Input domain: -5.12 <= x, y <= 5.12
Global minimum 0 at (x, y) = (0, 0)
Parameters
----------
params: dict[str, float]
function parameters
Returns
-------
float
function value
"""
return np.sum(np.array(list(params.values())) ** 2)


def test_Propulator():
"""
Test single worker using Propulator to optimize sphere.
"""
rng = random.Random(42) # Separate random number generator for optimization.
limits = {
"a": (-5.12, 5.12),
"b": (-5.12, 5.12),
}
with tempfile.TemporaryDirectory() as checkpoint_path:
set_logger_config(
level=logging.INFO,
log_file=checkpoint_path + "/propulate.log",
log_to_stdout=True,
log_rank=False,
colors=True,
)
# Set up evolutionary operator.
propagator = get_default_propagator( # Get default evolutionary operator.
pop_size=4, # Breeding pool size
limits=limits, # Search-space limits
mate_prob=0.7, # Crossover probability
mut_prob=9.0, # Mutation probability
random_prob=0.1, # Random-initialization probability
rng=rng, # Random number generator
)

# Set up propulator performing actual optimization.
propulator = Propulator(
loss_fn=sphere,
propagator=propagator,
generations=10,
checkpoint_path=checkpoint_path,
rng=rng,
)

# Run optimization and print summary of results.
propulator.propulate()
propulator.summarize()
best = min(propulator.population, key=attrgetter("loss"))

assert best.loss < 0.8
69 changes: 69 additions & 0 deletions tests/test_pso.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import random
import tempfile
from typing import Dict
from operator import attrgetter

import numpy as np

from propulate import Propulator
from propulate.propagators import Conditional
from propulate.propagators.pso import BasicPSO, InitUniformPSO


def sphere(params: Dict[str, float]) -> float:
"""
Sphere function: continuous, convex, separable, differentiable, unimodal
Input domain: -5.12 <= x, y <= 5.12
Global minimum 0 at (x, y) = (0, 0)
Parameters
----------
params: dict[str, float]
function parameters
Returns
-------
float
function value
"""
return np.sum(np.array(list(params.values())) ** 2)


def test_PSO():
"""
Test single worker using Propulator to optimize sphere using a PSO propagator.
"""
rng = random.Random(42) # Separate random number generator for optimization.
limits = {
"a": (-5.12, 5.12),
"b": (-5.12, 5.12),
}
with tempfile.TemporaryDirectory() as checkpoint_path:
# Set up evolutionary operator.

pso_propagator = BasicPSO(
0.729,
1.49334,
1.49445,
0, # MPI rank TODO fix when implemented proper MPI parallel tests
limits,
rng,
)
init = InitUniformPSO(limits, rng=rng, rank=0)
propagator = Conditional(1, pso_propagator, init) # TODO MPIify

# Set up propulator performing actual optimization.
propulator = Propulator(
loss_fn=sphere,
propagator=propagator,
generations=10,
checkpoint_path=checkpoint_path,
rng=rng,
)

# Run optimization and print summary of results.
propulator.propulate()
propulator.summarize()
best = min(propulator.population, key=attrgetter("loss"))

assert best.loss < 30.0
2 changes: 1 addition & 1 deletion tutorials/cmaes_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from propulate import Propulator
from propulate.propagators import BasicCMA, ActiveCMA, CMAPropagator
from propulate.utils import set_logger_config
from function_benchmark import *
from function_benchmark import get_function_search_space


if __name__ == "__main__":
Expand Down
Loading

0 comments on commit 7a6a707

Please sign in to comment.