Skip to content

Commit

Permalink
update docs; update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Freakwill committed Dec 14, 2023
1 parent 141e9a4 commit 3785d39
Show file tree
Hide file tree
Showing 49 changed files with 1,714 additions and 889 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2020 William Song
Copyright (c) 2023 William Song

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@

## Why

Why is the package named as “pyrimidine”? Because it begins with “py”.

> — Are you kiding?
>
> — No, I am serious.
> -- Why is the package named as “pyrimidine”?
> -- Because it begins with “py”.
> -- Are you kiding?
> -- No, I am serious.
## Download

Expand Down
Binary file modified docs/build/.doctrees/environment.pickle
Binary file not shown.
Binary file modified docs/build/.doctrees/index.doctree
Binary file not shown.
Binary file modified docs/build/.doctrees/source/API Design.doctree
Binary file not shown.
Binary file modified docs/build/.doctrees/source/Customization.doctree
Binary file not shown.
Binary file modified docs/build/.doctrees/source/Examples.doctree
Binary file not shown.
Binary file modified docs/build/.doctrees/source/Helpers.doctree
Binary file not shown.
Binary file modified docs/build/.doctrees/source/Home.doctree
Binary file not shown.
Binary file modified docs/build/.doctrees/source/Install.doctree
Binary file not shown.
Binary file modified docs/build/.doctrees/source/Misc.doctree
Binary file not shown.
Binary file not shown.
Binary file modified docs/build/.doctrees/source/pyrimidine.doctree
Binary file not shown.
Binary file modified docs/build/.doctrees/source/pyrimidine.learn.doctree
Binary file not shown.
Binary file modified docs/build/.doctrees/source/pyrimidine.local_search.doctree
Binary file not shown.
Binary file added docs/build/_images/game.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/build/_sources/index.rst.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Welcome to pyrimidine's world of genetic algorithm

Home <../source/Home.md>
Install <../source/Install.md>
Release History <../source/Release History.md>
API Design <../source/API Design.md>
Examples <../source/Examples.md>
Customization <../source/Customization.md>
Expand Down
148 changes: 131 additions & 17 deletions docs/build/_sources/source/API Design.md.txt
Original file line number Diff line number Diff line change
@@ -1,56 +1,170 @@
# API Design

## Iterative Models
## Modules

An iterative model is a class implementing iterative algorithms, repeating to call $x'=Tx$.
Short introduction to modules:

Following is the core code of the class.
- `meta`: Metaclasses
- `mixin`: Mixin Classes
- `base`: The base classes, esp. for creating GAs
- `population`: populations to implement classical GAs
- `chromosome`: some type of chromosomes
- `multipopulation`: multi-population GAs
- `individual`: individuals for GA or other EA
- `es/de/ep`: Evolutionary algorithms
- `pso/ba/fa`: Swarm intelligent algorithms
- `deco`: Decorators
- `utils`: Helpers
- `errors`: Exceptions
- `local_search/*`: Local search algorithms
- `learn/*`: Machine learning implemented by GAs

## Metaclasses
The metaclass `System` is defined to simulate abstract algebraic systems, which are instantiated as a set containing a set of elements, as well as operators and functions on them.

`MetaContainer` is the super-metaclass of `System` for creating container classes.

1. `ParamType --> MetaContainer --> System`
2. `ParamType --> MetaArray`

`MetaArray` is a compact version of `MetaContainer`

## Mixin Classes

Metaclasses define what the algorithm is, while mixin classes specify what the algorithm does.

The inheritance of metaclasses:

```python
def evolve(self):
looping:
self.transition()
```
IterativeMixin - - -> CollectiveMixin
| |
| |
v v
FitnessMixin - - -> PopulationMixin
```

### Iterative models/algorithms

Users could override `transition` to implement any other iteration form.
An iterative model is a mixin class implementing iterative algorithms, mainly repeating to call `transition` method.

Following is the core (pseudo-)code of the class.

```python
class IterativeMixin:

