Skip to content

Commit 3b50b66

Browse files
ewu63eirikurjmarcomangano
authored
Fix nsga2 bug (#438)
* fix allocation bugs for 64 bit systems * enable flaky nsga2 test * ensure array access is not out of bounds * run tests in isolation * enforce popsize in increments of 4 * flake8 --------- Co-authored-by: Eirikur Jonsson <[email protected]> Co-authored-by: Marco Mangano <[email protected]>
1 parent 6c877b4 commit 3b50b66

File tree

7 files changed

+17
-7
lines changed

7 files changed

+17
-7
lines changed

.github/test_real.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ cd tests
1111
# we have to copy over the coveragerc file to make sure it's in the
1212
# same directory where codecov is run
1313
cp ../.coveragerc .
14-
testflo --pre_announce --disallow_deprecations -v --coverage --coverpkg pyoptsparse $EXTRA_FLAGS
14+
testflo -i --pre_announce --disallow_deprecations -v --coverage --coverpkg pyoptsparse $EXTRA_FLAGS

.github/workflows/linux-build.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,4 @@ jobs:
3131
- name: Run tests
3232
run: |
3333
cd tests
34-
testflo --pre_announce -v -n 1 .
34+
testflo -i --pre_announce -v -n 1 .

.github/workflows/windows-build.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,4 @@ jobs:
5252
run: |
5353
conda activate pyos-build
5454
cd tests
55-
testflo --pre_announce -v -n 1 .
55+
testflo -i --pre_announce -v -n 1 .

pyoptsparse/pyNSGA2/pyNSGA2.py

+3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ def __init__(self, raiseError=True, options={}):
3434
if isinstance(nsga2, str) and raiseError:
3535
raise ImportError(nsga2)
3636

37+
if self.getOption("PopSize") % 4 != 0:
38+
raise ValueError("Option 'PopSize' must be a multiple of 4")
39+
3740
@staticmethod
3841
def _getInforms():
3942
informs = {}

pyoptsparse/pyNSGA2/source/allocate.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ void allocate_memory_ind (individual *ind, Global global)
3030
if (global.nbin != 0)
3131
{
3232
ind->xbin = (double *)malloc(global.nbin*sizeof(double));
33-
ind->gene = (int **)malloc(global.nbin*sizeof(int));
33+
ind->gene = (int **)malloc(global.nbin*sizeof(int *));
3434
for (j=0; j<global.nbin; j++)
3535
{
3636
ind->gene[j] = (int *)malloc(global.nbits[j]*sizeof(int));

pyoptsparse/pyNSGA2/source/crowddist.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ void assign_crowding_distance_list (population *pop, list *lst, int front_size,
2626
pop->ind[lst->child->index].crowd_dist = INF;
2727
return;
2828
}
29-
obj_array = (int **)malloc(global.nobj*sizeof(int));
29+
obj_array = (int **)malloc(global.nobj*sizeof(int *));
3030
dist = (int *)malloc(front_size*sizeof(int));
3131
for (i=0; i<global.nobj; i++)
3232
{
@@ -66,7 +66,7 @@ void assign_crowding_distance_indices (population *pop, int c1, int c2, Global g
6666
pop->ind[c2].crowd_dist = INF;
6767
return;
6868
}
69-
obj_array = (int **)malloc(global.nobj*sizeof(int));
69+
obj_array = (int **)malloc(global.nobj*sizeof(int *));
7070
dist = (int *)malloc(front_size*sizeof(int));
7171
for (i=0; i<global.nobj; i++)
7272
{

tests/test_nsga2_multi_objective.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def setup_optProb(self, n_obj):
5252
@parameterized.expand(
5353
[
5454
(1,),
55-
# (2,), # skipping flaky multi-objective test
55+
(2,),
5656
]
5757
)
5858
def test_opt(self, n_obj):
@@ -73,6 +73,13 @@ def test_opt(self, n_obj):
7373
assert_allclose(sol.fStar["obj1"], 12.0, atol=tol, rtol=tol)
7474
assert_allclose(sol.fStar["obj2"], 0.0, atol=tol, rtol=tol)
7575

76+
def test_options(self):
77+
with self.assertRaises(ValueError):
78+
# PopSize must be a multiple of 4
79+
self.setup_optProb(1)
80+
optOptions = {"PopSize": 5}
81+
self.optimize(optOptions=optOptions)
82+
7683

7784
if __name__ == "__main__":
7885
unittest.main()

0 commit comments

Comments
 (0)