Skip to content
This repository has been archived by the owner on Apr 13, 2024. It is now read-only.

Commit

Permalink
Merge pull request #53 from PasaOpasen/7v
Browse files Browse the repository at this point in the history
v6.7.6
  • Loading branch information
PasaOpasen authored Apr 17, 2022
2 parents 7893d03 + 2a032e0 commit 918a67c
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 35 deletions.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ version](https://badge.fury.io/py/geneticalgorithm2.svg)](https://pypi.org/proje
- [Installation](#installation)
- [Updates information](#updates-information)
- [**Future**](#future)
- [6.7.6 bug fix](#676-bug-fix)
- [6.7.5 refactor](#675-refactor)
- [6.7.4 bug fix](#674-bug-fix)
- [6.7.3 speed up](#673-speed-up)
Expand Down Expand Up @@ -130,6 +131,12 @@ pip3 install geneticalgorithm2
- `function_timeout` and `function` will be moved to `run()` method
- new stop criteria callbacks (min std, max functions evaluations)

## 6.7.6 bug fix

- fix some bug of `variable_type=='bool'`
- some refactor of progress bar
- add some dependences to `setup.py`

## 6.7.5 refactor

- shorter progress bar (length can be controled by setting `PROGRESS_BAR_LEN` field of `geneticalgorithm2` class)
Expand Down Expand Up @@ -1167,7 +1174,7 @@ There is an amazing way to control optimization process using `MiddleCallbacks`
selection=self.selection,

current_stagnation=counter,
max_stagnation=self.mniwi,
max_stagnation=self.count_stagnation,

parents_portion=self.param.parents_portion,
elit_ratio=self.param.elit_ratio,
Expand Down
47 changes: 23 additions & 24 deletions geneticalgorithm2/geneticalgorithm2.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import sys
import time
import random

import math

import numpy as np
from func_timeout import func_timeout, FunctionTimedOut
Expand All @@ -47,7 +47,7 @@
from .initializer import Population_initializer
from .plotting_tools import plot_pop_scores, plot_several_lines

from .utils import can_be_prob, is_numpy, union_to_matrix
from .utils import can_be_prob, is_numpy, union_to_matrix, fast_max

#endregion

Expand Down Expand Up @@ -236,7 +236,7 @@ def __set_var_boundaries(
variable_type: Union[str, Sequence[str]],
variable_boundaries
):
if variable_type == 'bool':
if isinstance(variable_type, str) and variable_type == 'bool':
self.var_bound = np.array([[0, 1]] * self.dim)
else:

Expand Down Expand Up @@ -272,12 +272,11 @@ def __set_max_iterations(self):
else:
self.iterate = int(self.param['max_num_iteration'])

self.stop_mniwi = False # is stopped cuz of no progress some iterations
max_it = self.param['max_iteration_without_improv']
if max_it is None:
self.mniwi = self.iterate + 1
self.count_stagnation = self.iterate + 1
else:
self.mniwi = int(max_it)
self.count_stagnation = int(max_it)

#endregion

Expand Down Expand Up @@ -489,7 +488,7 @@ def get_data():
selection=self.selection,

current_stagnation=fails,
max_stagnation=self.mniwi,
max_stagnation=self.count_stagnation,

parents_portion=self.param.parents_portion,
elit_ratio=self.param.elit_ratio,
Expand Down Expand Up @@ -524,7 +523,7 @@ def set_data(data: MiddleCallbackData):

fails = data.current_stagnation
reason_to_stop = data.reason_to_stop
self.mniwi = data.max_stagnation
self.count_stagnation = data.max_stagnation

self.set_function = data.set_function

Expand Down Expand Up @@ -758,7 +757,7 @@ def revolution(pop: np.ndarray, scores: np.ndarray, stagnation_count: int) -> Tu
scores = scores[args_to_sort]
self._update_report(scores)

if fails > self.mniwi:
if fails > self.count_stagnation:
reason_to_stop = f"limit of fails: {fails}"
elif t == self.iterate:
reason_to_stop = f'limit of iterations: {t}'
Expand All @@ -771,20 +770,18 @@ def revolution(pop: np.ndarray, scores: np.ndarray, stagnation_count: int) -> Tu
show_progress(t, self.iterate, f"GA is running... STOP! {reason_to_stop}")
break

show_progress(t, self.iterate, f"GA is running...{t} gen from {self.iterate}")


if scores[0] < self.best_function: # if there is progress
fails = 0
self.best_function = scores[0]

show_progress(t,
self.iterate,
f"GA is running...{t} gen from {self.iterate}...best value = {self.best_function}"
)
else:
fails += 1

show_progress(
t,
self.iterate,
f"GA is running...{t} gen from {self.iterate}...best value = {self.best_function}"
)

# Select parents

par = np.empty((self.par_s, self.dim))
Expand All @@ -802,14 +799,16 @@ def revolution(pop: np.ndarray, scores: np.ndarray, stagnation_count: int) -> Tu
par[par_slice] = pop[new_par_inds].copy()
par_scores[par_slice] = scores[new_par_inds].copy()

#
# select parents for crossover
ef_par_list = np.random.random(self.par_s) < self.prob_cross
par_count = ef_par_list.sum()
if par_count < 2:
while par_count < 2: # 2 parents at least
ef_par_list = np.random.random(self.par_s) <= self.prob_cross
par_count = np.sum(ef_par_list)

#
par_count = fast_max(2, math.floor(self.par_s * self.prob_cross)) # at least 2 parents
# select random parents
ef_par_list = np.random.choice(
np.arange(self.par_s),
par_count,
replace=False
)
ef_par = par[ef_par_list].copy()

# New generation
Expand Down
8 changes: 4 additions & 4 deletions geneticalgorithm2/mutations.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import numpy as np


from .utils import min_fast, max_fast
from .utils import fast_min, fast_max


class Mutations:
Expand All @@ -29,7 +29,7 @@ def mutations_discrete_dict():
def uniform_by_x():

def func(x: float, left: float, right: float):
alp = min_fast(x - left, right - x)
alp = fast_min(x - left, right - x)
return random.uniform(x - alp, x + alp)
return func

Expand All @@ -48,7 +48,7 @@ def gauss_by_x(sd: float = 0.3):
"""
def func(x: float, left: float, right: float):
std = sd * (right - left)
return max_fast(left, min_fast(right, np.random.normal(loc = x, scale = std)))
return fast_max(left, fast_min(right, np.random.normal(loc = x, scale = std)))

return func

Expand All @@ -59,7 +59,7 @@ def gauss_by_center(sd: float = 0.3):
"""
def func(x: float, left: float, right: float):
std = sd * (right - left)
return max_fast(left, min_fast(right, np.random.normal(loc = (left+right)*0.5, scale = std)))
return fast_max(left, fast_min(right, np.random.normal(loc =(left + right) * 0.5, scale = std)))

return func

Expand Down
9 changes: 5 additions & 4 deletions geneticalgorithm2/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@
import numpy as np


def min_fast(a, b):
def fast_min(a, b):
'''
1.5 times faster than row min(a, b)
'''
return a if a < b else b
return a if a < b else b

def max_fast(a, b):

def fast_max(a, b):
return a if a > b else b


Expand All @@ -35,7 +36,7 @@ def split_matrix(mat: np.ndarray):
"""
splits wide pop matrix to variables and scores
"""
return mat[:,:-1], mat[:, -1]
return mat[:, :-1], mat[:, -1]


def union_to_matrix(variables_2D: np.ndarray, scores_1D: np.ndarray):
Expand Down
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@

setuptools.setup(
name="geneticalgorithm2",
version="6.7.5",
version="6.7.6",
author="Demetry Pascal",
author_email="qtckpuhdsa@gmail.com",
maintainer='Demetry Pascal',
description="Supported highly optimized and flexible genetic algorithm package for python",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/PasaOpasen/geneticalgorithm2",
license='MIT',
keywords=['solve', 'optimization', 'problem', 'genetic', 'algorithm', 'GA', 'easy', 'fast', 'genetic-algorithm', 'combinatorial', 'mixed', 'evolutionary'],
packages=setuptools.find_packages(),
classifiers=[
Expand All @@ -27,7 +28,7 @@
'numpy',
'matplotlib',
'joblib',
'OppOpPopInit'
'OppOpPopInit>=2.0.0'
]

)
Expand Down

0 comments on commit 918a67c

Please sign in to comment.