def evolve(self):
self.init()
looping by k:
self.transition(k)
```

Users could override `transition` to implement own iteration algorithms.


### Fitness Models
### Fitness models

Fitness Models are Iterative Models with fitness. Iteration in fitness models would be influenced by fitness.
Fitness Models (`FitnessMixin`) are iterative models with fitness. The iteration in such models would be influenced by fitness.

Indiviudal is a fitness model in GA.

## Individuals
### Population models

Population Models (`PopulationMixin`) are collective algorithms with fitness.


## Basic Classes

### Individuals

An individual is defined as a container of chromosomes.

The individual classes are inherited from `BaseIndividual`. For instance, `BinaryIndividual` is a subclass encoded by several binary chromosomes.



See `Examples` section for a simple example of binary individuals --- Knapsack Problem.


## Chromosomes
### Chromosomes

The chromosomes as an array of genes, could be regarded as the unit of genetic operations. The subclass used most frequently is`BinaryChromosome`.

A chromosome is equivalent to an individual with only one chromosome, mathematically.


## Populations
### Populations

The population classes are inherited from `BasePopulation`. `StandardPopulation` is the standard population for GA. It is recommended to use `HOFPopulation` in most cases.

A population is a container of individuals, in original meaning. But It is possible to be a container of chromosomes in the view of algebra.


## Species
### Multi-populations

It is useful for multi-populations GA. It is regarded as a container of populations.


## Environment
It is designed to be the context for evolution of individuals. The aim of the class is not for numerical computing, instead for "the Skeuomorphic Design".
### Environment
It is designed to be the context for evolution of individuals. The aim of the class is not for numerical computing, instead for "the Skeuomorphic Design".

## Methods

### About fitness
Calculating the fintess is the most frequent task in the algorithms.

- `_fitness()`: the basic method to calculate the fitness of the individual. The methods whose names are started with `_` always do the most dirty task.
- `fitness`: decorated by `property`, get the fitness of the individual/population (from the cache first then call - `_fitness` if there is a cache). The fitness of a population is the maximal fitness of the individuals in the population.
- `fitness`: decorated by `property`, get the fitness of the individual (from the cache first then call `_fitness` if there is a cache).
- `best/mean/std_fitness`: the maximum/mean/std of the fitnesses of the individuals in a population.
- `get_all_fitness`: get the all fitnesses

### About elements(individuals in a population or populations in a multi-population/community)

- `best_element`: wrapped by `property`, equiv. to `get_best_element`
- `get_best_element`: get the element with maximal fitness
- `get_best_elements`: get some elements
- `sort/argsort`: sort the elements by fitness
- `solution`: decoding the best element

### Basic operation

- `copy`: copy an object
- `random`: class method to generate an object randomly
- `decode`: decode an individual to the real solution

### Genetic operation
- `clone`: chromosome-level
- `mutate`: chromosome-level
- `cross`: chromosome-level
- `select`: population-level
- `mate`: population-level, cross the elements, invalid in solution-level.
- `migrate`: population-level, crossover of the populations
- `dual`: chromosome-level
- `replicate`: copy then mutate
- `local_search`: population-level

Some operators defined in solution-level, i.e. only valid for individuals/populations (or chromosomes as the individuals), such as `_fitness`, some could be defined under solution-level, i.e. valid for chromosomes in an individual, such as `dual`, `cross`, `mutate`.

### List-like operation
`append, extend, pop, remove` to operate the list of the elements

### Side-effect and pure

Here `side-effect` means the method will change the fitness of the individual or the population. It could be ignored if you do not use the cache (to get the fitness).

### Others

- `set_*`/`get_*`: set/get methods, for instance, `get_all` the attributes of all individuals in a population.
- `set`: set attributes/methods for a class
- `save/load`: serialization/deserialization for populations/individuals

## Arguments/Parameters/Attributions

- `n_*`: number of ..., such as `n_chromosomes` represents the number of the chromosomes in an individual.
- `*_prob`: probability
- `*_rate`: e.g. `learning_rate`

## `params`/`alias`

`params` is a dictionary of parameters for the algorithm, it could be inherited from super class by meta-programming.

`alias` is a dictionary for alias to attributes.
33 changes: 22 additions & 11 deletions docs/build/_sources/source/Customization.md.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ In this section, we present more complicated examples.

## Customization Tricks

Take Partical Swarm Optimization(PSO) as an example for a quick look at the tricks of customization. First of all, define `class ParticleSwarm(PopulationModel):...`, as subclass of `PopulationModel`. `PopulationModel` is a mixin class where you have to define method `transit` to implement the PSO algorithm. Then assign `element_class` to be the type of particles, and set `default_size` as the number of the particles.
Take Partical Swarm Optimization(PSO) as an example for a quick look at the tricks of customization. First of all, define `class ParticleSwarm(PopulationMixin):...`, as subclass of `PopulationMixin`. `PopulationMixin` is a mixin class where you have to define method `transit` to implement the PSO algorithm. Then assign `element_class` to be the type of particles, and set `default_size` as the number of the particles.

Since the package has provide a practical class for PSO, you only need set the attribute `element_class` to be your own particle class in most case. See `example-pso.py` in `examples`.
Since the package has provide a practical class for PSO, you only need set the attribute `element_class` to be your own particle class in most cases. See `example-pso.py` in `examples`.

```python
class _Particle(BaseParticle):
Expand All @@ -23,12 +23,12 @@ In the standard definition, as an individual, a particle has two "chromosomes",


