Skip to content

Commit

Permalink
patch: array_parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
squillero committed Sep 18, 2024
1 parent 1c2aff9 commit 5eb2a5f
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 42 deletions.
28 changes: 16 additions & 12 deletions examples/classics/onemax.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

import byron

NUM_BITS = 50
NUM_BITS = 16


@byron.fitness_function
Expand All @@ -26,23 +26,27 @@ def fitness(genotype):
def main():
byron.welcome()

macro = byron.f.macro('{v}', v=byron.f.array_parameter('01', NUM_BITS + 1))
macro = byron.f.macro('{v}', v=byron.f.array_parameter('01', NUM_BITS))
top_frame = byron.f.sequence([macro])

evaluator = byron.evaluator.PythonEvaluator(fitness, strip_phenotypes=True)
# evaluators.append(byron.evaluator.PythonEvaluator(fitness, strip_phenotypes=True, backend='thread_pool'))
# evaluators.append(byron.evaluator.PythonEvaluator(fitness, strip_phenotypes=True, backend='joblib'))
# evaluators.append(byron.evaluator.ScriptEvaluator('./onemax-shell.sh', args=['-f']))
# evaluators.append(byron.evaluator.MakefileEvaluator('genome.dat', required_files=['onemax-shell.sh']))

evaluator = byron.evaluator.PythonEvaluator(fitness, strip_phenotypes=True, backend=None)
byron.logger.info("main: Using %s", evaluator)
population = byron.ea.vanilla_ea(
population = byron.ea.adaptive_ea(
top_frame, evaluator, max_generation=5_000, lambda_=20, mu=30, max_fitness=NUM_BITS
)

print()
macro = byron.f.macro('{v}', v=byron.f.array_parameter(range(2), NUM_BITS))
top_frame = byron.f.sequence([macro])
evaluator = byron.evaluator.PythonEvaluator(fitness, strip_phenotypes=True, backend=None)
byron.logger.info("main: Using %s", evaluator)
population = byron.ea.adaptive_ea(
top_frame, evaluator, max_generation=5_000, lambda_=20, mu=30, max_fitness=NUM_BITS
)

byron.sys.log_operators()
# evaluator = byron.evaluator.PythonEvaluator(fitness, strip_phenotypes=True)
# evaluators.append(byron.evaluator.PythonEvaluator(fitness, strip_phenotypes=True, backend='thread_pool'))
# evaluators.append(byron.evaluator.PythonEvaluator(fitness, strip_phenotypes=True, backend='joblib'))
# evaluators.append(byron.evaluator.ScriptEvaluator('./onemax-shell.sh', args=['-f']))
# evaluators.append(byron.evaluator.MakefileEvaluator('genome.dat', required_files=['onemax-shell.sh']))


if __name__ == "__main__":
Expand Down
29 changes: 15 additions & 14 deletions src/byron/framework/parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ class T(ParameterArrayABC):

def __init__(self):
super().__init__()
self._raw_value = None

def is_correct(self, obj: Any) -> bool:
if len(obj) != length:
Expand All @@ -201,10 +202,12 @@ def run_paranoia_checks(self) -> bool:

def mutate(self, strength: float = 1.0) -> None:
if strength == 1:
new_value = [rrandom.choice(symbols) for _ in range(length)]
self._raw_value = [rrandom.choice(symbols) for _ in range(length)]
else:
new_value = [rrandom.choice(symbols) if rrandom.boolean(strength) else old for old in self._value]
self.value = sep.join(new_value)
self._raw_value = [
rrandom.choice(symbols) if rrandom.boolean(strength) else old for old in self._raw_value
]
self.value = sep.join(self._raw_value)

T._patch_info(name="Array[" + "".join(str(a) for a in symbols) + f"x{length}]")
return T
Expand All @@ -215,14 +218,13 @@ def _array_parameter_range(min_: int, max_: int, length: int, sep: str) -> type[
class T(ParameterArrayABC):
__slots__ = [] # Preventing the automatic creation of __dict__

MIN = min_
MAX = max_
RANGE = (min_, max_)
LENGTH = length
SEP = sep

def __init__(self):
super().__init__()
self.raw_value = None
self._raw_value = None

def is_correct(self, obj: Any) -> bool:
return all(min_ <= int(e) < max_ for e in obj.split(sep))
Expand All @@ -234,14 +236,13 @@ def run_paranoia_checks(self) -> bool:

def mutate(self, strength: float = 1.0) -> None:
if strength == 1:
self.raw_value = [rrandom.random_int(min_, max_) for _ in range(length)]
self._raw_value = [rrandom.random_int(min_, max_) for _ in range(length)]
else:
i = rrandom.random_int(0, length)
self.raw_value[i] = rrandom.random_int(min_, max_)
while rrandom.boolean(strength):
i = rrandom.random_int(0, length)
self.raw_value[i] = rrandom.random_int(min_, max_)
self.value = sep.join(str(_) for _ in self.raw_value)
self._raw_value = [
rrandom.random_int(min_, max_) if rrandom.boolean(strength) else old for old in self._raw_value
]
self.value = sep.join(str(_) for _ in self._raw_value)
self.value = sep.join(str(_) for _ in self._raw_value)

T._patch_info(name=f"Array[range({min_}, {max_})]x{length}]")
return T
Expand All @@ -256,9 +257,9 @@ def array_parameter(
assert check_value_range(int(length), 1)
if isinstance(symbols, range):
assert check_value_range(symbols.stop - symbols.start, min_=1)
return _array_parameter_range(symbols.start, symbols.stop, int(length), sep=sep)
if sep is None:
sep = ' '
return _array_parameter_range(symbols.start, symbols.stop, int(length), sep=sep)
else:
assert check_valid_type(symbols, Collection)
assert check_valid_length(symbols, 1)
Expand Down
20 changes: 4 additions & 16 deletions src/byron/operators/mutations.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

from collections import Counter
from copy import deepcopy
from math import ceil, floor
from math import floor

from networkx import dfs_preorder_nodes

Expand All @@ -39,7 +39,7 @@


@genetic_operator(num_parents=1)
def single_parameter_mutation(parent: Individual, strength=1.0) -> list['Individual']:
def generic_parameter_mutation(parent: Individual, strength=1.0) -> list['Individual']:
"""Mutates a parameter
The function tries at least 100 times to change the parameter by calling `mutate` with the given strength.
Expand All @@ -63,26 +63,14 @@ def single_parameter_mutation(parent: Individual, strength=1.0) -> list['Individ


@genetic_operator(num_parents=1)
def single_element_array_parameter_mutation(parent: Individual, strength=1.0) -> list['Individual']:
scale = 0.05
ext_mutation = 1 / (scale * strength)
def array_parameter_mutation(parent: Individual, strength=1.0) -> list['Individual']:
offspring = parent.clone
candidates = [p for p in offspring.parameters if isinstance(p, ParameterArrayABC)]
if not candidates:
raise ByronOperatorFailure

parameter = rrandom.choice(candidates)
old_value = list(parameter.value)
new_value = list(parameter.value)
for _ in range(ceil(len(parameter.value) // ext_mutation)):
i = rrandom.random_int(0, len(parameter.value))
new_value[i] = rrandom.choice(parameter.DIGITS)

if strength > 0 and parameter.value == old_value:
raise ByronOperatorFailure

parameter.value = ''.join(new_value)

parameter.mutate(strength=strength)
return [offspring]


Expand Down

0 comments on commit 5eb2a5f

Please sign in to comment.