Skip to main content

PyPI package containing opposition learning operators and population initializers for evolutionary algorithms

Project description

Opposition learning operators and population initializers

PyPI version Downloads Downloads Downloads

Join the chat at https://gitter.im/opp-op-pop-init/community

Documentation: https://pasaopasen.github.io/opp-op-pop-init/

OPPosition learning OPerators and POPulation INITializers (from DPEA) is the python package containing opposition learning operators and population initializers for evolutionary algorithms.

Installation

pip install OppOpPopInit

or

pip3 install OppOpPopInit

About opposition operators

In several evolutionary algorithms it can be useful to create the opposite of some part of current population to explore searching space better. Usually it uses at the begging of searching process (with first population initialization) and every few generations with decreasing probability F. Also it's better to create oppositions of worse objects from populations. See this article for more information.

This package provides several operators for creating oppositions (opposition operators) and methods for creating start population using different distribution functions and opposition operators for each dimension!

Imports

What can u import from this package:

from OppOpPopInit import OppositionOperators # available opposition operators as static class
from OppOpPopInit import SampleInitializers  # available population initializers as static class

# main function which creates random population
# using initializers and oppositors
from OppOpPopInit import init_population 

Also there is a little module for plotting pictures like u can see below

import OppOpPopInit.plotting

Interface agreements

Borders

In the entire part of math optimization tasks the best skin of possible solutions is using 1D-vectors (x1, x2, ..., xn) of variables where each variables x can be from some area [xmin, xmax]. geneticalgorithm2 package and this package are both geared towards this case.

So, many functions here takes arguments minimums and maximums which mean the lower and the upper bounds (borders) of available areas by each using dimension. minimums and maximums should be sequences of integer or real numbers or only one number, but they cannot be numbers both and they must have equal length if they are sequence both.

Format of creators and oppositors

Creators are functions which create random samples (depended on bounds). In code a creator can be any object who can be called like function with signature () -> np.ndarray (Callable[[], np.ndarray]).

Oppositors are functions which take np.ndarray samples and return it's opposed form as np.ndarray. So in code an oppositor if the object can be called like (np.ndarray) -> np.ndarray (Callable[[np.ndarray], np.ndarray]).

Available opposition operators

Checklist

*OppositionOperators.Continual.abs

*OppositionOperators.Continual.modular

*OppositionOperators.Continual.quasi

*OppositionOperators.Continual.quasi_reflect

*OppositionOperators.Continual.over

*OppositionOperators.Continual.Partial -- for using several opposition operators for each subset of searching area.

*OppositionOperators.Discrete.integers_by_order -- it's like abs operator but for integer values

*OppositionOperators.CombinedOppositor -- for using existing opposition operators for each dimension with continual or mixed task. See examplebelow

U can create your own oppositor using pattern:

def oppositor(sample: np.ndarray) -> np.ndarray:
  # some code
  return new_sample

There are also OppositionOperators.Discrete._index_by_order and OppositionOperators.Discrete.value_by_order constructors for very special discrete tasks with available sets of valid values (like [-1, 0, 1, 5, 15]), but it's highly recommended to convert this task to indexes array task (and use OppositionOperators.Discrete.integers_by_order) like below:

# available values
vals = np.array([1, 90. -45, 3, 0.7, 3.4, 12])

valid_array_example = np.array([1, 1, 1, 3, -45])

# function
def optimized_func(arr: np.ndarray) -> float:
    #some code
    return result

# recommented way for optimization algorithm
indexes = np.arange(vals.size)

def new_optimized_functio(new_arr):
    arr = np.array([vals[i] for i in new_arr])
    return optimized_func(arr)

# and forth u are using indexes format for your population

print(
  new_optimized_functio(
    np.array([0, 0, 1, 4])
  )
)

Examples

abs oppositor

Code

modular oppositor

Code

quasi oppositor

Code

quasi_reflect oppositor

Code

over oppositor

Code

integers_by_order oppositor

Code

More examples

Code

Partial/Combined oppositor

If u want to use some oppositor to one dimenstion subset (e. g. indexes 0, 1, 3) and other oppositors for other subsets (e. g. indexes 2, 4, 5) -- u need to create Partial or Combined oppositors. The difference between them is that u need existing oppositors to make combined oppositor with them and u need oppositor makers to make partial oppositor. So, Partial oppositor is often easier to use but Combined is more flexible.

To create Combined oppositor use code like:

oppositor = OppositionOperators.CombinedOppositor(
  [
    (sequece of indexes to apply, oppositor_for_this_dimentions),
    (sequece of indexes to apply, oppositor_for_this_dimentions),
    ...
    (sequece of indexes to apply, oppositor_for_this_dimentions)
  ]
)

To create Partial oppositor use code:

oppositor = OppositionOperators.PartialOppositor(
    minimums=minimumns,
    maximums=maximums,
    indexes_to_opp_creator=[
        (sequece of indexes to apply, oppositor_creator),
        (sequece of indexes to apply, oppositor_creator)
    ]
)

Example:

import numpy as np
from OppOpPopInit import OppositionOperators

# 5 dim population

min_bound = np.array([-8, -3, -5.7, 0, 0])
max_bound = np.array([5, 4, 4, 9, 9])

# population points
points = np.array([
  [1, 2, 3, 4, 7.5],
  [1.6, -2, 3.9, 0.4, 5],
  [1.1, 3.2, -3, 4, 5],
  [4.1, 2, 3, -4, 0.5]
])

