Genetic algorithm to find the minimum of a three-variable function

Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
4
down vote
favorite
I've implemented a simple genetic algorithm for continuous floating point parameter spaces and without recombination. However, the way I'm passing in parameters and acquiring results from multiprocessing feels wrong. Should I be using concurrent.futures?
The code below uses the genetic algorithm to find the minimum of the equation x^2+y^2+z/10 over the parameter space -2 < x < 0, 0 < y < 2 and 10 < z < 11, but I'd like to keep the code easy to modify for various parameter spaces and evaluation functions.
import numpy as np
import multiprocessing
from collections import OrderedDict
import os
import time
def eval_iter(arg_lst, l_lst):
for c_i, args in enumerate(arg_lst):
yield c_i, args, l_lst
def eval_func(c_i, args, l_lst):
assert len(args) == 3
x = args[0]
y = args[1]
z = args[2]
res = x**2 + y**2 + z/10
print(f"Eval x, y, z: res")
l_lst[c_i] = res
if __name__ == '__main__':
generation_num = 10
child_num = 5
space = OrderedDict((
('x', (-2., 0.)),
('y', (0., 2.)),
('z', (10., 11.))
))
params = OrderedDict([(nm, ) for nm in space.keys()])
for nm, v_range in space.items():
params[nm] = np.random.uniform(v_range[0], v_range[1], size=child_num)
arg_list =
for c_n in range(child_num):
arg_list.append([val[c_n] for val in params.values()])
manager = multiprocessing.Manager()
loss_lst = manager.list([np.inf for i in range(child_num)])
for r_n in range(generation_num):
with multiprocessing.Pool(os.cpu_count()) as pool:
pool.starmap(eval_func, eval_iter(arg_list, loss_lst))
fittest_idx = int(np.argmin(loss_lst))
base_args = arg_list[fittest_idx]
print(f"Best base_argsn")
# mutate offspring from fittest individual
params = OrderedDict([(nm, ) for nm in space.keys()])
for s_i, (nm, v_range) in enumerate(space.items()):
std = (v_range[1] - v_range[0]) / 2
noise = np.random.normal(0, std, size=child_num)
new_param = base_args[s_i] + noise
params[nm] = np.clip(new_param, v_range[0], v_range[1])
arg_list =
for c_n in range(child_num):
arg_list.append([val[c_n] for val in params.values()])
loss_lst = manager.list([np.inf for i in range(child_num)])
python python-3.x numpy multiprocessing genetic-algorithm
add a comment |Â
up vote
4
down vote
favorite
I've implemented a simple genetic algorithm for continuous floating point parameter spaces and without recombination. However, the way I'm passing in parameters and acquiring results from multiprocessing feels wrong. Should I be using concurrent.futures?
The code below uses the genetic algorithm to find the minimum of the equation x^2+y^2+z/10 over the parameter space -2 < x < 0, 0 < y < 2 and 10 < z < 11, but I'd like to keep the code easy to modify for various parameter spaces and evaluation functions.
import numpy as np
import multiprocessing
from collections import OrderedDict
import os
import time
def eval_iter(arg_lst, l_lst):
for c_i, args in enumerate(arg_lst):
yield c_i, args, l_lst
def eval_func(c_i, args, l_lst):
assert len(args) == 3
x = args[0]
y = args[1]
z = args[2]
res = x**2 + y**2 + z/10
print(f"Eval x, y, z: res")
l_lst[c_i] = res
if __name__ == '__main__':
generation_num = 10
child_num = 5
space = OrderedDict((
('x', (-2., 0.)),
('y', (0., 2.)),
('z', (10., 11.))
))
params = OrderedDict([(nm, ) for nm in space.keys()])
for nm, v_range in space.items():
params[nm] = np.random.uniform(v_range[0], v_range[1], size=child_num)
arg_list =
for c_n in range(child_num):
arg_list.append([val[c_n] for val in params.values()])
manager = multiprocessing.Manager()
loss_lst = manager.list([np.inf for i in range(child_num)])
for r_n in range(generation_num):
with multiprocessing.Pool(os.cpu_count()) as pool:
pool.starmap(eval_func, eval_iter(arg_list, loss_lst))
fittest_idx = int(np.argmin(loss_lst))
base_args = arg_list[fittest_idx]
print(f"Best base_argsn")
# mutate offspring from fittest individual
params = OrderedDict([(nm, ) for nm in space.keys()])
for s_i, (nm, v_range) in enumerate(space.items()):
std = (v_range[1] - v_range[0]) / 2
noise = np.random.normal(0, std, size=child_num)
new_param = base_args[s_i] + noise
params[nm] = np.clip(new_param, v_range[0], v_range[1])
arg_list =
for c_n in range(child_num):
arg_list.append([val[c_n] for val in params.values()])
loss_lst = manager.list([np.inf for i in range(child_num)])
python python-3.x numpy multiprocessing genetic-algorithm
add a comment |Â
up vote
4
down vote
favorite
up vote
4
down vote
favorite
I've implemented a simple genetic algorithm for continuous floating point parameter spaces and without recombination. However, the way I'm passing in parameters and acquiring results from multiprocessing feels wrong. Should I be using concurrent.futures?
The code below uses the genetic algorithm to find the minimum of the equation x^2+y^2+z/10 over the parameter space -2 < x < 0, 0 < y < 2 and 10 < z < 11, but I'd like to keep the code easy to modify for various parameter spaces and evaluation functions.
import numpy as np
import multiprocessing
from collections import OrderedDict
import os
import time
def eval_iter(arg_lst, l_lst):
for c_i, args in enumerate(arg_lst):
yield c_i, args, l_lst
def eval_func(c_i, args, l_lst):
assert len(args) == 3
x = args[0]
y = args[1]
z = args[2]
res = x**2 + y**2 + z/10
print(f"Eval x, y, z: res")
l_lst[c_i] = res
if __name__ == '__main__':
generation_num = 10
child_num = 5
space = OrderedDict((
('x', (-2., 0.)),
('y', (0., 2.)),
('z', (10., 11.))
))
params = OrderedDict([(nm, ) for nm in space.keys()])
for nm, v_range in space.items():
params[nm] = np.random.uniform(v_range[0], v_range[1], size=child_num)
arg_list =
for c_n in range(child_num):
arg_list.append([val[c_n] for val in params.values()])
manager = multiprocessing.Manager()
loss_lst = manager.list([np.inf for i in range(child_num)])
for r_n in range(generation_num):
with multiprocessing.Pool(os.cpu_count()) as pool:
pool.starmap(eval_func, eval_iter(arg_list, loss_lst))
fittest_idx = int(np.argmin(loss_lst))
base_args = arg_list[fittest_idx]
print(f"Best base_argsn")
# mutate offspring from fittest individual
params = OrderedDict([(nm, ) for nm in space.keys()])
for s_i, (nm, v_range) in enumerate(space.items()):
std = (v_range[1] - v_range[0]) / 2
noise = np.random.normal(0, std, size=child_num)
new_param = base_args[s_i] + noise
params[nm] = np.clip(new_param, v_range[0], v_range[1])
arg_list =
for c_n in range(child_num):
arg_list.append([val[c_n] for val in params.values()])
loss_lst = manager.list([np.inf for i in range(child_num)])
python python-3.x numpy multiprocessing genetic-algorithm
I've implemented a simple genetic algorithm for continuous floating point parameter spaces and without recombination. However, the way I'm passing in parameters and acquiring results from multiprocessing feels wrong. Should I be using concurrent.futures?
The code below uses the genetic algorithm to find the minimum of the equation x^2+y^2+z/10 over the parameter space -2 < x < 0, 0 < y < 2 and 10 < z < 11, but I'd like to keep the code easy to modify for various parameter spaces and evaluation functions.
import numpy as np
import multiprocessing
from collections import OrderedDict
import os
import time
def eval_iter(arg_lst, l_lst):
for c_i, args in enumerate(arg_lst):
yield c_i, args, l_lst
def eval_func(c_i, args, l_lst):
assert len(args) == 3
x = args[0]
y = args[1]
z = args[2]
res = x**2 + y**2 + z/10
print(f"Eval x, y, z: res")
l_lst[c_i] = res
if __name__ == '__main__':
generation_num = 10
child_num = 5
space = OrderedDict((
('x', (-2., 0.)),
('y', (0., 2.)),
('z', (10., 11.))
))
params = OrderedDict([(nm, ) for nm in space.keys()])
for nm, v_range in space.items():
params[nm] = np.random.uniform(v_range[0], v_range[1], size=child_num)
arg_list =
for c_n in range(child_num):
arg_list.append([val[c_n] for val in params.values()])
manager = multiprocessing.Manager()
loss_lst = manager.list([np.inf for i in range(child_num)])
for r_n in range(generation_num):
with multiprocessing.Pool(os.cpu_count()) as pool:
pool.starmap(eval_func, eval_iter(arg_list, loss_lst))
fittest_idx = int(np.argmin(loss_lst))
base_args = arg_list[fittest_idx]
print(f"Best base_argsn")
# mutate offspring from fittest individual
params = OrderedDict([(nm, ) for nm in space.keys()])
for s_i, (nm, v_range) in enumerate(space.items()):
std = (v_range[1] - v_range[0]) / 2
noise = np.random.normal(0, std, size=child_num)
new_param = base_args[s_i] + noise
params[nm] = np.clip(new_param, v_range[0], v_range[1])
arg_list =
for c_n in range(child_num):
arg_list.append([val[c_n] for val in params.values()])
loss_lst = manager.list([np.inf for i in range(child_num)])
python python-3.x numpy multiprocessing genetic-algorithm
edited Mar 2 at 21:52
200_success
123k14142399
123k14142399
asked Mar 2 at 21:40
Seanny123
758822
758822
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
3
down vote
accepted
Better organisation
You program in its current state is one huge chunk of snippet with all logic inside it. You should consider splitting it into separate smaller functions. The limits on $ x, y, z $ are preset. Consider putting them as a
GLOBAL_CONSTANT.Ideal import order (according to PEP8) is
- standard library imports
- related third party imports
- local application/library specific imports
os/collectionsetc. are standard library, and should be imported first, followed bynumpy.pythonify your code
x = args[0]
y = args[1]
z = args[2]can be expressed as:
x, y, z = argssimilarly
manager.list([np.inf for i in range(child_num)])can become
manager.list([np.inf] * child_num)
I am not sure about how numpy.argmin works, but I think using None instead of np.inf could be better in the sense that you might extend your program to also find local/global maxima along with minima points.
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
accepted
Better organisation
You program in its current state is one huge chunk of snippet with all logic inside it. You should consider splitting it into separate smaller functions. The limits on $ x, y, z $ are preset. Consider putting them as a
GLOBAL_CONSTANT.Ideal import order (according to PEP8) is
- standard library imports
- related third party imports
- local application/library specific imports
os/collectionsetc. are standard library, and should be imported first, followed bynumpy.pythonify your code
x = args[0]
y = args[1]
z = args[2]can be expressed as:
x, y, z = argssimilarly
manager.list([np.inf for i in range(child_num)])can become
manager.list([np.inf] * child_num)
I am not sure about how numpy.argmin works, but I think using None instead of np.inf could be better in the sense that you might extend your program to also find local/global maxima along with minima points.
add a comment |Â
up vote
3
down vote
accepted
Better organisation
You program in its current state is one huge chunk of snippet with all logic inside it. You should consider splitting it into separate smaller functions. The limits on $ x, y, z $ are preset. Consider putting them as a
GLOBAL_CONSTANT.Ideal import order (according to PEP8) is
- standard library imports
- related third party imports
- local application/library specific imports
os/collectionsetc. are standard library, and should be imported first, followed bynumpy.pythonify your code
x = args[0]
y = args[1]
z = args[2]can be expressed as:
x, y, z = argssimilarly
manager.list([np.inf for i in range(child_num)])can become
manager.list([np.inf] * child_num)
I am not sure about how numpy.argmin works, but I think using None instead of np.inf could be better in the sense that you might extend your program to also find local/global maxima along with minima points.
add a comment |Â
up vote
3
down vote
accepted
up vote
3
down vote
accepted
Better organisation
You program in its current state is one huge chunk of snippet with all logic inside it. You should consider splitting it into separate smaller functions. The limits on $ x, y, z $ are preset. Consider putting them as a
GLOBAL_CONSTANT.Ideal import order (according to PEP8) is
- standard library imports
- related third party imports
- local application/library specific imports
os/collectionsetc. are standard library, and should be imported first, followed bynumpy.pythonify your code
x = args[0]
y = args[1]
z = args[2]can be expressed as:
x, y, z = argssimilarly
manager.list([np.inf for i in range(child_num)])can become
manager.list([np.inf] * child_num)
I am not sure about how numpy.argmin works, but I think using None instead of np.inf could be better in the sense that you might extend your program to also find local/global maxima along with minima points.
Better organisation
You program in its current state is one huge chunk of snippet with all logic inside it. You should consider splitting it into separate smaller functions. The limits on $ x, y, z $ are preset. Consider putting them as a
GLOBAL_CONSTANT.Ideal import order (according to PEP8) is
- standard library imports
- related third party imports
- local application/library specific imports
os/collectionsetc. are standard library, and should be imported first, followed bynumpy.pythonify your code
x = args[0]
y = args[1]
z = args[2]can be expressed as:
x, y, z = argssimilarly
manager.list([np.inf for i in range(child_num)])can become
manager.list([np.inf] * child_num)
I am not sure about how numpy.argmin works, but I think using None instead of np.inf could be better in the sense that you might extend your program to also find local/global maxima along with minima points.
answered Mar 3 at 1:33
hjpotter92
4,97611539
4,97611539
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f188702%2fgenetic-algorithm-to-find-the-minimum-of-a-three-variable-function%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password