Skip to content

Commit

Permalink
merge master
Browse files Browse the repository at this point in the history
  • Loading branch information
Oskar Taubert committed Oct 25, 2023
2 parents 2bf6e39 + 0729d6c commit 3f0348e
Show file tree
Hide file tree
Showing 14 changed files with 317 additions and 17 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 -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
- name: Coverage Badge
uses: tj-actions/coverage-badge-py@v2

- 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 }}
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
4 changes: 2 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ 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
Expand Down Expand Up @@ -103,7 +102,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
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
5 changes: 3 additions & 2 deletions tutorials/islands_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
import argparse
import logging
import random

import numpy as np
from mpi4py import MPI

from propulate import Islands
from propulate.propagators import SelectMin, SelectMax
from propulate.utils import get_default_propagator, set_logger_config
from function_benchmark import *

from function_benchmark import get_function_search_space

if __name__ == "__main__":
comm = MPI.COMM_WORLD
Expand Down
2 changes: 1 addition & 1 deletion tutorials/propulator_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from propulate import Propulator
from propulate.utils import get_default_propagator, set_logger_config
from function_benchmark import *
from function_benchmark import get_function_search_space

if __name__ == "__main__":
comm = MPI.COMM_WORLD
Expand Down

0 comments on commit 3f0348e

Please sign in to comment.