8000 Test parallel processing · madprog/GeneticAlgorithmPython@c4b1378 · GitHub
[go: up one dir, main page]

Skip to content

Commit c4b1378

Browse files
committed
Test parallel processing
1 parent 9610738 commit c4b1378

File tree

1 file changed

+60
-129
lines changed

1 file changed

+60
-129
lines changed

tests/test_stop_criteria.py

Lines changed: 60 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,20 @@
66
actual_num_fitness_calls_keep_elitism = 0
77
actual_num_fitness_calls_keep_parents = 0
88

9-
num_generations = 100
9+
num_generations = 50
1010
sol_per_pop = 10
1111
num_parents_mating = 5
1212

13-
def multi_objective_problem(keep_elitism=1,
14-
keep_parents=-1,
15-
fitness_batch_size=None,
16-
stop_criteria=None,
17-
parent_selection_type='sss',
18-
mutation_type="random",
19-
mutation_percent_genes="default",
20-
multi_objective=False):
2113

22-
function_inputs1 = [4,-2,3.5,5,-11,-4.7] # Function 1 inputs.
23-
function_inputs2 = [-2,0.7,-9,1.4,3,5] # Function 2 inputs.
24-
desired_output1 = 50 # Function 1 output.
25-
desired_output2 = 30 # Function 2 output.
14+
function_inputs1 = [4,-2,3.5,5,-11,-4.7] # Function 1 inputs.
15+
function_inputs2 = [-2,0.7,-9,1.4,3,5] # Function 2 inputs.
16+
desired_output1 = 50 # Function 1 output.
17+
desired_output2 = 30 # Function 2 output.
2618

27-
def fitness_func_batch_multi(ga_instance, solution, solution_idx):
19+
#### Define the fitness functions in the top-level of the module so that they are picklable and usable in the process-based parallel processing works.
20+
#### If the functions are defined inside a class/method/function, they are not picklable and this error is raised: AttributeError: Can't pickle local object
21+
#### Process-based parallel processing must have the used functions picklable.
22+
def fitness_func_batch_multi(ga_instance, solution, solution_idx):
2823
f = []
2924
for sol in solution:
3025
output1 = numpy.sum(sol*function_inputs1)
@@ -34,26 +29,37 @@ def fitness_func_batch_multi(ga_instance, solution, solution_idx):
3429
f.append([fitness1, fitness2])
3530
return f
3631

37-
def fitness_func_no_batch_multi(ga_instance, solution, solution_idx):
32+
def fitness_func_no_batch_multi(ga_instance, solution, solution_idx):
3833
output1 = numpy.sum(solution*function_inputs1)
3934
output2 = numpy.sum(solution*function_inputs2)
4035
fitness1 = 1.0 / (numpy.abs(output1 - desired_output1) + 0.000001)
4136
fitness2 = 1.0 / (numpy.abs(output2 - desired_output2) + 0.000001)
4237
return [fitness1, fitness2]
4338

44-
def fitness_func_batch_single(ga_instance, solution, solution_idx):
39+
def fitness_func_batch_single(ga_instance, solution, solution_idx):
4540
f = []
4641
for sol in solution:
4742
output = numpy.sum(solution*function_inputs1)
4843
fitness = 1.0 / (numpy.abs(output - desired_output1) + 0.000001)
4944
f.append(fitness)
5045
return f
5146

52-
def fitness_func_no_batch_single(ga_instance, solution, solution_idx):
47+
def fitness_func_no_batch_single(ga_instance, solution, solution_idx):
5348
output = numpy.sum(solution*function_inputs1)
5449
fitness = 1.0 / (numpy.abs(output - desired_output1) + 0.000001)
5550
return fitness
5651

52+
53+
def multi_objective_problem(keep_elitism=1,
54+
keep_parents=-1,
55+
fitness_batch_size=None,
56+
stop_criteria=None,
57+
parent_selection_type='sss',
58+
mutation_type="random",
59+
mutation_percent_genes="default",
60+
multi_objective=False,
61+
parallel_processing=None):
62+
5763
if fitness_batch_size is None or (type(fitness_batch_size) in pygad.GA.supported_int_types and fitness_batch_size == 1):
5864
if multi_objective == True:
5965
fitness_func = fitness_func_no_batch_multi
@@ -77,139 +83,64 @@ def fitness_func_no_batch_single(ga_instance, solution, solution_idx):
7783
keep_parents=keep_parents,
7884
stop_criteria=stop_criteria,
7985
parent_selection_type=parent_selection_type,
86+
parallel_processing=parallel_processing,
8087
suppress_warnings=True)
8188

