Skip to content

Commit

Permalink
Merge pull request #78 from Morridin/master
Browse files Browse the repository at this point in the history
Add support for Particle Swarm Optimisation to Propulate
  • Loading branch information
oskar-taubert authored Oct 11, 2023
2 parents 80cd801 + 82f96fe commit b34dac9
Show file tree
Hide file tree
Showing 17 changed files with 2,703 additions and 1,680 deletions.
11 changes: 3 additions & 8 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*.py[cod]
*.so
*.cfg
!.isort.cfg
!propulate/.isort.cfg
!setup.cfg
*.orig
*.log
Expand Down Expand Up @@ -49,11 +49,6 @@ MANIFEST
# Per-project virtualenvs
.venv*/

*.pkl

*.pickle
MNIST
*cpt.p
*cpt.p.bkp
scripts/*.png

voucher_propulate.txt
*.bkp
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,6 @@ OpenMPI.






6 changes: 6 additions & 0 deletions propulate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,22 @@
del get_distribution, DistributionNotFound

from .islands import Islands
from .population import Individual, Particle
from .propulator import Propulator
from .migrator import Migrator
from .pollinator import Pollinator
from .utils import get_default_propagator, set_logger_config

from . import propagators

__all__ = [
"Islands",
"Individual",
"Particle",
"Propulator",
"Migrator",
"Pollinator",
"get_default_propagator",
"set_logger_config",
"propagators",
]
41 changes: 22 additions & 19 deletions propulate/islands.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import logging
import platform
import random
from pathlib import Path
from typing import Callable, Union, List, Type
import logging

from mpi4py import MPI
import numpy as np
from mpi4py import MPI

from .propagators import Propagator, SelectMin, SelectMax
from .migrator import Migrator
from .pollinator import Pollinator
from .population import Individual

from .propagators import Propagator, SelectMin, SelectMax

log = logging.getLogger(__name__) # Get logger instance.

Expand Down Expand Up @@ -97,22 +97,25 @@ def __init__(
print(
"#################################################\n"
"# PROPULATE: Parallel Propagator of Populations #\n"
"#################################################\n\n"
" ⠀⠀⠀⠈⠉⠛⢷⣦⡀⠀⣀⣠⣤⠤⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n"
"⠀ ⠀⠀⠀⠀⠀⣀⣻⣿⣿⣿⣋⣀⡀⠀⠀⢀⣠⣤⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n"
"⠀ ⠀⠀⣠⠾⠛⠛⢻⣿⣿⣿⠟⠛⠛⠓⠢⠀⠀⠉⢿⣿⣆⣀⣠⣤⣀⣀⠀⠀⠀\n"
"⠀ ⠀⠘⠁⠀⠀⣰⡿⠛⠿⠿⣧⡀⠀⠀⢀⣤⣤⣤⣼⣿⣿⣿⡿⠟⠋⠉⠉⠀⠀\n"
"⠀ ⠀⠀⠀⠀⠠⠋⠀⠀⠀⠀⠘⣷⡀⠀⠀⠀⠀⠹⣿⣿⣿⠟⠻⢶⣄⠀⠀⠀⠀\n"
"⠀⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣧⠀⠀⠀⠀⢠⡿⠁⠀⠀⠀⠀⠈⠀⠀⠀⠀\n"
"⠀⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⡄⠀⠀⢠⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n"
"⠀⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⠀⠀⣾⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n"
"⠀ ⣤⣤⣤⣤⣤⣤⡤⠄⠀⠀⣀⡀⢸⡇⢠⣤⣁⣀⠀⠀⠠⢤⣤⣤⣤⣤⣤⣤⠀\n"
"⠀⠀⠀⠀⠀ ⠀⣀⣤⣶⣾⣿⣿⣷⣤⣤⣾⣿⣿⣿⣿⣷⣶⣤⣀⠀⠀⠀⠀⠀⠀\n"
" ⠀⠀⠀⣠⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⣄⠀⠀⠀\n"
"⠀ ⠀⠼⠿⣿⣿⠿⠛⠉⠉⠉⠙⠛⠿⣿⣿⠿⠛⠛⠛⠛⠿⢿⣿⣿⠿⠿⠇⠀⠀\n"
"⠀ ⢶⣤⣀⣀⣠⣴⠶⠛⠋⠙⠻⣦⣄⣀⣀⣠⣤⣴⠶⠶⣦⣄⣀⣀⣠⣤⣤⡶⠀\n"
" ⠀⠀⠈⠉⠉⠉⠀⠀⠀⠀⠀⠀⠀⠉⠉⠉⠉⠀⠀⠀⠀⠀⠉⠉⠉⠉⠀⠀⠀⠀\n"
"#################################################\n"
)
if "Windows" not in platform.system():
print(
" ⠀⠀⠀⠈⠉⠛⢷⣦⡀⠀⣀⣠⣤⠤⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n"
"⠀ ⠀⠀⠀⠀⠀⣀⣻⣿⣿⣿⣋⣀⡀⠀⠀⢀⣠⣤⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n"
"⠀ ⠀⠀⣠⠾⠛⠛⢻⣿⣿⣿⠟⠛⠛⠓⠢⠀⠀⠉⢿⣿⣆⣀⣠⣤⣀⣀⠀⠀⠀\n"
"⠀ ⠀⠘⠁⠀⠀⣰⡿⠛⠿⠿⣧⡀⠀⠀⢀⣤⣤⣤⣼⣿⣿⣿⡿⠟⠋⠉⠉⠀⠀\n"
"⠀ ⠀⠀⠀⠀⠠⠋⠀⠀⠀⠀⠘⣷⡀⠀⠀⠀⠀⠹⣿⣿⣿⠟⠻⢶⣄⠀⠀⠀⠀\n"
"⠀⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣧⠀⠀⠀⠀⢠⡿⠁⠀⠀⠀⠀⠈⠀⠀⠀⠀\n"
"⠀⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⡄⠀⠀⢠⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n"
"⠀⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⠀⠀⣾⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n"
"⠀ ⣤⣤⣤⣤⣤⣤⡤⠄⠀⠀⣀⡀⢸⡇⢠⣤⣁⣀⠀⠀⠠⢤⣤⣤⣤⣤⣤⣤⠀\n"
"⠀⠀⠀⠀⠀ ⠀⣀⣤⣶⣾⣿⣿⣷⣤⣤⣾⣿⣿⣿⣿⣷⣶⣤⣀⠀⠀⠀⠀⠀⠀\n"
" ⠀⠀⠀⣠⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⣄⠀⠀⠀\n"
"⠀ ⠀⠼⠿⣿⣿⠿⠛⠉⠉⠉⠙⠛⠿⣿⣿⠿⠛⠛⠛⠛⠿⢿⣿⣿⠿⠿⠇⠀⠀\n"
"⠀ ⢶⣤⣀⣀⣠⣴⠶⠛⠋⠙⠻⣦⣄⣀⣀⣠⣤⣴⠶⠶⣦⣄⣀⣀⣠⣤⣤⡶⠀\n"
" ⠀⠀⠈⠉⠉⠉⠀⠀⠀⠀⠀⠀⠀⠉⠉⠉⠉⠀⠀⠀⠀⠀⠉⠉⠉⠉⠀⠀⠀⠀\n"
)

# Homogeneous case with equal island sizes (differences of +-1 possible due to load balancing).
if island_sizes is None:
Expand Down
9 changes: 4 additions & 5 deletions propulate/pollinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,17 @@
import logging
import random
import time
from typing import Callable, Union, Tuple, List, Type
from pathlib import Path
from typing import Callable, Union, Tuple, List, Type

import numpy as np
from mpi4py import MPI

from ._globals import MIGRATION_TAG, SYNCHRONIZATION_TAG
from .propagators import Propagator, SelectMin, SelectMax
from .population import Individual
from .propagators import Propagator, SelectMin, SelectMax
from .propulator import Propulator


log = logging.getLogger(__name__)


Expand Down Expand Up @@ -327,9 +326,9 @@ def _check_for_duplicates(
Returns
-------
list[list[propulate.population.Individual | int]]
list[list[propulate.individual.Individual | int]]
individuals and their occurrences
list[propulate.population.Individual]
list[propulate.individual.Individual]
unique individuals in population
"""
if active:
Expand Down
33 changes: 33 additions & 0 deletions propulate/population.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from decimal import Decimal

import numpy as np


class Individual(dict):
"""
Expand Down Expand Up @@ -133,3 +135,34 @@ def equals(self, other) -> bool:
compare_traits = False
break
return compare_traits and self.loss == other.loss


class Particle(Individual):
"""
Child class of ``Individual`` with additional properties required for PSO, i.e., an array-type velocity field and
a (redundant) array-type position field.
Note that Propulate relies on ``Individual``s being ``dict``s.
When defining new propagators, users of the ``Particle`` class thus need to ensure that a ``Particle``'s position
always matches its dict contents and vice versa.
This class also contains an attribute field called ``global_rank``. It contains the global rank of the propagator
that
created it.
This is for purposes of better (or at all) retrieval in multi swarm case.
"""

def __init__(
self,
position: np.ndarray = None,
velocity: np.ndarray = None,
generation: int = -1,
rank: int = -1,
):
super().__init__(generation=generation, rank=rank)
if position is not None and velocity is not None:
assert position.shape == velocity.shape
self.velocity = velocity
self.position = position
self.global_rank = rank # The global rank of the creating propagator for later retrieval upon update.
Loading

0 comments on commit b34dac9

Please sign in to comment.