# saved indexes for oppositors
first_op_indexes = np.array([0, 2])
second_op_indexes = np.array([1, 3])

oppositor = OppositionOperators.CombinedOppositor(
  [
    (first_op_indexes, OppositionOperators.Continual.abs(
      minimums=min_bound[first_op_indexes],
      maximums=max_bound[first_op_indexes],
    )),
    (second_op_indexes, OppositionOperators.Continual.over(
      minimums=min_bound[second_op_indexes],
      maximums=max_bound[second_op_indexes],
    ))
  ]
)

# or 

oppositor = OppositionOperators.PartialOppositor(
    minimums=min_bound,
    maximums=max_bound,
    indexes_to_opp_creator=[
        (first_op_indexes, OppositionOperators.Continual.abs),
        (second_op_indexes, OppositionOperators.Continual.over)
    ]
)

# as u see, it's not necessary to oppose population by all dimensions, here we won't oppose by last dimension

oppositions = OppositionOperators.Reflect(points, oppositor)

print(oppositions)

# array([[-4.        ,  1.84589799, -4.7       ,  5.04795851,  7.5       ],
#       [-4.6       , -0.74399971, -5.6       ,  7.49178902,  5.        ],
#       [-4.1       ,  0.54619162,  1.3       ,  6.14214043,  5.        ],
#       [-7.1       , -2.59648698, -4.7       ,  0.95770904,  0.5       ]])

Another example code

RandomPartialOppositor

One of the most amazing feature of this package is RandomPartialOppositor. It lets u apply several oppositors to random subsets of dimension area and change these subsets after some counts after applying. It means that u can apply only one this oppositor to several samples and get result like u applyed several partial oppositors to parts of this samples.

Create RandomPartialOppositor oppositor using this structure:

oppositor = OppositionOperators.RandomPartialOppositor(
    [
        (count_of_random_dimensions, repeate_config_during_steps, avalable_indexes, oppositor_creator),
        (count_of_random_dimensions, repeate_config_during_steps, avalable_indexes, oppositor_creator),
        ...
        (count_of_random_dimensions, repeate_config_during_steps, avalable_indexes, oppositor_creator)
    ],
    minimums,
    maximums
)

See simplest example of using

Reflect method

Use OppositionOperators.Reflect(samples, oppositor) for oppose samples array using some oppositor. samples argument here is 2D-array with size samples*dimension.

Reflection with selection best

There is OppositionOperators.ReflectWithSelectionBest(population_samples, oppositor, eval_func, samples_scores = None, more_is_better = False) method for reflect population (with size N) and select best N objects from existing 2N objects. It has parameters:

  • population_samples : 2D numpy array; reflected population.
  • oppositor : function; applying oppositor.
  • eval_func : function; optimized function of population/task.
  • samples_scores : None/1D numpy array, optional; scores for reflected population (if calculated -- it's not necessary to calculate it again). The default is None.
  • more_is_better : logical, optional; The goal -- is maximize the function. The default is False.

See example

Population initializers

Simple random populations

Like oppositors operators there are some constructors for creating creators of start population:

  • SampleInitializers.RandomInteger(minimums, maximums) -- returns function which will return random integer vectors between minimums and maximums
  • SampleInitializers.Uniform(minimums, maximums) -- returns function which will return random vectors between minimums and maximums from uniform distribution
  • SampleInitializers.Normal(minimums, maximums, sd = None) -- returns function which will return random vectors between minimums and maximums from normal distribution

U can create your initializer function:

def func() -> np.ndarray:
    # code
    return valid_sample_array 

There is also SampleInitializers.Combined(minimums, maximums, indexes, creator_initializers) for generate population with different constructors for each dimension subset!

Use creator for initialize population with k objects using SampleInitializers.CreateSamples(creator, k).

RandomInteger

Code

Uniform

Code

Normal

Code

Mixed

Code

Populations with oppositions

Use init_population(total_count, creator, oppositors = None) to create population of size total_count where some objects are constructed by creator and other objects are constructed by applying each oppositor from oppositors to start objects.

Code

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

OppOpPopInit-2.0.1.tar.gz (14.0 kB view details)

Uploaded Source

Built Distribution

OppOpPopInit-2.0.1-py3-none-any.whl (15.8 kB view details)

Uploaded Python 3

File details

Details for the file OppOpPopInit-2.0.1.tar.gz.

File metadata

  • Download URL: OppOpPopInit-2.0.1.tar.gz
  • Upload date:
  • Size: 14.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.8.10

File hashes

Hashes for OppOpPopInit-2.0.1.tar.gz
Algorithm Hash digest
SHA256 6068451b606fc918011a5882bbbee17d2979c9f8951e61f1dddfada78b9e8d53
MD5 f63ad5fe55b83546b1c4f2bf28c04763
BLAKE2b-256 593e59fa1a994f1ec6fe85539293e8dcd363cefb4ee04d7ae2d35591cb437e5a

See more details on using hashes here.

Provenance

File details

Details for the file OppOpPopInit-2.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for OppOpPopInit-2.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 874f29683c7090e52218b9fee6951835f90434884b596e7c6f9eebea5756f238
MD5 1a72a7a8e10bcf72c2241dd477476bbd
BLAKE2b-256 96d7f63b820b788761adb8aab4d369d39dcfc2bce768b7f5a074ec49f0fa9543

See more details on using hashes here.

Provenance

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page