8289
ga_optimizer.run()
8390

84-
return ga_optimizer.generations_completed, ga_optimizer.best_solutions_fitness, ga_optimizer.last_generation_fitness, stop_criteria
85-
86-
def test_number_calls_fitness_function_default_keep():
87-
multi_objective_problem()
88-
89-
def test_number_calls_fitness_function_stop_criteria_reach(multi_objective=False,
90-
fitness_batch_size=None,
91-
num=10):
92-
generations_completed, best_solutions_fitness, last_generation_fitness, stop_criteria = multi_objective_problem(multi_objective=multi_objective,
93-
fitness_batch_size=fitness_batch_size,
94-
stop_criteria=f"reach_{num}")
95-
# Verify that the GA stops when meeting the criterion.
96-
criterion = stop_criteria.split('_')
97-
stop_word = criterion[0]
98-
if generations_completed < num_generations:
99-
if stop_word == 'reach':
100-
if len(criterion) > 2:
101-
# multi-objective problem.
102-
for idx, num in enumerate(criterion[1:]):
103-
criterion[idx + 1] = float(num)
104-
else:
105-
criterion[1] = float(criterion[1])
106-
107-
# Single-objective
108-
if type(last_generation_fitness[0]) in pygad.GA.supported_int_float_types:
109-
assert max(last_generation_fitness) >= criterion[1]
110-
# Multi-objective
111-
elif type(last_generation_fitness[0]) in [list, tuple, numpy.ndarray]:
112-
# Validate the value passed to the criterion.
113-
if len(criterion[1:]) == 1:
114-
# There is a single value used across all the objectives.
115-
pass
116-
elif len(criterion[1:]) > 1:
117-
# There are multiple values. The number of values must be equal to the number of objectives.
118-
if len(criterion[1:]) == len(last_generation_fitness[0]):
119-
pass
120-
else:
121-
raise ValueError("Error")
122-
123-
for obj_idx in range(len(last_generation_fitness[0])):
124-
# Use the objective index to return the proper value for the criterion.
125-
if len(criterion[1:]) == len(last_generation_fitness[0]):
126-
reach_fitness_value = criterion[obj_idx + 1]
127-
elif len(criterion[1:]) == 1:
128-
reach_fitness_value = criterion[1]
129-
130-
assert max(last_generation_fitness[:, obj_idx]) >= reach_fitness_value
131-
132-
def test_number_calls_fitness_function_stop_criteria_saturate(multi_objective=False,
133-
fitness_batch_size=None,
134-
num=5):
135-
generations_completed, best_solutions_fitness, last_generation_fitness, stop_criteria = multi_objective_problem(multi_objective=multi_objective,
136-
fitness_batch_size=fitness_batch_size,
137-
stop_criteria=f"saturate_{num}")
138-
# Verify that the GA stops when meeting the criterion.
139-
criterion = stop_criteria.split('_')
140-
stop_word = criterion[0]
141-
number = criterion[1]
142-
if generations_completed < num_generations:
143-
if stop_word == 'saturate':
144-
number = int(number)
145-
if type(last_generation_fitness[0]) in pygad.GA.supported_int_float_types:
146-
assert best_solutions_fitness[generations_completed - number] == best_solutions_fitness[generations_completed - 1]
147-
elif type(last_generation_fitness[0]) in [list, tuple, numpy.ndarray]:
148-
for obj_idx in range(len(best_solutions_fitness[0])):
149-
assert best_solutions_fitness[generations_completed - number][obj_idx] == best_solutions_fitness[generations_completed - 1][obj_idx]
91+
return None
92+
93+
def test_number_calls_fitness_function_parallel_processing(multi_objective=False,
94+
fitness_batch_size=None,
95+
parallel_processing=None):
96+
multi_objective_problem(multi_objective=multi_objective,
97+
fitness_batch_size=fitness_batch_size,
98+
parallel_processing=parallel_processing)
15099

