Using a Framework with a Custom Objective Function
Contents Chat Share Follow Download Source
Get access to this section and more
Below is a featured selection from this section. You can access this notebook and more by getting the ebook on Practical Evolutionary Algorithms.
Preamble¶
# used to create block diagrams
%reload_ext xdiag_magic
%xdiag_output_format svg
import numpy as np # for multidimensional containers
import pandas as pd # for DataFrames
import plotly.graph_objects as go # for data visualisation
import platypus as plat # multiobjective optimisation framework
Introduction¶
When applying multiobjective optimisation algorithms to realworld problems, we will often need to implement the objective functions ourselves. This problem comes in two parts:
 We need to design an objective function that correctly represents our realworld problem, taking the problem variables and producing the correct objective values;
 We need to implement this objective function in a way that can work with our optimiser.
This comes down to passing the desired number of problem variables to a custom objective function and receiving the desired number of objective values.
%%blockdiag
{
orientation = portrait
"Problem Variables" > "Objective Function" > "Objective Values"
"Objective Function" [color = '#ffffcc']
}
When preparing to implement multiobjective optimisation experiments, it's often more convenient to use a readymade framework/library instead of programming everything from scratch. Many libraries and frameworks have been implemented in many different programming languages. With our focus on multiobjective optimisation, our choice is an easy one. We will choose Platypus which has a focus on multiobjective problems and optimisation.
Platypus is a framework for evolutionary computing in Python with a focus on multiobjective evolutionary algorithms (MOEAs). It differs from existing optimization libraries, including PyGMO, Inspyred, DEAP, and Scipy, by providing optimization algorithms and analysis tools for multiobjective optimization.
In this section, we will use the Platypus framework to apply the Nondominated Sorting Genetic Algorithm II (NSGAII)^{1} to a custom objective function.
The Custom Objective Function¶
For our custom objective function we will look to implement F2 from Schaffer 1985^{2}, which is described as being a twovalued function of one variable. The function has been listed in Equation 1.
$$ \text{Minimize} = \begin{cases} f_{1}\left(x\right) = x^{2} \\ \tag{1} f_{2}\left(x\right) = \left(x2\right)^{2} \\ \end{cases} $$Let's implement this objective function using Python.
def schaffer_f1(x):
f1 = x[0]**2
f2 = (x[0]2)**2
return [f1, f2]
Now let's get this Python function into the Platypus Problem
object which can be used during the evaluation stage of Platypus' optimisation process.
First, we will instantiate an instance of the Problem object, passing in the parameters $1$ and $2$, indicating that we want 1 problem variable and 2 objective values, respectively.
problem = plat.Problem(1, 2)
Next, we need to specify the type of the problem variables and their boundaries. In this case, we want realvalued problem variables between 10 and 10.
problem.types[:] = plat.Real(10, 10)
Finally, we will assign our implementation of the Schaffer F1 function to our Problem object.
problem.function = schaffer_f1
Now we're ready to apply an optimisation algorithm to the problem. Let's create an instance of the NSGAII optimiser, and pass in our problem object as a parameter for its configurations.
algorithm = plat.NSGAII(problem)
Now we can execute the optimisation process. Let's give the optimiser a budget of 10,000 function evaluations as a termination criterion. This may take some time to complete depending on your processor speed and the number of function evaluations.
algorithm.run(10000)
Finally, we can display the results. In this case, we will be printing the objective values for each solution in the final population of the above execution.
for solution in algorithm.result:
print(solution.objectives)
[4.000406116449771, 1.0307637417395e08] [2.0661887134436118e07, 3.998181992676149] [2.1701411576087213, 0.2775815676054482] [2.047811296694047, 0.323741001257001] [3.85795280674386, 0.0012839892422746124] [0.752300481583038, 1.2828901995136763] [3.7335101024681214, 0.004592866561791519] [0.9117035925644464, 1.0923767564542999] [1.8623633131194153, 0.4036260040056451] [0.8737830994884715, 1.1347284607040173] [2.2510520799554907, 0.24964947062424778] [0.07764548290622653, 2.963047920330557] [0.6916914011009517, 1.3649719332745425] [0.23659564877888764, 2.290951698704208] [1.9585886984225853, 0.3606052065961433] [0.09141036747786122, 2.882044467658547] [1.3508179132222, 0.7018302157169464] [0.05861003020580801, 3.0902296900021624] [0.009522277661513296, 3.6191936435796506] [0.20831162577328802, 2.3826648876630343] [2.3357939109809247, 0.22247218088240192] [0.17617409041500665, 2.497250194986716] [0.8222956207433623, 1.1950749310287432] [2.4348663862579305, 0.19324302529430307] [0.04722632331267073, 3.1779615920583004] [1.2013076140510766, 0.8171404383132232] [1.2398721228004768, 0.7858903126885822] [1.154527527317117, 0.8565698219558984] [0.5352317220060879, 1.6088504153241636] [3.5967413411075397, 0.0107106624376574] [2.956686953256236, 0.07867915651016248] [0.06690611713824247, 3.0322574452636397] [3.955898122980472, 0.00012223575944294592] [0.9675304533431293, 1.0330054180319967] [3.663820749193919, 0.007376927999728054] [2.8433301863412423, 0.09845932164265439] [0.4532346290789683, 1.760326523468327] [2.666832761916732, 0.13465669335675234] [2.9298324600209735, 0.08313111117161856] [0.3452600320302341, 1.9949067580555013] [2.7502214336068773, 0.11670479929366886] [0.021632339349669443, 3.433314882873397] [3.127081161937991, 0.05365917601011508] [3.0595161909986706, 0.06292708944506217] [0.49503002027424053, 1.6806952277543725] [0.13269953390616224, 2.6755816448873646] [0.4909892386826973, 1.6881642675289228] [1.069628745906803, 0.9327144448233435] [0.21165344974443542, 2.3714210742247115] [0.00042548244659934515, 3.9179165790143666] [0.12193226241956984, 2.725180244804017] [0.2529102418024825, 2.2413029568584952] [0.3735599386902117, 1.928777940424643] [0.407215118948672, 1.8546787522775225] [0.01902321540284389, 3.467324523682896] [3.4270709706303144, 0.022131029612221954] [1.3927284792024572, 0.6721717676228457] [2.310777073648161, 0.2302809443532351] [0.10663910855534246, 2.80041334824992] [1.6782466262782314, 0.49636028822992345] [2.564552083012348, 0.158864506475574] [1.5990506691201138, 0.5409076594848761] [1.6466273900678845, 0.5137881912339534] [2.507086749219784, 0.17357366503684019] [3.5195942098870043, 0.015361580351052272] [3.346732876383687, 0.029101700781913598] [0.16701957396220501, 2.53229844074245] [1.296487169875423, 0.7419515494189568] [0.9813285269356339, 1.0188474315901757] [0.431990830820378, 1.8029504558687022] [0.005594521150650002, 3.7064083944495607] [0.028762881843416077, 3.3503779546120858] [0.002768126489055616, 3.7923161751441232] [0.6688676445871639, 1.3974944904828173] [0.6331087140148225, 1.4503835571347692] [0.14917494460438735, 2.6042480487060096] [0.03490266701368317, 3.287612447474493] [1.019691804230725, 0.98050019356262] [1.7610500734362216, 0.45286759965298273] [0.2889820244203225, 2.1387000915740364] [1.9946522245818739, 0.3453659339686975] [1.8170967153001796, 0.4251075234709829] [1.7183618263287819, 0.47490979343475437] [1.539482996149637, 0.5764468348473448] [1.1180491417008018, 0.888535426483315] [0.3709436302320389, 1.9347379567076086] [2.595263224841164, 0.15133495107378572] [1.1042434065425988, 0.9009239439414535] [0.5600452166100484, 1.566598463156636] [0.58496103481646, 1.5256512177068295] [0.2657901312645098, 2.2035966145856904] [1.2880316070285809, 0.7483724003857195] [0.15154734840880954, 2.5943840382383727] [2.6393378081564633, 0.14092223738050583] [0.2762477642642471, 2.173876667567008] [0.014128004691408657, 3.5386828710928633] [0.8007826736502606, 1.2213242260070742] [0.30214239286818895, 2.10344316698689] [0.013468293147486475, 3.54925639071522] [3.281546468271266, 0.03553077050050727]
Visualising Solutions in Objective Space¶
In the last section, we concluded by printing the objective values for every solution. This information will be easier to digest using a plot, so let's quickly put the data into a Pandas DataFrame and then use Plotly to create a scatterplot. Let's start by moving our Platypus data structure to a DataFrame.
objective_values = np.empty((0, 2))
for solution in algorithm.result:
y = solution.objectives
objective_values = np.vstack([objective_values, y])
# convert to DataFrame
objective_values = pd.DataFrame(objective_values, columns=['f1','f2'])
With that complete, we can have a peek at our DataFrame to make sure we've not made any obvious mistakes.
objective_values
f1  f2  

