Skip to content

Commit

Permalink
(#50) add tests for the optimization methods
Browse files Browse the repository at this point in the history
  • Loading branch information
SevgiAkten committed Aug 13, 2024
1 parent 7f1cdc9 commit 25ef752
Show file tree
Hide file tree
Showing 6 changed files with 703 additions and 15 deletions.
32 changes: 17 additions & 15 deletions src/example/example_mcccga.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

import optimizer
import numpy as np
from individual import GeneType

class ExampleProblem:
class RealProblem:
"""
Example problem class to be minimized.
This class implements a simple binary optimization problem, where the goal is to maximize the number of 1s.
This class implements a simple sum of squares function with a global minimum value of 0,
achieved when all elements of the chromosome are equal to 0.
"""

def __init__(self):
Expand All @@ -19,47 +21,47 @@ def f(self, x):
"""
Compute the objective function value.
This method implements a simple sum of binary values.
This method implements the sum of squares function.
Parameters
----------
x : list or numpy.ndarray
The input chromosome represented as a list or array of binary values (0s and 1s).
The input chromosome represented as a list or array of real values.
Returns
-------
int
float
The computed value of the function given the input x.
"""
return sum(x)
return sum(np.power(xi, 2) for xi in x)

def run_mcccga_example():
"""
Run the Machine-Coded Compact Cellular Genetic Algorithm (mcccga)
using the optimizer module.
The mcccga is configured with a 5x5 grid, 100 generations, and a chromosome size of 10.
The problem being solved is an instance of the ExampleProblem class,
with binary genes, constrained by specified mins and maxs.
The problem being solved is an instance of the RealProblem class,
with real genes, constrained by specified mins and maxs.
Returns
-------
tuple
A tuple containing the best solution chromosome and its corresponding value.
"""
# Create an instance of the problem
problem_instance = ExampleProblem()
problem_instance = RealProblem()

result = optimizer.mcccga(
n_cols=5,
n_rows=5,
n_gen=100,
ch_size=10,
gen_type=GeneType.BINARY,
problem=problem_instance, # Pass the ExampleProblem instance
n_gen=500,
ch_size=5,
gen_type=GeneType.REAL,
problem=problem_instance, # Pass the RealProblem instance
selection=optimizer.TournamentSelection,
mins=[0] * 10, # Minimum values for each gene (binary)
maxs=[1] * 10 # Maximum values for each gene (binary)
mins=[-3.768] * 5,
maxs=[3.768] * 5
)

# Print the results
Expand Down
195 changes: 195 additions & 0 deletions src/tests/test_optimizer_alpha_cga.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
import pytest
from optimizer import alpha_cga, GeneType, TournamentSelection, ByteOnePointCrossover, ByteMutationRandom, OnePointCrossover, BitFlipMutation, PMXCrossover, SwapMutation
import numpy as np
from typing import List

class RealProblem:
"""
Example problem class to be minimized.
This class implements a simple sum of squares function with a global minimum value of 0,
achieved when all elements of the chromosome are equal to 0.
"""

def __init__(self):
pass

def f(self, x):
"""
Compute the objective function value.
This method implements the sum of squares function.
Parameters
----------
x : list or numpy.ndarray
The input chromosome represented as a list or array of real values.
Returns
-------
float
The computed value of the function given the input x.
"""
return sum(np.power(xi, 2) for xi in x)

def test_optimizer_alpha_cga_real():
"""Test alpha_cga on a real-valued sum of squares problem."""
result = alpha_cga(
n_cols=5,
n_rows=5,
n_gen=50,
ch_size=5,
gen_type=GeneType.REAL,
p_crossover=0.9,
p_mutation=0.2,
problem=RealProblem(),
selection=TournamentSelection,
recombination=ByteOnePointCrossover,
mutation=ByteMutationRandom,
mins=[-32.768] * 5,
maxs=[32.768] * 5

)
assert result[1] == 0.0, "The alpha_cga did not find the global minimum."
assert result[0] == [0.0] * 5, "The chromosome does not match the global minimum."

class BinaryProblem:
"""
Example problem class to be maximized for binary chromosomes.
This class implements the OneMax problem where the goal is to maximize the number of 1s in a binary string.
"""

def __init__(self):
pass

def f(self, x):
"""
Compute the objective function value.
This method counts the number of 1s in the binary chromosome.
Parameters
----------
x : list or numpy.ndarray
The input chromosome represented as a list or array of binary values (0s and 1s).
Returns
-------
int
The computed value, which is the count of 1s in the chromosome.
"""
return -sum(x)

def test_optimizer_alpha_cga_binary():
"""Test alpha_cga on a binary OneMax problem."""
result = alpha_cga(
n_cols=5,
n_rows=5,
n_gen=50,
ch_size=10,
gen_type=GeneType.BINARY,
p_crossover=0.9,
p_mutation=0.2,
problem=BinaryProblem(),
selection=TournamentSelection,
recombination=OnePointCrossover,
mutation=BitFlipMutation,
mins=[0] * 10,
maxs=[1] * 10
)
assert result[1] == -10, "The alpha_cga did not maximize the number of 1s."
assert result[0] == [1] * 10, "The chromosome does not match the optimal binary sequence."



class PermutationProblem:
"""
Example problem class to be minimized using a permutation-based approach.
This class implements a simple objective function that measures the sum of absolute differences
between the chromosome and a target permutation.
"""

def __init__(self, target: List[int]):
"""
Initialize the PermutationProblem with a target permutation.
Parameters
----------
target : list of int
The target permutation that the algorithm aims to find.
"""
self.target = target

def f(self, x: List[int]) -> float:
"""
Compute the objective function value.
This method implements the sum of absolute differences function.
Parameters
----------
x : list
The input chromosome represented as a list of integers (permutation).
Returns
-------
float
The computed value of the function given the input x.
"""
return sum(abs(xi - ti) for xi, ti in zip(x, self.target))


def test_optimizer_alpha_cga_permutation(self):
"""
Test alpha_cga on a permutation-based problem where the target is the identity permutation.
"""
target_permutation = [i for i in range(10)]
problem = PermutationProblem(target=target_permutation)

result = alpha_cga(
n_cols=5,
n_rows=5,
n_gen=50,
ch_size=10,
gen_type=GeneType.PERMUTATION,
p_crossover=0.9,
p_mutation=0.2,
problem=problem.f(target_permutation),
selection=TournamentSelection(),
recombination=PMXCrossover(),
mutation=SwapMutation(),
mins=[0] * 10,
maxs=[9] * 10
)

# Assert that the alpha_cga finds the global minimum
print(result[0])
print(result[1])
assert result[1] == 0.0, "The alpha_cga did not find the global minimum."
assert result[0] == target_permutation, "The chromosome does not match the target permutation."


def test_optimizer_alpha_cga_no_variation():
"""Test alpha_cga with no crossover or mutation."""
result = alpha_cga(
n_cols=5,
n_rows=5,
n_gen=50,
ch_size=5,
gen_type=GeneType.REAL,
p_crossover=0.0,
p_mutation=0.0,
problem=RealProblem(),
selection=TournamentSelection,
recombination=ByteOnePointCrossover,
mutation=ByteMutationRandom,
mins=[-32.768] * 5,
maxs=[32.768] * 5
)
assert result[1] != 0.0, "With no crossover or mutation, the solution should not reach the global minimum."


if __name__ == "__main__":
pytest.main()
51 changes: 51 additions & 0 deletions src/tests/test_optimizer_ccga.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import pytest
from optimizer import ccga, GeneType, TournamentSelection, ByteOnePointCrossover, ByteMutationRandom, OnePointCrossover, BitFlipMutation, PMXCrossover, SwapMutation
import numpy as np
from typing import List

class BinaryProblem:
"""
Example problem class to be maximized for binary chromosomes.
This class implements the OneMax problem where the goal is to maximize the number of 1s in a binary string.
"""

def __init__(self):
pass

def f(self, x):
"""
Compute the objective function value.
This method counts the number of 1s in the binary chromosome.
Parameters
----------
x : list or numpy.ndarray
The input chromosome represented as a list or array of binary values (0s and 1s).
Returns
-------
int
The computed value, which is the count of 1s in the chromosome.
"""
return sum(x)

def test_optimizer_ccga_binary():
"""Test ccga on a binary OneMax problem."""
result = ccga(
n_cols=5,
n_rows=5,
n_gen=200,
ch_size=5,
gen_type=GeneType.BINARY,
problem=BinaryProblem(),
selection=TournamentSelection,
mins=[0] * 5,
maxs=[1] * 5
)
assert result[1] == 5, "The ccga did not maximize the number of 1s."
assert result[0] == [1] * 5, "The chromosome does not match the optimal binary sequence."

if __name__ == "__main__":
pytest.main()
Loading

0 comments on commit 25ef752

Please sign in to comment.