151100
if __name__ == "__main__":
152-
#### Single-objective problem with a single numeric value with stop_criteria.
153-
print()
154-
test_number_calls_fitness_function_default_keep()
101+
#### Thread-based Parallel Processing
155102
print()
156-
test_number_calls_fitness_function_stop_criteria_reach()
103+
test_number_calls_fitness_function_parallel_processing(parallel_processing=['thread', 1])
157104
print()
158-
test_number_calls_fitness_function_stop_criteria_reach(num=2)
105+
test_number_calls_fitness_function_parallel_processing(parallel_processing=['thread', 2])
159106
print()
160-
test_number_calls_fitness_function_stop_criteria_saturate()
107+
test_number_calls_fitness_function_parallel_processing(parallel_processing=['thread', 5])
161108
print()
162-
test_number_calls_fitness_function_stop_criteria_saturate(num=2)
109+
test_number_calls_fitness_function_parallel_processing(fitness_batch_size=4,
110+
parallel_processing=['thread', 5])
163111
print()
164-
test_number_calls_fitness_function_stop_criteria_reach(fitness_batch_size=4)
112+
test_number_calls_fitness_function_parallel_processing(fitness_batch_size=4,
113+
parallel_processing=['thread', 5])
165114
print()
166-
test_number_calls_fitness_function_stop_criteria_reach(fitness_batch_size=4,
167-
num=2)
168115
print()
169-
test_number_calls_fitness_function_stop_criteria_saturate(fitness_batch_size=4)
170-
print()
171-
test_number_calls_fitness_function_stop_criteria_saturate(fitness_batch_size=4,
172-
num=2)
116+
test_number_calls_fitness_function_parallel_processing(multi_objective=True,
117+
fitness_batch_size=4,
118+
parallel_processing=['thread', 5])
173119
print()
120+
test_number_calls_fitness_function_parallel_processing(multi_objective=True,
121+
fitness_batch_size=4,
122+
parallel_processing=['thread', 5])
174123

175-
176-
#### Multi-objective problem with a single numeric value with stop_criteria.
177-
test_number_calls_fitness_function_stop_criteria_reach(multi_objective=True)
124+
#### Process-based Parallel Processing
125+
test_number_calls_fitness_function_parallel_processing(parallel_processing=['process', 1])
178126
print()
179-
test_number_calls_fitness_function_stop_criteria_reach(multi_objective=True,
180-
num=2)
127+
test_number_calls_fitness_function_parallel_processing(parallel_processing=['process', 2])
181128
print()
182-
test_number_calls_fitness_function_stop_criteria_saturate(multi_objective=True)
129+
test_number_calls_fitness_function_parallel_processing(parallel_processing=['process', 5])
183130
print()
184-
test_number_calls_fitness_function_stop_criteria_saturate(multi_objective=True,
185-
num=2)
131+
test_number_calls_fitness_function_parallel_processing(fitness_batch_size=4,
132+
parallel_processing=['thread', 5])
186133
print()
187-
test_number_calls_fitness_function_stop_criteria_reach(multi_objective=True,
188-
fitness_batch_size=4)
134+
test_number_calls_fitness_function_parallel_processing(fitness_batch_size=4,
135+
parallel_processing=['process', 5])
189136
print()
190-
test_number_calls_fitness_function_stop_criteria_reach(multi_objective=True,
191-
fitness_batch_size=4,
192-
num=2)
193-
print()
194-
test_number_calls_fitness_function_stop_criteria_saturate(multi_objective=True,
195-
fitness_batch_size=4)
196137
print()
197-
test_number_calls_fitness_function_stop_criteria_saturate(multi_objective=True,
198-
fitness_batch_size=4,
199-
num=50)
138+
test_number_calls_fitness_function_parallel_processing(multi_objective=True,
139+
fitness_batch_size=4,
140+
parallel_processing=['process', 5])
200141
print()
201-
202-
203-
#### Multi-objective problem with multiple numeric values with stop_criteria.
204-
test_number_calls_fitness_function_stop_criteria_reach(multi_objective=True)
142+
test_number_calls_fitness_function_parallel_processing(multi_objective=True,
143+
fitness_batch_size=4,
144+
parallel_processing=['process', 5])
205145
print()
206-
test_number_calls_fitness_function_stop_criteria_reach(multi_objective=True,
207-
num="2_5")
208-
print()
209-
test_number_calls_fitness_function_stop_criteria_reach(multi_objective=True,
210-
fitness_batch_size=4)
211-
print()
212-
test_number_calls_fitness_function_stop_criteria_reach(multi_objective=True,
213-
fitness_batch_size=4,
214-
num="10_20")
215146

0 commit comments

Comments
 (0)
0