0  4.000406e+00  1.030764e08 
1  2.066189e07  3.998182e+00 
2  2.170141e+00  2.775816e01 
3  2.047811e+00  3.237410e01 
4  3.857953e+00  1.283989e03 
...  ...  ... 
95  1.412800e02  3.538683e+00 
96  8.007827e01  1.221324e+00 
97  3.021424e01  2.103443e+00 
98  1.346829e02  3.549256e+00 
99  3.281546e+00  3.553077e02 
100 rows × 2 columns
With no obvious issues, let's visualise the results using a scatterplot.
fig = go.Figure()
fig.add_scatter(x=objective_values.f1, y=objective_values.f2, mode='markers')
fig.show()
Great! If you search the literature for the true Paretooptimal front for Schaffer F1, you can see that our approximation is looking as expected.
Conclusion¶
In this section, we have demonstrated how we can use a popular multiobjective optimisation algorithm, NSGAII, to approximate multiple tradeoff solutions to the Schaffer F1 test problem. We did this using the Platypus framework, and by implementing our custom objective function. You can use this approach to write your own objective functions that can be optimised by any algorithm in the Platypus framework.

Deb, K., Pratap, A., Agarwal, S., & Meyarivan, T. A. M. T. (2002). A fast and elitist multiobjective genetic algorithm: NSGAII. IEEE transactions on evolutionary computation, 6(2), 182197. ↩

Schaffer, J.. (1985). Multiple Objective Optimization with Vector Evaluated Genetic Algorithms. Proceedings of the First Int. Conference on Genetic Algortihms, Ed. G.J.E Grefensette, J.J. Lawrence Erlbraum. 93100. ↩
Get access to this section and more
You can access this notebook and more by getting the ebook on Practical Evolutionary Algorithms.