Skip to content

Commit

Permalink
move function to run() method
Browse files Browse the repository at this point in the history
  • Loading branch information
PasaOpasen committed Apr 14, 2024
1 parent ed36786 commit 3c82731
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 37 deletions.
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ https://pasaopasen.github.io/geneticalgorithm2/
- [Updates information](#updates-information)
- [**Future**](#future)
- [**TODO firstly**](#todo-firstly)
- [6.9.1 refactor](#691-refactor)
- [6.9.0 reborn](#690-reborn)
- [6.8.7 minor update](#687-minor-update)
- [6.8.6 minor update](#686-minor-update)
Expand Down Expand Up @@ -133,12 +134,12 @@ Features of this package:

# Installation

Install this package with standard dependencies to use the entire functional.
Install this package with standard light dependencies to use the base functional.
```
pip install geneticalgorithm2
```

Install this package with full dependencies to use all provided functional.
Install this package with full dependencies to use all provided functional including plotting and built-in parallelism tools.

```
pip install geneticalgorithm2[full]
Expand All @@ -149,13 +150,16 @@ pip install geneticalgorithm2[full]
## **Future**

- duplicates removing and revolutions will be moved to `MiddleCallbacks` and removed as alone `run()` parameters
- `function_timeout` and `function` will be moved to `run()` method
- new stop criteria callbacks (min std, max functions evaluations)
- `vartype` will support strings like `iiiiibbf`

## **TODO firstly**
- Remove old style mensions from README
- Remove old style mentions from README

## 6.9.1 refactor

- Finally move `function_timeout` and `function` to `run()` method and deprecate its usage in init()
- `function` is not mandatory to be non-empty

## 6.9.0 reborn

Expand Down
85 changes: 62 additions & 23 deletions geneticalgorithm2/geneticalgorithm2.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ def needs_mutation(self) -> bool:

def __init__(
self,
function: FunctionToMinimize,
function: FunctionToMinimize = None,

dimension: int,
dimension: int = 0,
variable_type: Union[VARIABLE_TYPE, Sequence[VARIABLE_TYPE]] = 'bool',
variable_boundaries: Optional[Union[array2D, Sequence[Tuple[float, float]]]] = None,

Expand All @@ -89,8 +89,8 @@ def __init__(
initializes the GA object and performs main checks
Args:
function: the given objective function to be minimized
dimension: the number of decision variables, the population samples dimention
function: the given objective function to be minimized -- deprecated and moved to run() method
dimension: the number of decision variables, the population samples dimension
variable_type: string means the variable type for all variables,
for mixed types use sequence of strings of type for each variable
Expand All @@ -108,7 +108,7 @@ def __init__(
function_timeout: if the given function does not provide
output before function_timeout (unit is seconds) the algorithm raises error.
For example, when there is an infinite loop in the given function.
`None` means disabling
`None` means disabling -- deprecated and moved to run()
algorithm_parameters: AlgorithmParams object or usual dictionary with algorithm parameter;
it is not mandatory to provide all possible parameters
Expand All @@ -118,9 +118,6 @@ def __init__(
For maximization u can multiply the function by -1 (for instance): the absolute
value of the output would be the actual objective function
- If u want to use set_function only and maybe u dont have usual function,
just set the function to something like lambda x: 0 but set function_timeout=None too
for more details and examples of implementation please visit:
https://github.com/PasaOpasen/geneticalgorithm2
Expand All @@ -137,8 +134,10 @@ def __init__(
self.dup_oppositor = None
self.creator = None
self.init_oppositors = None

self.f: Callable[[array1D], float] = None
self.funtimeout: float = None

self.set_function: Callable[[np.ndarray], np.ndarray] = None

# self.dim: int = None
Expand Down Expand Up @@ -191,20 +190,18 @@ def __init__(

#############################################################
# input function
assert (callable(function)), "function must be callable!"
self.f = function

if function_timeout is not None and function_timeout > 0:
try:
from func_timeout import func_timeout, FunctionTimedOut
except ModuleNotFoundError:
raise ModuleNotFoundError(
"function_timeout > 0 needs additional package func_timeout\n"
"run `python -m pip install func_timeout`\n"
"or disable this parameter: function_timeout=None"
)

self.funtimeout = None if function_timeout is None else float(function_timeout)
if function:
warnings.warn(
f"function is deprecated in init constructor and will be removed in version 7. "
f"Move this argument to run() method"
)
self._check_function(function)
if function_timeout:
warnings.warn(
f"function_timeout is deprecated in init constructor and will be removed in version 7. "
f"Move this argument to run() method"
)
self._check_function_timeout(function_timeout)

#############################################################

Expand Down Expand Up @@ -325,6 +322,24 @@ def _set_max_iterations(self):
else:
self.max_stagnations = math.ceil(max_it)

def _check_function(self, function: Callable[[array1D], float]):
assert callable(function), "function must be callable!"
self.f = function

def _check_function_timeout(self, function_timeout: Optional[float]):

if function_timeout is not None and function_timeout > 0:
try:
from func_timeout import func_timeout, FunctionTimedOut
except ModuleNotFoundError:
raise ModuleNotFoundError(
"function_timeout > 0 needs additional package func_timeout\n"
"run `python -m pip install func_timeout`\n"
"or disable this parameter: function_timeout=None"
)

self.funtimeout = None if function_timeout is None else float(function_timeout)

#endregion

#region REPORT
Expand Down Expand Up @@ -432,6 +447,9 @@ def run(
# deprecated
disable_progress_bar: bool = False,

function: FunctionToMinimize = None,
function_timeout: Optional[float] = None,

set_function: SetFunctionToMinimize = None,
apply_function_to_parents: bool = False,
start_generation: GenerationConvertible = Generation(),
Expand Down Expand Up @@ -471,7 +489,15 @@ def run(
disable_progress_bar: deprecated
set_function: set function to be used instead of usual function
function: the given objective function (sample -> its score) to be minimized;
function_timeout: if the given function does not provide
output before function_timeout (unit is seconds) the algorithm raises error.
For example, when there is an infinite loop in the given function.
`None` means disabling
set_function: set function (all samples -> score per sample) to be used instead of usual function
(usually for optimization purposes)
apply_function_to_parents: whether to apply function to parents from previous generation (if it's needed)
Expand Down Expand Up @@ -510,6 +536,9 @@ def run(
{'population': 2D-array, 'scores': 1D-array}, None if doesn't need to save in file
seed: random seed (None if doesn't matter)
Notes:
if `function_timeout` is enabled then `function` must be set
"""

if disable_progress_bar:
Expand Down Expand Up @@ -664,6 +693,16 @@ def total_middle_callback():
else (lambda: int(time.time() - start_time) >= time_limit_secs)
)

# combine with deprecated parts
function = function or self.f
function_timeout = function_timeout or self.funtimeout

assert function or set_function, 'no function to minimize'
if function:
self._check_function(function)
if function_timeout:
self._check_function_timeout(function_timeout)

self.set_function = set_function or GeneticAlgorithm2.default_set_function(self.f)

#region Initial population, duplicates filter, revolutionary
Expand Down
22 changes: 12 additions & 10 deletions tests/min of sum int.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,18 @@ def f(X):

# check discrete mutation

varbound = [[0,10]]*300

model = ga(function=f, dimension=300, variable_type='int',
variable_boundaries=varbound,
algorithm_parameters={
'mutation_discrete_type': 'uniform_discrete',
'max_num_iteration': 1000
})

model.run(stop_when_reached=0)
varbound = [[0, 10]] * 300

model = ga(
dimension=300, variable_type='int',
variable_boundaries=varbound,
algorithm_parameters={
'mutation_discrete_type': 'uniform_discrete',
'max_num_iteration': 1000
}
)

model.run(stop_when_reached=0, function=f,)


model = ga(function=f, dimension=300, variable_type='int',
Expand Down

0 comments on commit 3c82731

Please sign in to comment.