Skip to content

Commit

Permalink
Add a test for NSGA-II and fix the fail of describe test
Browse files Browse the repository at this point in the history
  • Loading branch information
bees4ever committed Mar 2, 2018
1 parent aba7b78 commit 566e23f
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 40 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ install:

script:
- pip uninstall spotpy -y
- py.test spotpy/unittests/test_* spotpy/examples/tutorial_rosenbrock.py --cov spotpy --cov-report term-missing -v
- py.test spotpy/unittests/test_* spotpy/examples/tutorial_rosenbrock.py spotpy/examples/tutorial_nsgaii.py --cov spotpy --cov-report term-missing -v

after_success:
- coveralls
117 changes: 78 additions & 39 deletions spotpy/algorithms/nsgaii.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@
'''

import numpy as np
import pprint
import copy

import matplotlib.pyplot as pl
from mpl_toolkits.mplot3d import Axes3D

from spotpy.algorithms import _algorithm

Expand All @@ -36,13 +31,51 @@ def __repr__(self):


class NSGAII(_algorithm):
"""
Implements the "Fast and Elitist Multiobjective Genetic Algorithm: NSGA-II
by Kalyanmoy Deb, Associate Member, IEEE, Amrit Pratap, Sameer Agarwal, and T. Meyarivan
"""

def __init__(self, *args, **kwargs):
"""
Input
----------
spot_setup: class
model: function
Should be callable with a parameter combination of the parameter-function
and return an list of simulation results (as long as evaluation list)
parameter: function
When called, it should return a random parameter combination. Which can
be e.g. uniform or Gaussian
objectivefunction: function
Should return the objectivefunction for a given list of a model simulation and
observation.
evaluation: function
Should return the true values as return by the model.
dbname: str
* Name of the database where parameter, objectivefunction value and simulation results will be saved.
dbformat: str
* ram: fast suited for short sampling time. no file will be created and results are saved in an array.
* csv: A csv file will be created, which you can import afterwards.
parallel: str
* seq: Sequentiel sampling (default): Normal iterations on one core of your cpu.
* mpi: Message Passing Interface: Parallel computing on cluster pcs (recommended for unix os).
save_sim: boolean
* True: Simulation results will be saved
* False: Simulation results will not be saved
"""

super(NSGAII, self).__init__(*args, **kwargs)
# self.all_objectives = [self.setup.__getattribute__(m) for m in dir(self.setup) if "objectivefunc" in m]

self.param_len = len(self.get_parameters())
self.generation = 0
self.length_of_objective_func = 2 # TODO make it better, do we need this
self.length_of_objective_func = 0

self.objfun_maxmin_list = None
self.objfun_normalize_list= []
Expand All @@ -55,9 +88,11 @@ def fast_non_dominated_sort(self, P):
F[1] = {}

if self.objfun_maxmin_list is None:
self.length_of_objective_func = 0
# In the first iteration create this list to have it prepared for later use
self.objfun_maxmin_list = []
for _ in self.objectivefunction(self.setup.evaluation(), self.setup.simulation(P[0])):
self.length_of_objective_func += 1
self.objfun_maxmin_list.append([])

param_generator = ((p, list(P[p])) for p in P)
Expand Down Expand Up @@ -185,40 +220,44 @@ def sample(self, generations=2, paramsamp=20):
F = self.fast_non_dominated_sort(R_0)

print("GENERATION: " + str(self.generation) + " of " + str(generations))
layer = 0
fig = pl.figure()

if self.length_of_objective_func == 2:

for i in F:
if layer == 0:
l_color = "b"
else:
l_color = "#"
for _ in range(6):
l_color += ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"][
np.random.randint(16)]
for j in F[i]:
pl.plot(F[i][j].m_vals[0], F[i][j].m_vals[1], color=l_color, marker='o')
layer += 1

pl.show()

elif self.length_of_objective_func == 3:

ax = fig.add_subplot(111, projection='3d')

for i in F:
for j in F[i]:
ax.scatter(F[i][j].m_vals[0], F[i][j].m_vals[1],
F[i][j].m_vals[2]) # , lay_col[layer] + 'o')
layer += 1

# ax.set_xlabel(m1_name)
# ax.set_ylabel(m2_name)
# ax.set_zlabel(m3_name)

pl.show()
# Debuggin Issue
# import matplotlib.pyplot as pl
# from mpl_toolkits.mplot3d import Axes3D
# layer = 0
# fig = pl.figure()
#
# if self.length_of_objective_func == 2:
#
# for i in F:
# if layer == 0:
# l_color = "b"
# else:
# l_color = "#"
# for _ in range(6):
# l_color += ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"][
# np.random.randint(16)]
# for j in F[i]:
# pl.plot(F[i][j].m_vals[0], F[i][j].m_vals[1], color=l_color, marker='o')
# layer += 1
#
# pl.show()
#
# elif self.length_of_objective_func == 3:
#
# ax = fig.add_subplot(111, projection='3d')
#
# for i in F:
# for j in F[i]:
# ax.scatter(F[i][j].m_vals[0], F[i][j].m_vals[1],
# F[i][j].m_vals[2]) # , lay_col[layer] + 'o')
# layer += 1
#
# # ax.set_xlabel(m1_name)
# # ax.set_ylabel(m2_name)
# # ax.set_zlabel(m3_name)
#
# pl.show()

# Now sort again
complete_sort_all_p = []
Expand Down
92 changes: 92 additions & 0 deletions spotpy/examples/tutorial_nsgaii.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#!/usr/bin/env python
# coding: utf-8


from __future__ import division, print_function
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

try:
import spotpy
except ImportError:
import sys

sys.path.append(".")
import spotpy

import spotpy.algorithms
from spotpy.examples.hymod_python.hymod import hymod
import os
import unittest


class spot_setup(object):
def __init__(self):
# Transform [mm/day] into [l s-1], where 1.783 is the catchment area
self.Factor = 1.783 * 1000 * 1000 / (60 * 60 * 24)
# Load Observation data from file
self.PET, self.Precip = [], []
self.date, self.trueObs = [], []
self.owd = os.path.dirname(os.path.realpath(__file__))
self.hymod_path = self.owd + os.sep + 'hymod_python'
climatefile = open(self.hymod_path + os.sep + 'hymod_input.csv', 'r')
headerline = climatefile.readline()[:-1]

if ';' in headerline:
self.delimiter = ';'
else:
self.delimiter = ','
self.header = headerline.split(self.delimiter)
for line in climatefile:
values = line.strip().split(self.delimiter)
self.date.append(str(values[0]))
self.Precip.append(float(values[1]))
self.PET.append(float(values[2]))
self.trueObs.append(float(values[3]))

climatefile.close()
self.params = [spotpy.parameter.Uniform('cmax', low=1.0, high=500, optguess=412.33),
spotpy.parameter.Uniform('bexp', low=0.1, high=2.0, optguess=0.1725),
spotpy.parameter.Uniform('alpha', low=0.1, high=0.99, optguess=0.8127),
spotpy.parameter.Uniform('Ks', low=0.0, high=0.10, optguess=0.0404),
spotpy.parameter.Uniform('Kq', low=0.1, high=0.99, optguess=0.5592),
spotpy.parameter.Uniform('fake1', low=0.1, high=10, optguess=0.5592),
spotpy.parameter.Uniform('fake2', low=0.1, high=10, optguess=0.5592)]

def parameters(self):
return spotpy.parameter.generate(self.params)

def simulation(self, x):
data = hymod(self.Precip, self.PET, x[0], x[1], x[2], x[3], x[4])
sim = []
for val in data:
sim.append(val * self.Factor)
return sim[366:]

def evaluation(self):
return self.trueObs[366:]

def objectivefunction(self, simulation, evaluation, params=None):
# like = spotpy.likelihoods.gaussianLikelihoodMeasErrorOut(evaluation,simulation)
# return -like
# like1 = spotpy.signatures.getSkewness(evaluation, simulation)
like1 = spotpy.objectivefunctions.agreementindex(evaluation, simulation)
like2 = spotpy.objectivefunctions.rmse(evaluation, simulation)
like3 = spotpy.signatures.getCoeffVariation(evaluation, simulation)
return [like1, like2, like3]



class Test_NSGAII(unittest.TestCase):
def setUp(self):
self.sp_setup = spot_setup()
self.sampler = spotpy.algorithms.NSGAII(self.sp_setup, dbname='NSGA2', dbformat="csv")

self.sampler.sample(generations=5, paramsamp=40)

def test_sampler_output(self):
self.assertGreaterEqual(400, len(self.sampler.getdata()))
self.assertLessEqual(300, len(self.sampler.getdata()))

0 comments on commit 566e23f

Please sign in to comment.