## Simulated Annealing Algorithm
See the following code for SA Algorithm. The standard SA is an iteration of one solution. Hence we inherit it from `FitnessModel` instead of `PopulationModel`
See the following code for SA Algorithm. The standard SA is an iteration of one solution. Hence we inherit it from `FitnessMixin` instead of `PopulationMixin`

```python
#!/usr/bin/env python3

class SimulatedAnnealing(FitnessModel):
class SimulatedAnnealing(FitnessMixin):
"""Class for Simulated Annealing

Attributes:
Expand Down Expand Up @@ -81,10 +81,10 @@ class SimulatedAnnealing(FitnessModel):

## Differential Evolution

The standard DE is a global searching algorithm. The class `DifferentialEvolution` for DE is inherited from `PopulationModel`.
The standard DE is a global searching algorithm. The class `DifferentialEvolution` for DE is inherited from `PopulationMixin`.

```python
class DifferentialEvolution(PopulationModel):
class DifferentialEvolution(PopulationMixin):

params ={
"factor" : 0.25,
Expand Down Expand Up @@ -125,7 +125,6 @@ After running `comparison-de.py`, we get the following fitness curves.
Different from GA, DE or other algorithms based on the population, simulated annealing is based on single individual. It is a sort of local search. Following is the skelton of SA.

```python
# import statsments

class SimulatedAnnealing(PhantomIndividual):
"""Class for Simulated Annealing
Expand All @@ -148,7 +147,6 @@ class SimulatedAnnealing(PhantomIndividual):
# initialize phantom solution
self.phantom = self.copy(fitness=None)


def transit(self, *args, **kwargs):
T = self.initT
for epoch in range(self.n_epochs):
Expand All @@ -160,7 +158,6 @@ class SimulatedAnnealing(PhantomIndividual):
self.backup()
self.initT = T * self.ext_c


def move(self, T):
"""Move phantom

Expand All @@ -175,7 +172,7 @@ class SimulatedAnnealing(PhantomIndividual):
if flag:
self.phantom.chromosomes = cpy.chromosomes
self.phantom.fitness = cpy.fitness
```
```


```python
Expand Down Expand Up @@ -253,4 +250,18 @@ class BaseTabuSearch(BaseIndividual):
raise NotImplementedError
```

## Hacking
### GA with local search
Now we incorporate the local search algorithm into GA. Suppose that `MyIndividual` is a subclass of `SimulatedAnnealing`.

```python
SAPopulation = LocalSearchPopulation[MyIndividual] // 10
pop = SAPopulation.random()
```

The class `LocalSearchPopulation` will do local research in each iteration that is calling the `ezolve` method of `MyIndividual`.

(`ezolve` method is an easy version of `evolve` method)

## Hacking

Will be filled in future.
Loading

0 comments on commit 3785d39

Please sign in to comment.