You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by er...@apache.org on 2022/01/19 04:47:06 UTC

[commons-math] branch feature__MATH-1563__genetic_algorithm updated (76d6c40 -> 378a167)

This is an automated email from the ASF dual-hosted git repository.

erans pushed a change to branch feature__MATH-1563__genetic_algorithm
in repository https://gitbox.apache.org/repos/asf/commons-math.git.


    from 76d6c40  Add "LICENCE" and "NOTICE" files.
     add bc3711d  Track changes.
     add 9b0fc1f  Allow successful build on Java 9+.
     add 7bb6190  Remove spurious file.
     add 336811d  Relax tolerance (unit tests).
     add d81b5e9  Replace "CMAESOptimizer.Sigma" with "Sigma".
     add ae6ceea  Replace calls to deprecated classes and methods (unit tests).
     add 2a1da68  Remove examples and correct artifact ids in dist-archive
     add 916a7d0  Add a release profile
     add f4bc2a4  Do not perform site checkout by default
     add 61cfea9  Disable jacoco coverage check in core module
     add 5b291c7  Merge branch 'master' of https://gitbox.apache.org/repos/asf/commons-math
     add 32c7564  Remove dependency fileset
     add 384554f  Move "shade" plugin to a profile (POM).
     add 426545d  Relax tolerance (unit test).
     add 49f220c  Fix duplicate reference (POM).
     new dd36d80  MATH-1563: Introducing new implementation of GA functionality (WIP).
     new a7797aa  Move GA module declaration to ensure that there are no dependencies on legacy codes.
     new 67f376b  MATH-1563: Introducing new implementation of GA functionality (WIP).
     new b79fc9e  Move GA module declaration to ensure that there are no dependencies on legacy codes.
     new 6e52481  MATH-1563: Introducing new implementation of GA functionality (WIP).
     new 2af5ba0  Move GA module declaration to ensure that there are no dependencies on legacy codes.
     new 770f4d9  Add "LICENCE" and "NOTICE" files.
     new 825a18a  Merge branch 'feature__MATH-1563__genetic_algorithm' of https://gitbox.apache.org/repos/asf/commons-math into feature__MATH-1563__genetic_algorithm
     new 378a167  Add dependency on "ga" module.

The 9 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 commons-math-core/pom.xml                          |   3 +
 .../commons/math4/core/jdkmath/JdkMathTest.java    |  10 +
 commons-math-examples/pom.xml                      |  86 ++--
 .../nonlinear/scalar/noderiv/CMAESOptimizer.java   |  78 +--
 .../AbstractLeastSquaresOptimizerAbstractTest.java |  10 +-
 .../LevenbergMarquardtOptimizerTest.java           |   7 +-
 .../ml/clustering/FuzzyKMeansClustererTest.java    |   5 +-
 .../scalar/noderiv/CMAESOptimizerTest.java         |  19 +-
 .../math4/legacy/stat/StatUtilsTest.java.orig      | 556 ---------------------
 .../std_test_func.simplex.multidirectional.csv     |   2 +-
 .../noderiv/std_test_func.simplex.nelder_mead.csv  |   4 +-
 dist-archive/pom.xml                               |  44 +-
 dist-archive/src/assembly/bin.xml                  |   7 -
 pom.xml                                            |  32 +-
 src/changes/changes.xml                            |   3 +
 15 files changed, 156 insertions(+), 710 deletions(-)
 delete mode 100644 commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/stat/StatUtilsTest.java.orig

[commons-math] 01/09: MATH-1563: Introducing new implementation of GA functionality (WIP).

Posted by er...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

erans pushed a commit to branch feature__MATH-1563__genetic_algorithm
in repository https://gitbox.apache.org/repos/asf/commons-math.git

commit dd36d808e111553a8be249537cbcf76b3103babd
Author: avbasak1 <av...@in.ibm.com>
AuthorDate: Sun Jan 2 18:54:37 2022 +0530

    MATH-1563: Introducing new implementation of GA functionality (WIP).
---
 .../examples-ga/examples-ga-math-functions/pom.xml |  47 ++++
 .../mathfunctions/dimension2/Dim2GraphPlotter.java | 145 ++++++++++
 .../dimension2/Dimension2Coordinate.java           |  64 +++++
 .../dimension2/Dimension2Decoder.java              |  49 ++++
 .../dimension2/Dimension2FitnessFunction.java      |  40 +++
 .../Dimension2FunctionAdaptiveOptimizer.java       | 114 ++++++++
 .../dimension2/Dimension2FunctionOptimizer.java    | 114 ++++++++
 .../legacy/Dimension2FunctionOptimizerLegacy.java  | 103 +++++++
 .../dimension2/legacy/LegacyBinaryChromosome.java  |  65 +++++
 .../dimension2/legacy/UnchangedBestFitness.java    |  67 +++++
 .../dimension2/legacy/package-info.java            |  20 ++
 .../ga/mathfunctions/dimension2/package-info.java  |  20 ++
 .../mathfunctions/dimensionN/DimNGraphPlotter.java | 145 ++++++++++
 .../dimensionN/DimensionNCoordinate.java           |  54 ++++
 .../dimensionN/DimensionNDecoder.java              |  52 ++++
 .../dimensionN/DimensionNFitnessFunction.java      |  42 +++
 .../DimensionNFunctionAdaptiveOptimizer.java       | 114 ++++++++
 .../dimensionN/DimensionNFunctionOptimizer.java    | 113 ++++++++
 .../ga/mathfunctions/dimensionN/package-info.java  |  20 ++
 .../examples/ga/mathfunctions/utils/Constants.java |  55 ++++
 .../ga/mathfunctions/utils/package-info.java       |  20 ++
 .../examples-ga/examples-ga-tsp/pom.xml            |  52 ++++
 .../math4/examples/ga/tsp/TSPFitnessFunction.java  |  52 ++++
 .../math4/examples/ga/tsp/TSPOptimizer.java        | 116 ++++++++
 .../math4/examples/ga/tsp/commons/City.java        |  77 ++++++
 .../examples/ga/tsp/commons/DistanceMatrix.java    |  71 +++++
 .../examples/ga/tsp/commons/package-info.java      |  20 ++
 .../examples/ga/tsp/legacy/TSPChromosome.java      |  76 ++++++
 .../examples/ga/tsp/legacy/TSPOptimizerLegacy.java |  99 +++++++
 .../ga/tsp/legacy/UnchangedBestFitness.java        |  67 +++++
 .../math4/examples/ga/tsp/legacy/package-info.java |  20 ++
 .../math4/examples/ga/tsp/package-info.java        |  20 ++
 .../math4/examples/ga/tsp/utils/Constants.java     |  65 +++++
 .../math4/examples/ga/tsp/utils/GraphPlotter.java  | 146 ++++++++++
 .../math4/examples/ga/tsp/utils/package-info.java  |  20 ++
 commons-math-examples/examples-ga/pom.xml          |  56 ++++
 commons-math-examples/pom.xml                      |   1 +
 commons-math-ga/pom.xml                            |  54 ++++
 .../commons/math4/ga/AbstractGeneticAlgorithm.java | 180 ++++++++++++
 .../commons/math4/ga/AdaptiveGeneticAlgorithm.java | 164 +++++++++++
 .../apache/commons/math4/ga/GeneticAlgorithm.java  | 171 ++++++++++++
 .../math4/ga/chromosome/AbstractChromosome.java    | 148 ++++++++++
 .../ga/chromosome/AbstractListChromosome.java      | 125 +++++++++
 .../math4/ga/chromosome/BinaryChromosome.java      | 303 +++++++++++++++++++++
 .../commons/math4/ga/chromosome/Chromosome.java    |  48 ++++
 .../math4/ga/chromosome/ChromosomePair.java        |  66 +++++
 .../ga/chromosome/IntegralValuedChromosome.java    | 136 +++++++++
 .../math4/ga/chromosome/RealValuedChromosome.java  | 160 +++++++++++
 .../commons/math4/ga/chromosome/package-info.java  |  20 ++
 .../math4/ga/convergence/FixedElapsedTime.java     |  80 ++++++
 .../math4/ga/convergence/FixedGenerationCount.java |  76 ++++++
 .../math4/ga/convergence/StoppingCondition.java    |  38 +++
 .../math4/ga/convergence/UnchangedBestFitness.java |  72 +++++
 .../math4/ga/convergence/UnchangedMeanFitness.java |  85 ++++++
 .../commons/math4/ga/convergence/package-info.java |  20 ++
 .../AbstractChromosomeCrossoverPolicy.java         |  53 ++++
 .../AbstractListChromosomeCrossoverPolicy.java     |  76 ++++++
 .../math4/ga/crossover/CrossoverPolicy.java        |  39 +++
 .../commons/math4/ga/crossover/CycleCrossover.java | 168 ++++++++++++
 .../math4/ga/crossover/NPointCrossover.java        | 154 +++++++++++
 .../ga/crossover/OnePointBinaryCrossover.java      | 115 ++++++++
 .../math4/ga/crossover/OnePointCrossover.java      | 102 +++++++
 .../math4/ga/crossover/OrderedCrossover.java       | 131 +++++++++
 .../math4/ga/crossover/UniformCrossover.java       | 123 +++++++++
 .../commons/math4/ga/crossover/package-info.java   |  20 ++
 ...nearAverageRankBasedCrossoverRateGenerator.java |  58 ++++
 ...nearMaximumRankBasedCrossoverRateGenerator.java |  58 ++++
 .../ConstantCrossoverRateGenerator.java            |  50 ++++
 .../rategenerator/CrossoverRateGenerator.java      |  42 +++
 .../ga/crossover/rategenerator/package-info.java   |  20 ++
 .../ga/decoder/AbstractListChromosomeDecoder.java  |  59 ++++
 .../apache/commons/math4/ga/decoder/Decoder.java   |  35 +++
 .../commons/math4/ga/decoder/RandomKeyDecoder.java |  75 +++++
 .../decoder/TransparentListChromosomeDecoder.java  |  39 +++
 .../commons/math4/ga/decoder/package-info.java     |  20 ++
 .../commons/math4/ga/fitness/FitnessFunction.java  |  34 +++
 .../commons/math4/ga/fitness/package-info.java     |  20 ++
 .../ga/internal/exception/GeneticException.java    | 120 ++++++++
 .../math4/ga/internal/exception/package-info.java  |  20 ++
 .../stats/PopulationStatisticalSummaryImpl.java    | 177 ++++++++++++
 .../math4/ga/internal/stats/package-info.java      |  20 ++
 .../math4/ga/listener/ConvergenceListener.java     |  37 +++
 .../ga/listener/ConvergenceListenerRegistry.java   |  91 +++++++
 .../ga/listener/PopulationStatisticsLogger.java    |  49 ++++
 .../commons/math4/ga/listener/package-info.java    |  20 ++
 .../AbstractListChromosomeMutationPolicy.java      | 101 +++++++
 .../commons/math4/ga/mutation/BinaryMutation.java  | 135 +++++++++
 .../math4/ga/mutation/IntegralValuedMutation.java  |  88 ++++++
 .../commons/math4/ga/mutation/MutationPolicy.java  |  36 +++
 .../math4/ga/mutation/RealValuedMutation.java      |  97 +++++++
 .../commons/math4/ga/mutation/package-info.java    |  20 ++
 .../AdaptiveLinearMutationRateGenerator.java       |  54 ++++
 .../ConstantMutationRateGenerator.java             |  47 ++++
 .../rategenerator/MutationRateGenerator.java       |  38 +++
 .../ga/mutation/rategenerator/package-info.java    |  20 ++
 .../org/apache/commons/math4/ga/package-info.java  |  20 ++
 .../math4/ga/population/ListPopulation.java        | 220 +++++++++++++++
 .../commons/math4/ga/population/Population.java    |  59 ++++
 .../commons/math4/ga/population/package-info.java  |  20 ++
 .../math4/ga/selection/SelectionPolicy.java        |  35 +++
 .../math4/ga/selection/TournamentSelection.java    | 108 ++++++++
 .../commons/math4/ga/selection/package-info.java   |  20 ++
 .../ga/stats/PopulationStatisticalSummary.java     |  67 +++++
 .../commons/math4/ga/stats/package-info.java       |  20 ++
 .../ga/utils/ChromosomeRepresentationUtils.java    | 211 ++++++++++++++
 .../math4/ga/utils/RandomProviderManager.java      |  47 ++++
 .../commons/math4/ga/utils/package-info.java       |  20 ++
 .../math4/ga/GeneticAlgorithmTestBinaryOneMax.java | 187 +++++++++++++
 .../math4/ga/GeneticAlgorithmTestPermutations.java | 144 ++++++++++
 .../ga/chromosome/AbstractChromosomeTest.java      |  65 +++++
 .../math4/ga/chromosome/BinaryChromosomeTest.java  |  92 +++++++
 .../math4/ga/chromosome/ChromosomePairTest.java    |  38 +++
 .../chromosome/IntegralValuedChromosomeTest.java   |  93 +++++++
 .../ga/chromosome/RealValuedChromosomeTest.java    |  75 +++++
 .../ga/convergencecond/FixedElapsedTimeTest.java   |  59 ++++
 .../convergencecond/FixedGenerationCountTest.java  |  48 ++++
 .../convergencecond/UnchangedBestFitnessTest.java  |  68 +++++
 .../convergencecond/UnchangedMeanFitnessTest.java  |  68 +++++
 .../AbstractChromosomeCrossoverPolicyTest.java     |  45 +++
 .../AbstractListChromosomeCrossoverPolicyTest.java |  77 ++++++
 .../math4/ga/crossover/CycleCrossoverTest.java     | 115 ++++++++
 .../math4/ga/crossover/NPointCrossoverTest.java    | 127 +++++++++
 .../ga/crossover/OnePointBinaryCrossoverTest.java  |  73 +++++
 .../math4/ga/crossover/OnePointCrossoverTest.java  |  66 +++++
 .../math4/ga/crossover/OrderedCrossoverTest.java   |  63 +++++
 .../math4/ga/crossover/UniformCrossoverTest.java   | 113 ++++++++
 ...MaximumRankBasedCrossoverRateGeneratorTest.java |  68 +++++
 .../decoder/AbstractListChromosomeDecoderTest.java |  44 +++
 .../math4/ga/decoder/RandomKeyDecoderTest.java     |  58 ++++
 .../TransparentListChromosomeDecoderTest.java      |  39 +++
 .../commons/math4/ga/dummy/DummyChromosome.java    |  27 ++
 .../math4/ga/dummy/DummyListChromosome.java        |  47 ++++
 .../math4/ga/dummy/DummyListChromosomeDecoder.java |  41 +++
 .../math4/ga/exception/GeneticExceptionTest.java   |  39 +++
 .../listener/ConvergenceListenerRegistryTest.java  | 107 ++++++++
 .../listener/PopulationStatisticsLoggerTest.java   |  45 +++
 .../AbstractListChromosomeMutationPolicyTest.java  |  44 +++
 .../math4/ga/mutation/BinaryMutationTest.java      |  90 ++++++
 .../ga/mutation/IntegralValuedMutationTest.java    |  85 ++++++
 .../math4/ga/mutation/RealValuedMutationTest.java  |  85 ++++++
 .../AdaptiveLinearMutationRateGeneratorTest.java   |  61 +++++
 .../ConstantMutationRateGeneratorTest.java         |  45 +++
 .../math4/ga/population/ListPopulationTest.java    | 202 ++++++++++++++
 .../ga/selection/TournamentSelectionTest.java      | 109 ++++++++
 .../utils/ChromosomeRepresentationUtilsTest.java   | 163 +++++++++++
 pom.xml                                            |   1 +
 .../resources/spotbugs/spotbugs-exclude-filter.xml |   6 +
 147 files changed, 10897 insertions(+)

diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/pom.xml b/commons-math-examples/examples-ga/examples-ga-math-functions/pom.xml
new file mode 100644
index 0000000..d09ca3f
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/pom.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor 
+    license agreements. See the NOTICE file distributed with this work for additional 
+    information regarding copyright ownership. The ASF licenses this file to 
+    You under the Apache License, Version 2.0 (the "License"); you may not use 
+    this file except in compliance with the License. You may obtain a copy of 
+    the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required 
+    by applicable law or agreed to in writing, software distributed under the 
+    License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
+    OF ANY KIND, either express or implied. See the License for the specific 
+    language governing permissions and limitations under the License. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>examples-ga</artifactId>
+        <version>4.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>examples-ga-math-functions</artifactId>
+
+    <properties>
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
+
+        <!-- OSGi -->
+        <commons.osgi.symbolicName>org.apache.commons.math4.examples.ga.mathfunctions</commons.osgi.symbolicName>
+        <commons.osgi.export>org.apache.commons.math4.examples.ga.mathfunctions</commons.osgi.export>
+        <!-- Java 9+ -->
+        <commons.automatic.module.name>org.apache.commons.math4.examples.ga.mathfunctions</commons.automatic.module.name>
+        <!-- Workaround to avoid duplicating config files. -->
+        <math.parent.dir>${basedir}/../../..</math.parent.dir>
+
+        <uberjar.name>examples-ga-mathfunctions</uberjar.name>
+        <project.mainClass>org.apache.commons.math4.examples.ga.mathfunctions.Dimension2FunctionOptimizer</project.mainClass>
+        <slf4jVersion>1.7.32</slf4jVersion>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <version>${slf4jVersion}</version>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/Dim2GraphPlotter.java b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/Dim2GraphPlotter.java
new file mode 100644
index 0000000..eca37e8
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/Dim2GraphPlotter.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.examples.ga.mathfunctions.dimension2;
+
+import java.awt.BorderLayout;
+import java.util.List;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+import org.apache.commons.math4.ga.internal.stats.PopulationStatisticalSummaryImpl;
+import org.apache.commons.math4.ga.listener.ConvergenceListener;
+import org.apache.commons.math4.ga.population.Population;
+import org.apache.commons.math4.ga.stats.PopulationStatisticalSummary;
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.ChartPanel;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
+import org.jfree.data.xy.XYSeries;
+import org.jfree.data.xy.XYSeriesCollection;
+
+/**
+ * This class represents the graph plotter during optimization.
+ */
+public class Dim2GraphPlotter extends JFrame implements ConvergenceListener<Dimension2Coordinate> {
+
+    /**
+     * Generated serialversionId.
+     */
+    private static final long serialVersionUID = -5683904006424006584L;
+
+    /** collection of 2-D series. **/
+    private final XYSeriesCollection dataset = new XYSeriesCollection();
+
+    /**
+     * constructor.
+     * @param plotSubject subject of plot
+     * @param xAxisLabel  x axis label
+     * @param yAxisLabel  y axis label
+     */
+    public Dim2GraphPlotter(String plotSubject, String xAxisLabel, String yAxisLabel) {
+        super(plotSubject);
+
+        final JPanel chartPanel = createChartPanel(plotSubject, xAxisLabel, yAxisLabel);
+        add(chartPanel, BorderLayout.CENTER);
+
+        setSize(640, 480);
+        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+        setLocationRelativeTo(null);
+
+        setVisible(true);
+    }
+
+    /**
+     * Adds data point to graph.
+     * @param graphName  name of graph
+     * @param generation generation, to be plotted along x axis
+     * @param value      value, to be plotted along y axis
+     */
+    private void addDataPoint(String graphName, int generation, double value) {
+        XYSeries series = null;
+
+        if (!containsGraph(graphName)) {
+            series = new XYSeries(graphName);
+            dataset.addSeries(series);
+        } else {
+            series = dataset.getSeries(graphName);
+        }
+        series.add(generation, value);
+
+        setVisible(true);
+    }
+
+    /**
+     * Checks if the graph with the given name already exists.
+     * @param graphName name of the graph
+     * @return true/false
+     */
+    @SuppressWarnings("unchecked")
+    private boolean containsGraph(String graphName) {
+        final List<XYSeries> seriesList = dataset.getSeries();
+        if (seriesList == null || seriesList.isEmpty()) {
+            return false;
+        }
+        for (XYSeries series : seriesList) {
+            if (series.getKey().compareTo(graphName) == 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Creates chart panel.
+     * @param chartTitle chart title
+     * @param xAxisLabel x axis label
+     * @param yAxisLabel y axis label
+     * @return panel
+     */
+    private JPanel createChartPanel(String chartTitle, String xAxisLabel, String yAxisLabel) {
+
+        final boolean showLegend = true;
+        final boolean createURL = false;
+        final boolean createTooltip = false;
+
+        final JFreeChart chart = ChartFactory.createXYLineChart(chartTitle, xAxisLabel, yAxisLabel, dataset,
+                PlotOrientation.VERTICAL, showLegend, createTooltip, createURL);
+        final XYPlot plot = chart.getXYPlot();
+        final XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
+
+        plot.setRenderer(renderer);
+
+        return new ChartPanel(chart);
+
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void notify(int generation, Population<Dimension2Coordinate> population) {
+        PopulationStatisticalSummary<Dimension2Coordinate> populationStatisticalSummary =
+                new PopulationStatisticalSummaryImpl<>(population);
+        this.addDataPoint("Average", generation, populationStatisticalSummary.getMeanFitness());
+        this.addDataPoint("Best", generation, populationStatisticalSummary.getMaxFitness());
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/Dimension2Coordinate.java b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/Dimension2Coordinate.java
new file mode 100644
index 0000000..307f1ef
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/Dimension2Coordinate.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.examples.ga.mathfunctions.dimension2;
+
+/**
+ * This class represents the coordinate of the problem domain i.e. the phenotype of chromosome.
+ */
+public class Dimension2Coordinate {
+
+    /** coordinate of first dimension. **/
+    private final double x;
+
+    /** coordinate of second dimension. **/
+    private final double y;
+
+    /**
+     * constructor.
+     * @param x coordinate of first dimension
+     * @param y coordinate of second dimension
+     */
+    public Dimension2Coordinate(double x, double y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    /**
+     * returns the coordinate of first dimension.
+     * @return coordinate of first dimension
+     */
+    public double getX() {
+        return x;
+    }
+
+    /**
+     * returns the coordinate of second dimension.
+     * @return coordinate of second dimension
+     */
+    public double getY() {
+        return y;
+    }
+
+    /**
+     * Returns a string representation of coordinate.
+     */
+    @Override
+    public String toString() {
+        return "Coordinate [x=" + x + ", y=" + y + "]";
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/Dimension2Decoder.java b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/Dimension2Decoder.java
new file mode 100644
index 0000000..e8394d1
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/Dimension2Decoder.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.examples.ga.mathfunctions.dimension2;
+
+import org.apache.commons.math4.ga.chromosome.BinaryChromosome;
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.decoder.Decoder;
+
+/**
+ * Decoder to convert chromosome's binary genotype to phenotype
+ * {@link Dimension2Coordinate}.
+ */
+public class Dimension2Decoder implements Decoder<Dimension2Coordinate> {
+
+    /**
+     * Decode the binary representation of chromosome to
+     * {@link Dimension2Coordinate}.
+     * @param chromosome The {@link Chromosome}
+     */
+    @Override
+    public Dimension2Coordinate decode(Chromosome<Dimension2Coordinate> chromosome) {
+        final BinaryChromosome<Dimension2Coordinate> binaryChromosome =
+                (BinaryChromosome<Dimension2Coordinate>) chromosome;
+        final long alleles = binaryChromosome.getRepresentation()[0];
+
+        long mask1 = ~(Long.MAX_VALUE << 12);
+        long mask2 = ~(Long.MAX_VALUE << 24) ^ mask1;
+
+        final double x = (alleles & mask1) / 100d;
+        final double y = ((alleles & mask2) >> 12) / 100d;
+
+        return new Dimension2Coordinate(x, y);
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/Dimension2FitnessFunction.java b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/Dimension2FitnessFunction.java
new file mode 100644
index 0000000..33e8f73
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/Dimension2FitnessFunction.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.examples.ga.mathfunctions.dimension2;
+
+import org.apache.commons.math4.ga.fitness.FitnessFunction;
+
+/**
+ * This class represents the mathematical fitness function for optimizing a 2
+ * dimension mathematical function.
+ */
+public class Dimension2FitnessFunction implements FitnessFunction<Dimension2Coordinate> {
+
+    /**
+     * Computes the fitness value based on the decoded chromosome.
+     * @param coordinate The {@link Dimension2Coordinate}
+     * @return the fitness value
+     */
+    @Override
+    public double compute(Dimension2Coordinate coordinate) {
+        return -Math.pow(Math.pow(coordinate.getX(), 2) + Math.pow(coordinate.getY(), 2), .25) *
+                (Math.pow(Math.sin(50 * Math.pow(Math.pow(coordinate.getX(), 2) + Math.pow(coordinate.getY(), 2), .1)),
+                        2) + 1);
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/Dimension2FunctionAdaptiveOptimizer.java b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/Dimension2FunctionAdaptiveOptimizer.java
new file mode 100644
index 0000000..6579dda
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/Dimension2FunctionAdaptiveOptimizer.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.examples.ga.mathfunctions.dimension2;
+
+import org.apache.commons.math4.examples.ga.mathfunctions.utils.Constants;
+import org.apache.commons.math4.ga.AdaptiveGeneticAlgorithm;
+import org.apache.commons.math4.ga.chromosome.BinaryChromosome;
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.convergence.StoppingCondition;
+import org.apache.commons.math4.ga.convergence.UnchangedBestFitness;
+import org.apache.commons.math4.ga.crossover.OnePointBinaryCrossover;
+import org.apache.commons.math4.ga.crossover.rategenerator.ConstantCrossoverRateGenerator;
+import org.apache.commons.math4.ga.listener.ConvergenceListenerRegistry;
+import org.apache.commons.math4.ga.listener.PopulationStatisticsLogger;
+import org.apache.commons.math4.ga.mutation.BinaryMutation;
+import org.apache.commons.math4.ga.mutation.rategenerator.AdaptiveLinearMutationRateGenerator;
+import org.apache.commons.math4.ga.population.ListPopulation;
+import org.apache.commons.math4.ga.population.Population;
+import org.apache.commons.math4.ga.selection.TournamentSelection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class represents an optimizer for a 2-dimensional math function using
+ * genetic algorithm.
+ */
+public class Dimension2FunctionAdaptiveOptimizer {
+
+    /** number of dimension. **/
+    private static final int DIMENSION = 2;
+
+    /** size of tournament. **/
+    private static final int TOURNAMENT_SIZE = 3;
+
+    /** instance of logger. **/
+    private Logger logger = LoggerFactory.getLogger(Dimension2FunctionAdaptiveOptimizer.class);
+
+    /**
+     * Optimizes the 2-dimension fitness function.
+     * @param args arguments
+     */
+    public static void main(String[] args) {
+        final Population<Dimension2Coordinate> initPopulation = getInitialPopulation();
+
+        final Dimension2FunctionAdaptiveOptimizer optimizer = new Dimension2FunctionAdaptiveOptimizer();
+
+        final ConvergenceListenerRegistry<Dimension2Coordinate> convergenceListenerRegistry =
+                ConvergenceListenerRegistry.getInstance();
+        convergenceListenerRegistry.addConvergenceListener(new PopulationStatisticsLogger<Dimension2Coordinate>());
+        convergenceListenerRegistry
+                .addConvergenceListener(new Dim2GraphPlotter("Adaptive Convergence Stats", "generation", "fitness"));
+
+        optimizer.optimize(initPopulation);
+    }
+
+    private void optimize(Population<Dimension2Coordinate> initial) {
+
+        // initialize a new genetic algorithm
+        final AdaptiveGeneticAlgorithm<Dimension2Coordinate> ga = new AdaptiveGeneticAlgorithm<>(
+                new OnePointBinaryCrossover<Dimension2Coordinate>(), new ConstantCrossoverRateGenerator<>(1),
+                new BinaryMutation<Dimension2Coordinate>(),
+                new AdaptiveLinearMutationRateGenerator<>(Constants.AVERAGE_MUTATION_RATE / 2,
+                        Constants.AVERAGE_MUTATION_RATE * 2),
+                new TournamentSelection<>(TOURNAMENT_SIZE));
+
+        // stopping condition
+        final StoppingCondition<Dimension2Coordinate> stopCond = new UnchangedBestFitness<>(
+                Constants.GENERATION_COUNT_WITH_UNCHANGED_BEST_FUTNESS);
+
+        // run the algorithm
+        final Population<Dimension2Coordinate> finalPopulation = ga.evolve(initial, stopCond);
+
+        // best chromosome from the final population
+        final Chromosome<Dimension2Coordinate> bestFinal = finalPopulation.getFittestChromosome();
+
+        logger.info("*********************************************");
+        logger.info("***********Optimization Result***************");
+
+        logger.info(bestFinal.toString());
+
+    }
+
+    /**
+     * Generates an initial population.
+     * @return initial population
+     */
+    private static Population<Dimension2Coordinate> getInitialPopulation() {
+        final Population<Dimension2Coordinate> population = new ListPopulation<>(
+                DIMENSION * Constants.POPULATION_SIZE_PER_DIMENSION);
+        final Dimension2FitnessFunction fitnessFunction = new Dimension2FitnessFunction();
+        final Dimension2Decoder decoder = new Dimension2Decoder();
+        for (int i = 0; i < DIMENSION * Constants.POPULATION_SIZE_PER_DIMENSION; i++) {
+            population.addChromosome(BinaryChromosome.<Dimension2Coordinate>randomChromosome(
+                    DIMENSION * Constants.CHROMOSOME_LENGTH_PER_DIMENSION, fitnessFunction, decoder));
+        }
+        return population;
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/Dimension2FunctionOptimizer.java b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/Dimension2FunctionOptimizer.java
new file mode 100644
index 0000000..1d6a3fa
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/Dimension2FunctionOptimizer.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.examples.ga.mathfunctions.dimension2;
+
+import org.apache.commons.math4.examples.ga.mathfunctions.utils.Constants;
+import org.apache.commons.math4.ga.GeneticAlgorithm;
+import org.apache.commons.math4.ga.chromosome.BinaryChromosome;
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.convergence.StoppingCondition;
+import org.apache.commons.math4.ga.convergence.UnchangedBestFitness;
+import org.apache.commons.math4.ga.crossover.OnePointBinaryCrossover;
+import org.apache.commons.math4.ga.listener.ConvergenceListenerRegistry;
+import org.apache.commons.math4.ga.listener.PopulationStatisticsLogger;
+import org.apache.commons.math4.ga.mutation.BinaryMutation;
+import org.apache.commons.math4.ga.population.ListPopulation;
+import org.apache.commons.math4.ga.population.Population;
+import org.apache.commons.math4.ga.selection.TournamentSelection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class represents an optimizer for a 2-dimensional math function using
+ * genetic algorithm.
+ */
+public class Dimension2FunctionOptimizer {
+
+    /** number of dimension. **/
+    private static final int DIMENSION = 2;
+
+    /** size of tournament. **/
+    private static final int TOURNAMENT_SIZE = 3;
+
+    /** instance of logger. **/
+    private Logger logger = LoggerFactory.getLogger(Dimension2FunctionAdaptiveOptimizer.class);
+
+    /**
+     * Optimizes the 2-dimension fitness function.
+     * @param args arguments
+     */
+    public static void main(String[] args) {
+        final Population<Dimension2Coordinate> initPopulation = getInitialPopulation();
+
+        final Dimension2FunctionOptimizer optimizer = new Dimension2FunctionOptimizer();
+
+        final ConvergenceListenerRegistry<Dimension2Coordinate> convergenceListenerRegistry =
+                ConvergenceListenerRegistry.getInstance();
+        convergenceListenerRegistry.addConvergenceListener(new PopulationStatisticsLogger<Dimension2Coordinate>());
+        convergenceListenerRegistry
+                .addConvergenceListener(new Dim2GraphPlotter("Convergence Stats", "generation", "fitness"));
+
+        optimizer.optimize(initPopulation);
+    }
+
+    /**
+     * Optimizes the population.
+     * @param initial The {@link Population}
+     */
+    public void optimize(Population<Dimension2Coordinate> initial) {
+
+        // initialize a new genetic algorithm
+        final GeneticAlgorithm<Dimension2Coordinate> ga = new GeneticAlgorithm<>(
+                new OnePointBinaryCrossover<Dimension2Coordinate>(), Constants.CROSSOVER_RATE,
+                new BinaryMutation<Dimension2Coordinate>(), Constants.AVERAGE_MUTATION_RATE,
+                new TournamentSelection<Dimension2Coordinate>(TOURNAMENT_SIZE), Constants.ELITISM_RATE);
+
+        // stopping condition
+        final StoppingCondition<Dimension2Coordinate> stopCond = new UnchangedBestFitness<>(
+                Constants.GENERATION_COUNT_WITH_UNCHANGED_BEST_FUTNESS);
+
+        // run the algorithm
+        final Population<Dimension2Coordinate> finalPopulation = ga.evolve(initial, stopCond);
+
+        // best chromosome from the final population
+        final Chromosome<Dimension2Coordinate> bestFinal = finalPopulation.getFittestChromosome();
+
+        logger.info("*********************************************");
+        logger.info("***********Optimization Result***************");
+
+        logger.info(bestFinal.toString());
+
+    }
+
+    /**
+     * Generates an initial population.
+     * @return initial population
+     */
+    private static Population<Dimension2Coordinate> getInitialPopulation() {
+        final Population<Dimension2Coordinate> population = new ListPopulation<>(
+                DIMENSION * Constants.POPULATION_SIZE_PER_DIMENSION);
+        final Dimension2FitnessFunction fitnessFunction = new Dimension2FitnessFunction();
+        final Dimension2Decoder decoder = new Dimension2Decoder();
+        for (int i = 0; i < DIMENSION * Constants.POPULATION_SIZE_PER_DIMENSION; i++) {
+            population.addChromosome(BinaryChromosome.<Dimension2Coordinate>randomChromosome(
+                    DIMENSION * Constants.CHROMOSOME_LENGTH_PER_DIMENSION, fitnessFunction, decoder));
+        }
+        return population;
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/legacy/Dimension2FunctionOptimizerLegacy.java b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/legacy/Dimension2FunctionOptimizerLegacy.java
new file mode 100644
index 0000000..b523d41
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/legacy/Dimension2FunctionOptimizerLegacy.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.examples.ga.mathfunctions.dimension2.legacy;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+
+import org.apache.commons.math3.genetics.BinaryChromosome;
+import org.apache.commons.math3.genetics.BinaryMutation;
+import org.apache.commons.math3.genetics.Chromosome;
+import org.apache.commons.math3.genetics.ElitisticListPopulation;
+import org.apache.commons.math3.genetics.GeneticAlgorithm;
+import org.apache.commons.math3.genetics.OnePointCrossover;
+import org.apache.commons.math3.genetics.Population;
+import org.apache.commons.math3.genetics.StoppingCondition;
+import org.apache.commons.math3.genetics.TournamentSelection;
+import org.apache.commons.math4.examples.ga.mathfunctions.utils.Constants;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+
+/**
+ * This class represents an optimizer for a 2-dimensional math function using
+ * the legacy genetic algorithm.
+ */
+public class Dimension2FunctionOptimizerLegacy {
+
+    /** number of dimension. **/
+    private static final int DIMENSION = 2;
+
+    /** size of tournament. **/
+    private static final int TOURNAMENT_SIZE = 3;
+
+    /**
+     * Optimizes the 2-dimensional fitness function.
+     * @param args arguments
+     */
+    public static void main(String[] args) {
+        final Population initPopulation = getInitialPopulation();
+        final Dimension2FunctionOptimizerLegacy simulation = new Dimension2FunctionOptimizerLegacy();
+
+        simulation.optimize(initPopulation);
+    }
+
+    /**
+     * Optimizes the initial population using legacy genetic algorithm.
+     * @param initial initial {@link Population}
+     */
+    public void optimize(Population initial) {
+
+        // initialize a new genetic algorithm
+        final GeneticAlgorithm geneticAlgorithm = new GeneticAlgorithm(new OnePointCrossover<>(),
+                Constants.CROSSOVER_RATE, new BinaryMutation(), Constants.AVERAGE_MUTATION_RATE,
+                new TournamentSelection(TOURNAMENT_SIZE));
+
+        // stopping condition
+        final StoppingCondition stopCond = new UnchangedBestFitness(
+                Constants.GENERATION_COUNT_WITH_UNCHANGED_BEST_FUTNESS);
+
+        // run the algorithm
+        final Population finalPopulation = geneticAlgorithm.evolve(initial, stopCond);
+
+        // best chromosome from the final population
+        final Chromosome bestFinal = finalPopulation.getFittestChromosome();
+
+        try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out, Constants.ENCODING))) {
+            writer.write("*********************************************");
+            writer.newLine();
+            writer.write("***********Optimization Result***************");
+            writer.write(bestFinal.toString());
+        } catch (IOException e) {
+            throw new GeneticException(e);
+        }
+    }
+
+    /**
+     * Generates the initial population.
+     * @return initial population
+     */
+    private static Population getInitialPopulation() {
+        final Population population = new ElitisticListPopulation(Constants.POPULATION_SIZE_PER_DIMENSION,
+                Constants.ELITISM_RATE);
+        for (int i = 0; i < Constants.POPULATION_SIZE_PER_DIMENSION; i++) {
+            population.addChromosome(new LegacyBinaryChromosome(BinaryChromosome
+                    .randomBinaryRepresentation(DIMENSION * Constants.CHROMOSOME_LENGTH_PER_DIMENSION)));
+        }
+        return population;
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/legacy/LegacyBinaryChromosome.java b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/legacy/LegacyBinaryChromosome.java
new file mode 100644
index 0000000..66c4615
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/legacy/LegacyBinaryChromosome.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.examples.ga.mathfunctions.dimension2.legacy;
+
+import java.util.List;
+
+import org.apache.commons.math3.genetics.AbstractListChromosome;
+import org.apache.commons.math3.genetics.BinaryChromosome;
+
+/**
+ * A representation of concrete binary chromosome.
+ */
+public class LegacyBinaryChromosome extends BinaryChromosome {
+
+    /**
+     * constructor.
+     * @param representation the internal representation
+     */
+    public LegacyBinaryChromosome(List<Integer> representation) {
+        super(representation);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public double fitness() {
+        final List<Integer> alleles = getRepresentation();
+
+        final StringBuilder allelesStr = new StringBuilder();
+        for (Integer allele : alleles) {
+            allelesStr.append(Integer.toBinaryString(allele));
+        }
+
+        final double x = Integer.parseInt(allelesStr.substring(0, 12), 2) / 100.0;
+        final double y = Integer.parseInt(allelesStr.substring(12, 24), 2) / 100.0;
+
+        return -Math.pow(Math.pow(x, 2) + Math.pow(y, 2), .25) *
+                (Math.pow(Math.sin(50 * Math.pow(Math.pow(x, 2) + Math.pow(y, 2), .1)), 2) + 1);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public AbstractListChromosome<Integer> newFixedLengthChromosome(List<Integer> chromosomeRepresentation) {
+        return new LegacyBinaryChromosome(chromosomeRepresentation);
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/legacy/UnchangedBestFitness.java b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/legacy/UnchangedBestFitness.java
new file mode 100644
index 0000000..8800f39
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/legacy/UnchangedBestFitness.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.examples.ga.mathfunctions.dimension2.legacy;
+
+import org.apache.commons.math3.genetics.Population;
+import org.apache.commons.math3.genetics.StoppingCondition;
+
+/**
+ * This class represents the stopping condition based on unchanged best fitness.
+ */
+public class UnchangedBestFitness implements StoppingCondition {
+
+    /** last best fitness. **/
+    private double lastBestFitness = Double.MIN_VALUE;
+
+    /** maximum number of generations evolved with unchanged best fitness. **/
+    private final int maxGenerationsWithUnchangedBestFitness;
+
+    /** generations having unchanged best fitness. **/
+    private int generationsHavingUnchangedBestFitness;
+
+    /**
+     * constructor.
+     * @param maxGenerationsWithUnchangedAverageFitness maximum number of
+     *                                                  generations evolved with
+     *                                                  unchanged best fitness
+     */
+    public UnchangedBestFitness(final int maxGenerationsWithUnchangedAverageFitness) {
+        this.maxGenerationsWithUnchangedBestFitness = maxGenerationsWithUnchangedAverageFitness;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean isSatisfied(Population population) {
+        final double currentBestFitness = population.getFittestChromosome().getFitness();
+
+        if (lastBestFitness == currentBestFitness) {
+            this.generationsHavingUnchangedBestFitness++;
+            if (generationsHavingUnchangedBestFitness == maxGenerationsWithUnchangedBestFitness) {
+                return true;
+            }
+        } else {
+            this.generationsHavingUnchangedBestFitness = 0;
+            lastBestFitness = currentBestFitness;
+        }
+
+        return false;
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/legacy/package-info.java b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/legacy/package-info.java
new file mode 100644
index 0000000..7965791
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/legacy/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.examples.ga.mathfunctions.dimension2.legacy;
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/package-info.java b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/package-info.java
new file mode 100644
index 0000000..432651f
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimension2/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.examples.ga.mathfunctions.dimension2;
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimensionN/DimNGraphPlotter.java b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimensionN/DimNGraphPlotter.java
new file mode 100644
index 0000000..52571e3
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimensionN/DimNGraphPlotter.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.examples.ga.mathfunctions.dimensionN;
+
+import java.awt.BorderLayout;
+import java.util.List;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+import org.apache.commons.math4.ga.internal.stats.PopulationStatisticalSummaryImpl;
+import org.apache.commons.math4.ga.listener.ConvergenceListener;
+import org.apache.commons.math4.ga.population.Population;
+import org.apache.commons.math4.ga.stats.PopulationStatisticalSummary;
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.ChartPanel;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
+import org.jfree.data.xy.XYSeries;
+import org.jfree.data.xy.XYSeriesCollection;
+
+/**
+ * This class represents the graph plotter during optimization.
+ */
+public class DimNGraphPlotter extends JFrame implements ConvergenceListener<DimensionNCoordinate> {
+
+    /**
+     * Generated serialversionId.
+     */
+    private static final long serialVersionUID = -5683904006424006584L;
+
+    /** collection of 2-D series. **/
+    private final XYSeriesCollection dataset = new XYSeriesCollection();
+
+    /**
+     * constructor.
+     * @param plotSubject subject of plot
+     * @param xAxisLabel  x axis label
+     * @param yAxisLabel  y axis label
+     */
+    public DimNGraphPlotter(String plotSubject, String xAxisLabel, String yAxisLabel) {
+        super(plotSubject);
+
+        final JPanel chartPanel = createChartPanel(plotSubject, xAxisLabel, yAxisLabel);
+        add(chartPanel, BorderLayout.CENTER);
+
+        setSize(640, 480);
+        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+        setLocationRelativeTo(null);
+
+        setVisible(true);
+    }
+
+    /**
+     * Adds data point to graph.
+     * @param graphName  name of graph
+     * @param generation generation, to be plotted along x axis
+     * @param value      value, to be plotted along y axis
+     */
+    private void addDataPoint(String graphName, int generation, double value) {
+        XYSeries series = null;
+
+        if (!containsGraph(graphName)) {
+            series = new XYSeries(graphName);
+            dataset.addSeries(series);
+        } else {
+            series = dataset.getSeries(graphName);
+        }
+        series.add(generation, value);
+
+        setVisible(true);
+    }
+
+    /**
+     * Checks if the graph with the given name already exists.
+     * @param graphName name of the graph
+     * @return true/false
+     */
+    @SuppressWarnings("unchecked")
+    private boolean containsGraph(String graphName) {
+        final List<XYSeries> seriesList = dataset.getSeries();
+        if (seriesList == null || seriesList.isEmpty()) {
+            return false;
+        }
+        for (XYSeries series : seriesList) {
+            if (series.getKey().compareTo(graphName) == 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Creates chart panel.
+     * @param chartTitle chart title
+     * @param xAxisLabel x axis label
+     * @param yAxisLabel y axis label
+     * @return panel
+     */
+    private JPanel createChartPanel(String chartTitle, String xAxisLabel, String yAxisLabel) {
+
+        final boolean showLegend = true;
+        final boolean createURL = false;
+        final boolean createTooltip = false;
+
+        final JFreeChart chart = ChartFactory.createXYLineChart(chartTitle, xAxisLabel, yAxisLabel, dataset,
+                PlotOrientation.VERTICAL, showLegend, createTooltip, createURL);
+        final XYPlot plot = chart.getXYPlot();
+        final XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
+
+        plot.setRenderer(renderer);
+
+        return new ChartPanel(chart);
+
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void notify(int generation, Population<DimensionNCoordinate> population) {
+        PopulationStatisticalSummary<DimensionNCoordinate> populationStatisticalSummary =
+                new PopulationStatisticalSummaryImpl<>(population);
+        this.addDataPoint("Average", generation, populationStatisticalSummary.getMeanFitness());
+        this.addDataPoint("Best", generation, populationStatisticalSummary.getMaxFitness());
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimensionN/DimensionNCoordinate.java b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimensionN/DimensionNCoordinate.java
new file mode 100644
index 0000000..98a31bc
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimensionN/DimensionNCoordinate.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.examples.ga.mathfunctions.dimensionN;
+
+import java.util.List;
+
+/**
+ * This class represents the coordinate of the problem domain i.e. the phenotype
+ * of chromosome.
+ */
+public class DimensionNCoordinate {
+
+    /** coordinate of all dimensions. **/
+    private final List<Double> values;
+
+    /**
+     * constructor.
+     * @param values coordinates of all dimensions.
+     */
+    public DimensionNCoordinate(List<Double> values) {
+        this.values = values;
+    }
+
+    /**
+     * Returns the values of all coordinates.
+     * @return values of coordinates
+     */
+    public List<Double> getValues() {
+        return values;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        return "Coordinate [values=" + values + "]";
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimensionN/DimensionNDecoder.java b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimensionN/DimensionNDecoder.java
new file mode 100644
index 0000000..9579815
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimensionN/DimensionNDecoder.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.examples.ga.mathfunctions.dimensionN;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.math4.ga.chromosome.BinaryChromosome;
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.decoder.Decoder;
+
+/**
+ * Decoder to convert chromosome's binary genotype to phenotype
+ * {@link DimensionNCoordinate}.
+ */
+public class DimensionNDecoder implements Decoder<DimensionNCoordinate> {
+
+    /**
+     * decode the binary representation of chromosome to
+     * {@link DimensionNCoordinate}.
+     * @param chromosome The {@link Chromosome}
+     */
+    @Override
+    public DimensionNCoordinate decode(Chromosome<DimensionNCoordinate> chromosome) {
+        final BinaryChromosome<DimensionNCoordinate> binaryChromosome =
+                (BinaryChromosome<DimensionNCoordinate>) chromosome;
+        final long length = binaryChromosome.getLength();
+        final List<Double> coordinates = new ArrayList<>();
+
+        for (int i = 0; i < length; i += 12) {
+            final String dimensionStrValue = binaryChromosome.getStringRepresentation(i, i + 12);
+            coordinates.add(Integer.parseUnsignedInt(dimensionStrValue, 2) / 100d);
+        }
+
+        return new DimensionNCoordinate(coordinates);
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimensionN/DimensionNFitnessFunction.java b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimensionN/DimensionNFitnessFunction.java
new file mode 100644
index 0000000..1c0d7db
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimensionN/DimensionNFitnessFunction.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.examples.ga.mathfunctions.dimensionN;
+
+import org.apache.commons.math4.ga.fitness.FitnessFunction;
+
+/**
+ * This class represents the mathematical fitness function for optimizing a 2
+ * dimension mathematical function.
+ */
+public class DimensionNFitnessFunction implements FitnessFunction<DimensionNCoordinate> {
+
+    /**
+     * Computes the fitness value based on the decoded chromosome.
+     * @param coordinate The {@link DimensionNCoordinate}
+     * @return the fitness value
+     */
+    @Override
+    public double compute(DimensionNCoordinate coordinate) {
+        double sumOfSquare = 0.0;
+        for (Double value : coordinate.getValues()) {
+            sumOfSquare += Math.pow(value, 2);
+        }
+        return -Math.pow(sumOfSquare, .25) * (Math.pow(Math.sin(50 * Math.pow(sumOfSquare, .1)), 2) + 1);
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimensionN/DimensionNFunctionAdaptiveOptimizer.java b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimensionN/DimensionNFunctionAdaptiveOptimizer.java
new file mode 100644
index 0000000..dee317a
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimensionN/DimensionNFunctionAdaptiveOptimizer.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.examples.ga.mathfunctions.dimensionN;
+
+import org.apache.commons.math4.examples.ga.mathfunctions.utils.Constants;
+import org.apache.commons.math4.ga.AbstractGeneticAlgorithm;
+import org.apache.commons.math4.ga.AdaptiveGeneticAlgorithm;
+import org.apache.commons.math4.ga.chromosome.BinaryChromosome;
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.convergence.StoppingCondition;
+import org.apache.commons.math4.ga.convergence.UnchangedBestFitness;
+import org.apache.commons.math4.ga.crossover.OnePointBinaryCrossover;
+import org.apache.commons.math4.ga.crossover.rategenerator.AdaptiveLinearMaximumRankBasedCrossoverRateGenerator;
+import org.apache.commons.math4.ga.listener.ConvergenceListenerRegistry;
+import org.apache.commons.math4.ga.listener.PopulationStatisticsLogger;
+import org.apache.commons.math4.ga.mutation.BinaryMutation;
+import org.apache.commons.math4.ga.mutation.rategenerator.AdaptiveLinearMutationRateGenerator;
+import org.apache.commons.math4.ga.population.ListPopulation;
+import org.apache.commons.math4.ga.population.Population;
+import org.apache.commons.math4.ga.selection.TournamentSelection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class represents an optimizer for a 2-dimensional math function using
+ * genetic algorithm.
+ */
+public class DimensionNFunctionAdaptiveOptimizer {
+
+    /** number of dimension. **/
+    private static final int DIMENSION = 10;
+
+    /** size of tournament. **/
+    private static final int TOURNAMENT_SIZE = 4;
+
+    /** instance of logger. **/
+    private Logger logger = LoggerFactory.getLogger(DimensionNFunctionOptimizer.class);
+
+    /**
+     * Optimizes the 2-dimension fitness function.
+     * @param args arguments
+     */
+    public static void main(String[] args) {
+        final Population<DimensionNCoordinate> initPopulation = getInitialPopulation();
+
+        final DimensionNFunctionAdaptiveOptimizer optimizer = new DimensionNFunctionAdaptiveOptimizer();
+
+        final ConvergenceListenerRegistry<DimensionNCoordinate> convergenceListenerRegistry =
+                ConvergenceListenerRegistry.getInstance();
+        convergenceListenerRegistry.addConvergenceListener(new PopulationStatisticsLogger<DimensionNCoordinate>());
+        convergenceListenerRegistry
+                .addConvergenceListener(new DimNGraphPlotter("Adaptive Convergence Stats", "generation", "fitness"));
+
+        optimizer.optimize(initPopulation);
+    }
+
+    private void optimize(Population<DimensionNCoordinate> initial) {
+
+        // initialize a new genetic algorithm
+        final AbstractGeneticAlgorithm<DimensionNCoordinate> ga = new AdaptiveGeneticAlgorithm<DimensionNCoordinate>(
+                new OnePointBinaryCrossover<DimensionNCoordinate>(),
+                new AdaptiveLinearMaximumRankBasedCrossoverRateGenerator<>(Constants.CROSSOVER_RATE / 2,
+                        Constants.CROSSOVER_RATE),
+                new BinaryMutation<>(), new AdaptiveLinearMutationRateGenerator<>(0, Constants.AVERAGE_MUTATION_RATE),
+                new TournamentSelection<>(TOURNAMENT_SIZE), Constants.ELITISM_RATE);
+
+        // stopping condition
+        final StoppingCondition<DimensionNCoordinate> stopCond = new UnchangedBestFitness<>(
+                Constants.GENERATION_COUNT_WITH_UNCHANGED_BEST_FUTNESS);
+
+        // run the algorithm
+        final Population<DimensionNCoordinate> finalPopulation = ga.evolve(initial, stopCond);
+
+        // best chromosome from the final population
+        final Chromosome<DimensionNCoordinate> bestFinal = finalPopulation.getFittestChromosome();
+
+        logger.info("*********************************************");
+        logger.info("***********Optimization Result***************");
+        logger.info(bestFinal.toString());
+
+    }
+
+    /**
+     * Generates an initial population.
+     * @return initial population
+     */
+    private static Population<DimensionNCoordinate> getInitialPopulation() {
+        final Population<DimensionNCoordinate> population = new ListPopulation<>(
+                DIMENSION * Constants.POPULATION_SIZE_PER_DIMENSION);
+        final DimensionNFitnessFunction fitnessFunction = new DimensionNFitnessFunction();
+        final DimensionNDecoder decoder = new DimensionNDecoder();
+        for (int i = 0; i < DIMENSION * Constants.POPULATION_SIZE_PER_DIMENSION; i++) {
+            population.addChromosome(BinaryChromosome.<DimensionNCoordinate>randomChromosome(
+                    DIMENSION * Constants.CHROMOSOME_LENGTH_PER_DIMENSION, fitnessFunction, decoder));
+        }
+        return population;
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimensionN/DimensionNFunctionOptimizer.java b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimensionN/DimensionNFunctionOptimizer.java
new file mode 100644
index 0000000..5791b05
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimensionN/DimensionNFunctionOptimizer.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.examples.ga.mathfunctions.dimensionN;
+
+import org.apache.commons.math4.examples.ga.mathfunctions.utils.Constants;
+import org.apache.commons.math4.ga.GeneticAlgorithm;
+import org.apache.commons.math4.ga.chromosome.BinaryChromosome;
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.convergence.StoppingCondition;
+import org.apache.commons.math4.ga.convergence.UnchangedBestFitness;
+import org.apache.commons.math4.ga.crossover.OnePointBinaryCrossover;
+import org.apache.commons.math4.ga.listener.ConvergenceListenerRegistry;
+import org.apache.commons.math4.ga.listener.PopulationStatisticsLogger;
+import org.apache.commons.math4.ga.mutation.BinaryMutation;
+import org.apache.commons.math4.ga.population.ListPopulation;
+import org.apache.commons.math4.ga.population.Population;
+import org.apache.commons.math4.ga.selection.TournamentSelection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class represents an optimizer for a 2-dimensional math function using
+ * genetic algorithm.
+ */
+public class DimensionNFunctionOptimizer {
+
+    /** number of dimension. **/
+    private static final int DIMENSION = 10;
+
+    /** size of tournament. **/
+    private static final int TOURNAMENT_SIZE = 4;
+
+    /** instance of logger. **/
+    private Logger logger = LoggerFactory.getLogger(DimensionNFunctionOptimizer.class);
+
+    /**
+     * Optimizes the 2-dimension fitness function.
+     * @param args arguments
+     */
+    public static void main(String[] args) {
+        final Population<DimensionNCoordinate> initPopulation = getInitialPopulation();
+
+        final DimensionNFunctionOptimizer optimizer = new DimensionNFunctionOptimizer();
+
+        final ConvergenceListenerRegistry<DimensionNCoordinate> convergenceListenerRegistry =
+                ConvergenceListenerRegistry.getInstance();
+        convergenceListenerRegistry.addConvergenceListener(new PopulationStatisticsLogger<DimensionNCoordinate>());
+        convergenceListenerRegistry
+                .addConvergenceListener(new DimNGraphPlotter("Convergence Stats", "generation", "fitness"));
+
+        optimizer.optimize(initPopulation);
+    }
+
+    /**
+     * Optimizes the population.
+     * @param initial The {@link Population}
+     */
+    public void optimize(Population<DimensionNCoordinate> initial) {
+
+        // initialize a new genetic algorithm
+        final GeneticAlgorithm<DimensionNCoordinate> ga = new GeneticAlgorithm<>(
+                new OnePointBinaryCrossover<DimensionNCoordinate>(), Constants.CROSSOVER_RATE,
+                new BinaryMutation<DimensionNCoordinate>(), Constants.AVERAGE_MUTATION_RATE,
+                new TournamentSelection<>(TOURNAMENT_SIZE), Constants.ELITISM_RATE);
+
+        // stopping condition
+        final StoppingCondition<DimensionNCoordinate> stopCond = new UnchangedBestFitness<>(
+                Constants.GENERATION_COUNT_WITH_UNCHANGED_BEST_FUTNESS);
+
+        // run the algorithm
+        final Population<DimensionNCoordinate> finalPopulation = ga.evolve(initial, stopCond);
+
+        // best chromosome from the final population
+        final Chromosome<DimensionNCoordinate> bestFinal = finalPopulation.getFittestChromosome();
+
+        logger.info("*********************************************");
+        logger.info("***********Optimization Result***************");
+        logger.info(bestFinal.toString());
+
+    }
+
+    /**
+     * Generates an initial population.
+     * @return initial population
+     */
+    private static Population<DimensionNCoordinate> getInitialPopulation() {
+        final Population<DimensionNCoordinate> population = new ListPopulation<>(
+                DIMENSION * Constants.POPULATION_SIZE_PER_DIMENSION);
+        final DimensionNFitnessFunction fitnessFunction = new DimensionNFitnessFunction();
+        final DimensionNDecoder decoder = new DimensionNDecoder();
+        for (int i = 0; i < DIMENSION * Constants.POPULATION_SIZE_PER_DIMENSION; i++) {
+            population.addChromosome(BinaryChromosome.<DimensionNCoordinate>randomChromosome(
+                    DIMENSION * Constants.CHROMOSOME_LENGTH_PER_DIMENSION, fitnessFunction, decoder));
+        }
+        return population;
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimensionN/package-info.java b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimensionN/package-info.java
new file mode 100644
index 0000000..6a15fed
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/dimensionN/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.examples.ga.mathfunctions.dimensionN;
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/utils/Constants.java b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/utils/Constants.java
new file mode 100644
index 0000000..1389c75
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/utils/Constants.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.examples.ga.mathfunctions.utils;
+
+/**
+ * This abstraction maintains constants used by this module.
+ */
+public final class Constants {
+
+    /** size of population. **/
+    public static final int POPULATION_SIZE_PER_DIMENSION = 10;
+
+    /** size of tournament. **/
+    public static final int TOURNAMENT_SIZE_PER_DIMENSION = 2;
+
+    /** length of chromosome. **/
+    public static final int CHROMOSOME_LENGTH_PER_DIMENSION = 12;
+
+    /** rate of crossover. **/
+    public static final double CROSSOVER_RATE = 1.0;
+
+    /** rate of elitism. **/
+    public static final double ELITISM_RATE = 0.25;
+
+    /** rate of mutation. **/
+    public static final double AVERAGE_MUTATION_RATE = 0.05;
+
+    /** number of generations with unchanged best fitness. **/
+    public static final int GENERATION_COUNT_WITH_UNCHANGED_BEST_FUTNESS = 50;
+
+    /** encoding for console logger. **/
+    public static final String ENCODING = "UTF-8";
+
+    /**
+     * constructor.
+     */
+    private Constants() {
+
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/utils/package-info.java b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/utils/package-info.java
new file mode 100644
index 0000000..360a1c3
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/src/main/java/org/apache/commons/math4/examples/ga/mathfunctions/utils/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.examples.ga.mathfunctions.utils;
diff --git a/commons-math-examples/examples-ga/examples-ga-tsp/pom.xml b/commons-math-examples/examples-ga/examples-ga-tsp/pom.xml
new file mode 100644
index 0000000..b4a7811
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-tsp/pom.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor 
+    license agreements. See the NOTICE file distributed with this work for additional 
+    information regarding copyright ownership. The ASF licenses this file to 
+    You under the Apache License, Version 2.0 (the "License"); you may not use 
+    this file except in compliance with the License. You may obtain a copy of 
+    the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required 
+    by applicable law or agreed to in writing, software distributed under the 
+    License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
+    OF ANY KIND, either express or implied. See the License for the specific 
+    language governing permissions and limitations under the License. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>examples-ga</artifactId>
+        <version>4.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>examples-ga-tsp</artifactId>
+
+    <properties>
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
+
+        <!-- OSGi -->
+        <commons.osgi.symbolicName>org.apache.commons.math4.examples.ga.tsp</commons.osgi.symbolicName>
+        <commons.osgi.export>org.apache.commons.math4.examples.ga.tsp</commons.osgi.export>
+        <!-- Java 9+ -->
+        <commons.automatic.module.name>org.apache.commons.math4.examples.ga.tsp</commons.automatic.module.name>
+        <!-- Workaround to avoid duplicating config files. -->
+        <math.parent.dir>${basedir}/../../..</math.parent.dir>
+
+        <uberjar.name>examples-ga-mathfunctions</uberjar.name>
+        <project.mainClass>org.apache.commons.math4.examples.ga.tsp.TSPOptimizer</project.mainClass>
+        <slf4jVersion>1.7.32</slf4jVersion>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-csv</artifactId>
+            <version>1.9.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <version>${slf4jVersion}</version>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/TSPFitnessFunction.java b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/TSPFitnessFunction.java
new file mode 100644
index 0000000..9b06312
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/TSPFitnessFunction.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.examples.ga.tsp;
+
+import java.util.List;
+
+
+import org.apache.commons.math4.examples.ga.tsp.commons.City;
+import org.apache.commons.math4.examples.ga.tsp.commons.DistanceMatrix;
+import org.apache.commons.math4.ga.fitness.FitnessFunction;
+
+/**
+ * This class represents the fitness function for tsp.
+ */
+public class TSPFitnessFunction implements FitnessFunction<List<City>> {
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public double compute(List<City> cities) {
+        double totalDistance = 0.0;
+        int index1 = 0;
+        int index2 = 0;
+        for (int i = 0; i < cities.size(); i++) {
+            index1 = i;
+            index2 = (i == cities.size() - 1) ? 0 : i + 1;
+            totalDistance += calculateNodeDistance(cities.get(index1), cities.get(index2));
+        }
+        return -totalDistance;
+    }
+
+    private double calculateNodeDistance(City node1, City node2) {
+        final DistanceMatrix distanceMatrix = DistanceMatrix.getInstance();
+        return distanceMatrix.getDistance(node1, node2);
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/TSPOptimizer.java b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/TSPOptimizer.java
new file mode 100644
index 0000000..21833ef
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/TSPOptimizer.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.examples.ga.tsp;
+
+import java.util.List;
+
+import org.apache.commons.math4.examples.ga.tsp.commons.City;
+import org.apache.commons.math4.examples.ga.tsp.utils.Constants;
+import org.apache.commons.math4.examples.ga.tsp.utils.GraphPlotter;
+import org.apache.commons.math4.ga.GeneticAlgorithm;
+import org.apache.commons.math4.ga.chromosome.RealValuedChromosome;
+import org.apache.commons.math4.ga.convergence.StoppingCondition;
+import org.apache.commons.math4.ga.convergence.UnchangedBestFitness;
+import org.apache.commons.math4.ga.crossover.OnePointCrossover;
+import org.apache.commons.math4.ga.decoder.RandomKeyDecoder;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.apache.commons.math4.ga.listener.ConvergenceListenerRegistry;
+import org.apache.commons.math4.ga.listener.PopulationStatisticsLogger;
+import org.apache.commons.math4.ga.mutation.RealValuedMutation;
+import org.apache.commons.math4.ga.population.ListPopulation;
+import org.apache.commons.math4.ga.population.Population;
+import org.apache.commons.math4.ga.selection.TournamentSelection;
+import org.apache.commons.math4.ga.utils.ChromosomeRepresentationUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class represents the optimizer for traveling salesman problem.
+ */
+public class TSPOptimizer {
+
+    /** instance of logger. **/
+    private Logger logger = LoggerFactory.getLogger(TSPOptimizer.class);
+
+    /**
+     * Main method to initiate the optimization process.
+     * @param args arguments
+     */
+    public static void main(String[] args) {
+        try {
+            final Population<List<City>> initPopulation = getInitialPopulation(Constants.CITIES);
+
+            final TSPOptimizer optimizer = new TSPOptimizer();
+
+            final ConvergenceListenerRegistry<List<City>> convergenceListenerRegistry = ConvergenceListenerRegistry
+                    .getInstance();
+            convergenceListenerRegistry.addConvergenceListener(new PopulationStatisticsLogger<>());
+            convergenceListenerRegistry
+                    .addConvergenceListener(new GraphPlotter("Convergence", "generation", "total-distance"));
+
+            optimizer.optimizeSGA(initPopulation, Constants.CITIES);
+
+            Thread.sleep(5000);
+
+        } catch (InterruptedException e) {
+            throw new GeneticException(e);
+        }
+    }
+
+    /**
+     * Optimizes the tsp problem.
+     * @param initial initial population
+     * @param cities  cities
+     */
+    public void optimizeSGA(Population<List<City>> initial, List<City> cities) {
+
+        // initialize a new genetic algorithm
+        final GeneticAlgorithm<List<City>> ga = new GeneticAlgorithm<>(new OnePointCrossover<Integer, List<City>>(),
+                Constants.CROSSOVER_RATE, new RealValuedMutation<List<City>>(), Constants.AVERAGE_MUTATION_RATE,
+                new TournamentSelection<List<City>>(Constants.TOURNAMENT_SIZE));
+
+        // stopping condition
+        final StoppingCondition<List<City>> stopCond = new UnchangedBestFitness<>(
+                Constants.GENERATION_COUNT_WITH_UNCHANGED_BEST_FUTNESS);
+
+        // run the algorithm
+        final Population<List<City>> finalPopulation = ga.evolve(initial, stopCond);
+
+        // best chromosome from the final population
+        final RealValuedChromosome<List<City>> bestFinal = (RealValuedChromosome<List<City>>) finalPopulation
+                .getFittestChromosome();
+
+        logger.info("*********************************************");
+        logger.info("***********Optimization Result***************");
+
+        logger.info(bestFinal.decode().toString());
+
+    }
+
+    private static Population<List<City>> getInitialPopulation(List<City> cities) {
+        final Population<List<City>> simulationPopulation = new ListPopulation<>(Constants.POPULATION_SIZE);
+
+        for (int i = 0; i < Constants.POPULATION_SIZE; i++) {
+            simulationPopulation.addChromosome(new RealValuedChromosome<>(
+                    ChromosomeRepresentationUtils.randomPermutation(Constants.CHROMOSOME_LENGTH),
+                    new TSPFitnessFunction(), new RandomKeyDecoder<City>(cities)));
+        }
+
+        return simulationPopulation;
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/commons/City.java b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/commons/City.java
new file mode 100644
index 0000000..7a6d8d1
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/commons/City.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.examples.ga.tsp.commons;
+
+/**
+ * This class represents a city with location coordinate.
+ */
+public final class City {
+
+    /** index of city. **/
+    private final int index;
+
+    /** x coordinate. **/
+    private final double x;
+
+    /** y coordinate. **/
+    private final double y;
+
+    /**
+     * constructor.
+     * @param index index of city
+     * @param x     x coordinate
+     * @param y     y coordinate
+     */
+    public City(int index, double x, double y) {
+        this.index = index;
+        this.x = x;
+        this.y = y;
+    }
+
+    /**
+     * Returns city index.
+     * @return city index
+     */
+    public int getIndex() {
+        return index;
+    }
+
+    /**
+     * Returns x coordinate.
+     * @return x coordinate
+     */
+    public double getX() {
+        return x;
+    }
+
+    /**
+     * Returns y coordinate.
+     * @return y coordinate
+     */
+    public double getY() {
+        return y;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        return "Node [index=" + index + ", x=" + x + ", y=" + y + "]";
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/commons/DistanceMatrix.java b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/commons/DistanceMatrix.java
new file mode 100644
index 0000000..175c7c6
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/commons/DistanceMatrix.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.examples.ga.tsp.commons;
+
+import java.util.List;
+
+import org.apache.commons.math4.examples.ga.tsp.utils.Constants;
+
+/**
+ * This class represents the distance matrix between cities.
+ */
+public final class DistanceMatrix {
+
+    /** instance of the class. **/
+    private static final DistanceMatrix INSTANCE = new DistanceMatrix();
+
+    /** distances between cities. **/
+    private double[][] distances;
+
+    private DistanceMatrix() {
+        initialize(Constants.CITIES);
+    }
+
+    /**
+     * Returns distances between two cities.
+     * @param city1 first city
+     * @param city2 second city
+     * @return distance
+     */
+    public double getDistance(City city1, City city2) {
+        return distances[city1.getIndex() - 1][city2.getIndex() - 1];
+    }
+
+    /**
+     * Initializes the distance matrix.
+     * @param cities list of cities
+     */
+    private void initialize(List<City> cities) {
+        final int len = cities.size();
+        this.distances = new double[len][len];
+        for (int i = 0; i < len; i++) {
+            for (int j = 0; j < len; j++) {
+                distances[i][j] = Math.pow(Math.pow(cities.get(i).getX() - cities.get(j).getX(), 2) +
+                        Math.pow(cities.get(i).getY() - cities.get(j).getY(), 2), .5);
+            }
+        }
+    }
+
+    /**
+     * Returns the instance of this class.
+     * @return instance
+     */
+    public static DistanceMatrix getInstance() {
+        return INSTANCE;
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/commons/package-info.java b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/commons/package-info.java
new file mode 100644
index 0000000..e0422fd
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/commons/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.examples.ga.tsp.commons;
diff --git a/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/legacy/TSPChromosome.java b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/legacy/TSPChromosome.java
new file mode 100644
index 0000000..9a42d39
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/legacy/TSPChromosome.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.examples.ga.tsp.legacy;
+
+import java.util.List;
+
+import org.apache.commons.math3.genetics.RandomKey;
+import org.apache.commons.math4.examples.ga.tsp.commons.City;
+import org.apache.commons.math4.examples.ga.tsp.commons.DistanceMatrix;
+
+/**
+ * This class represents chromosome for tsp problem.
+ */
+public class TSPChromosome extends RandomKey<City> {
+
+    /** list of cities. **/
+    private final List<City> cities;
+
+    /**
+     * constructor.
+     * @param representation internal representation of chromosome
+     * @param cities         list of cities
+     */
+    public TSPChromosome(List<Double> representation, List<City> cities) {
+        super(representation);
+        this.cities = cities;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public double fitness() {
+        final List<City> permutatedNodes = decode(cities);
+        return -calculateTotalDistance(permutatedNodes);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public TSPChromosome newFixedLengthChromosome(List<Double> representation) {
+        return new TSPChromosome(representation, cities);
+    }
+
+    private double calculateTotalDistance(List<City> permutedCities) {
+        double totalDistance = 0.0;
+        int index1 = 0;
+        int index2 = 0;
+        for (int i = 0; i < permutedCities.size(); i++) {
+            index1 = i;
+            index2 = (i == permutedCities.size() - 1) ? 0 : i + 1;
+            totalDistance += calculateNodeDistance(permutedCities.get(index1), permutedCities.get(index2));
+        }
+        return totalDistance;
+    }
+
+    private double calculateNodeDistance(City node1, City node2) {
+        return DistanceMatrix.getInstance().getDistance(node1, node2);
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/legacy/TSPOptimizerLegacy.java b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/legacy/TSPOptimizerLegacy.java
new file mode 100644
index 0000000..81ae597
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/legacy/TSPOptimizerLegacy.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.examples.ga.tsp.legacy;
+
+import java.io.BufferedWriter;
+
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.util.List;
+
+import org.apache.commons.math3.genetics.ElitisticListPopulation;
+import org.apache.commons.math3.genetics.GeneticAlgorithm;
+import org.apache.commons.math3.genetics.OnePointCrossover;
+import org.apache.commons.math3.genetics.Population;
+import org.apache.commons.math3.genetics.RandomKey;
+import org.apache.commons.math3.genetics.RandomKeyMutation;
+import org.apache.commons.math3.genetics.StoppingCondition;
+import org.apache.commons.math3.genetics.TournamentSelection;
+import org.apache.commons.math4.examples.ga.tsp.commons.City;
+import org.apache.commons.math4.examples.ga.tsp.utils.Constants;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+
+/**
+ * This class represents the tsp optimizer based on legacy implementation of
+ * Genetic Algorithm.
+ */
+public class TSPOptimizerLegacy {
+
+    /**
+     * MainThread.sleep(5000) method to initiate optimization.
+     * @param args arguments
+     */
+    public static void main(String[] args) {
+
+        final Population initPopulation = getInitialPopulation(Constants.CITIES);
+        final TSPOptimizerLegacy optimizer = new TSPOptimizerLegacy();
+
+        optimizer.optimize(initPopulation, Constants.CITIES);
+
+    }
+
+    /**
+     * Optimizes the tsp problem using legacy GA.
+     * @param initial initial population
+     * @param cities  cities
+     */
+    public void optimize(Population initial, List<City> cities) {
+
+        // initialize a new genetic algorithm
+        final GeneticAlgorithm ga = new GeneticAlgorithm(new OnePointCrossover<Integer>(), Constants.CROSSOVER_RATE,
+                new RandomKeyMutation(), Constants.AVERAGE_MUTATION_RATE,
+                new TournamentSelection(Constants.TOURNAMENT_SIZE));
+
+        // stopping condition
+        final StoppingCondition stopCond = new UnchangedBestFitness(
+                Constants.GENERATION_COUNT_WITH_UNCHANGED_BEST_FUTNESS);
+
+        // run the algorithm
+        final Population finalPopulation = ga.evolve(initial, stopCond);
+
+        // best chromosome from the final population
+        @SuppressWarnings("unchecked")
+        final RandomKey<City> bestFinal = (RandomKey<City>) finalPopulation.getFittestChromosome();
+
+        try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out, Constants.ENCODING))) {
+            writer.write("*********************************************");
+            writer.newLine();
+            writer.write("***********Optimization Result***************");
+            writer.write(bestFinal.toString());
+        } catch (IOException e) {
+            throw new GeneticException(e);
+        }
+    }
+
+    private static Population getInitialPopulation(List<City> cities) {
+        final Population simulationPopulation = new ElitisticListPopulation(Constants.POPULATION_SIZE, .25);
+
+        for (int i = 0; i < Constants.POPULATION_SIZE; i++) {
+            simulationPopulation.addChromosome(new TSPChromosome(RandomKey.randomPermutation(cities.size()), cities));
+        }
+
+        return simulationPopulation;
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/legacy/UnchangedBestFitness.java b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/legacy/UnchangedBestFitness.java
new file mode 100644
index 0000000..44fe93a
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/legacy/UnchangedBestFitness.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.examples.ga.tsp.legacy;
+
+import org.apache.commons.math3.genetics.Population;
+import org.apache.commons.math3.genetics.StoppingCondition;
+
+/**
+ * This class represents the stopping condition based on unchanged best fitness.
+ */
+public class UnchangedBestFitness implements StoppingCondition {
+
+    /** last best fitness. **/
+    private double lastBestFitness = Double.MIN_VALUE;
+
+    /** maximum number of generations evolved with unchanged best fitness. **/
+    private final int maxGenerationsWithUnchangedBestFitness;
+
+    /** generations having unchanged best fitness. **/
+    private int generationsHavingUnchangedBestFitness;
+
+    /**
+     * constructor.
+     * @param maxGenerationsWithUnchangedAverageFitness maximum number of
+     *                                                  generations evolved with
+     *                                                  unchanged best fitness
+     */
+    public UnchangedBestFitness(final int maxGenerationsWithUnchangedAverageFitness) {
+        this.maxGenerationsWithUnchangedBestFitness = maxGenerationsWithUnchangedAverageFitness;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean isSatisfied(Population population) {
+        final double currentBestFitness = population.getFittestChromosome().getFitness();
+
+        if (lastBestFitness == currentBestFitness) {
+            this.generationsHavingUnchangedBestFitness++;
+            if (generationsHavingUnchangedBestFitness == maxGenerationsWithUnchangedBestFitness) {
+                return true;
+            }
+        } else {
+            this.generationsHavingUnchangedBestFitness = 0;
+            lastBestFitness = currentBestFitness;
+        }
+
+        return false;
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/legacy/package-info.java b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/legacy/package-info.java
new file mode 100644
index 0000000..d46c6fd
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/legacy/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.examples.ga.tsp.legacy;
diff --git a/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/package-info.java b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/package-info.java
new file mode 100644
index 0000000..938b8f9
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.examples.ga.tsp;
diff --git a/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/utils/Constants.java b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/utils/Constants.java
new file mode 100644
index 0000000..c41cc31
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/utils/Constants.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.examples.ga.tsp.utils;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.math4.examples.ga.tsp.commons.City;
+
+/**
+ * This class contains all required constants for this example.
+ */
+public final class Constants {
+
+    /** size of population. **/
+    public static final int POPULATION_SIZE = 100;
+
+    /** size of tournament. **/
+    public static final int TOURNAMENT_SIZE = 5;
+
+    /** length of chromosome. **/
+    public static final int CHROMOSOME_LENGTH = 14;
+
+    /** rate of crossover. **/
+    public static final double CROSSOVER_RATE = 1.0;
+
+    /** rate of elitism. **/
+    public static final double ELITISM_RATE = 0.25;
+
+    /** rate of mutation. **/
+    public static final double AVERAGE_MUTATION_RATE = 0.05;
+
+    /** maximum number of generations with unchanged best fitness. **/
+    public static final int GENERATION_COUNT_WITH_UNCHANGED_BEST_FUTNESS = 50;
+
+    /** list of cities. **/
+    public static final List<City> CITIES = Collections.unmodifiableList(
+            Arrays.asList(new City[] {new City(1, 0, 0), new City(2, 1, 0), new City(3, 2, 0), new City(4, 3, 0),
+                new City(5, 3, 1), new City(6, 3, 2), new City(7, 3, 3), new City(8, 2, 3), new City(9, 1, 3),
+                new City(10, 0, 3), new City(11, 1, 2), new City(12, 2, 2), new City(13, 2, 1), new City(14, 1, 1)}));
+
+    /** encoding for console logger. **/
+    public static final String ENCODING = "UTF-8";
+
+    private Constants() {
+
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/utils/GraphPlotter.java b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/utils/GraphPlotter.java
new file mode 100644
index 0000000..701380b
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/utils/GraphPlotter.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.examples.ga.tsp.utils;
+
+import java.awt.BorderLayout;
+
+import java.util.List;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+import org.apache.commons.math4.examples.ga.tsp.commons.City;
+import org.apache.commons.math4.ga.internal.stats.PopulationStatisticalSummaryImpl;
+import org.apache.commons.math4.ga.listener.ConvergenceListener;
+import org.apache.commons.math4.ga.population.Population;
+import org.apache.commons.math4.ga.stats.PopulationStatisticalSummary;
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.ChartPanel;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
+import org.jfree.data.xy.XYSeries;
+import org.jfree.data.xy.XYSeriesCollection;
+
+/**
+ * This class represents the graph plotter during optimization.
+ */
+public class GraphPlotter extends JFrame implements ConvergenceListener<List<City>> {
+
+    /**
+     * Generated serialversionId.
+     */
+    private static final long serialVersionUID = -5683904006424006584L;
+
+    /** collection of 2-D series. **/
+    private final XYSeriesCollection dataset = new XYSeriesCollection();
+
+    /**
+     * constructor.
+     * @param plotSubject subject of plot
+     * @param xAxisLabel  x axis label
+     * @param yAxisLabel  y axis label
+     */
+    public GraphPlotter(String plotSubject, String xAxisLabel, String yAxisLabel) {
+        super(plotSubject);
+
+        final JPanel chartPanel = createChartPanel(plotSubject, xAxisLabel, yAxisLabel);
+        add(chartPanel, BorderLayout.CENTER);
+
+        setSize(640, 480);
+        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+        setLocationRelativeTo(null);
+
+        setVisible(true);
+    }
+
+    /**
+     * Adds data point to graph.
+     * @param graphName  name of graph
+     * @param generation generation, to be plotted along x axis
+     * @param value      value, to be plotted along y axis
+     */
+    private void addDataPoint(String graphName, int generation, double value) {
+        XYSeries series = null;
+
+        if (!containsGraph(graphName)) {
+            series = new XYSeries(graphName);
+            dataset.addSeries(series);
+        } else {
+            series = dataset.getSeries(graphName);
+        }
+        series.add(generation, value);
+
+        setVisible(true);
+    }
+
+    /**
+     * Checks if the graph with the given name already exists.
+     * @param graphName name of the graph
+     * @return true/false
+     */
+    @SuppressWarnings("unchecked")
+    private boolean containsGraph(String graphName) {
+        final List<XYSeries> seriesList = dataset.getSeries();
+        if (seriesList == null || seriesList.isEmpty()) {
+            return false;
+        }
+        for (XYSeries series : seriesList) {
+            if (series.getKey().compareTo(graphName) == 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Creates chart panel.
+     * @param chartTitle chart title
+     * @param xAxisLabel x axis label
+     * @param yAxisLabel y axis label
+     * @return panel
+     */
+    private JPanel createChartPanel(String chartTitle, String xAxisLabel, String yAxisLabel) {
+
+        final boolean showLegend = true;
+        final boolean createURL = false;
+        final boolean createTooltip = false;
+
+        final JFreeChart chart = ChartFactory.createXYLineChart(chartTitle, xAxisLabel, yAxisLabel, dataset,
+                PlotOrientation.VERTICAL, showLegend, createTooltip, createURL);
+        final XYPlot plot = chart.getXYPlot();
+        final XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
+
+        plot.setRenderer(renderer);
+
+        return new ChartPanel(chart);
+
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void notify(int generation, Population<List<City>> population) {
+        PopulationStatisticalSummary<List<City>> populationStatisticalSummary = new PopulationStatisticalSummaryImpl<>(
+                population);
+        this.addDataPoint("Average", generation, populationStatisticalSummary.getMeanFitness());
+        this.addDataPoint("Best", generation, populationStatisticalSummary.getMaxFitness());
+    }
+
+}
diff --git a/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/utils/package-info.java b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/utils/package-info.java
new file mode 100644
index 0000000..5caadde
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-tsp/src/main/java/org/apache/commons/math4/examples/ga/tsp/utils/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.examples.ga.tsp.utils;
diff --git a/commons-math-examples/examples-ga/pom.xml b/commons-math-examples/examples-ga/pom.xml
new file mode 100644
index 0000000..8432483
--- /dev/null
+++ b/commons-math-examples/examples-ga/pom.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-math-examples</artifactId>
+        <version>4.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>examples-ga</artifactId>
+    <packaging>pom</packaging>
+    <name>examples-genetic-algorithm</name>
+
+    <properties>
+        <!-- Workaround to avoid duplicating config files. -->
+        <math.parent.dir>${basedir}/../..</math.parent.dir>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-math-ga</artifactId>
+            <version>4.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-math3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jfree</groupId>
+            <artifactId>jfreechart</artifactId>
+            <version>1.5.3</version>
+        </dependency>
+    </dependencies>
+    <modules>
+        <module>examples-ga-math-functions</module>
+        <module>examples-ga-tsp</module>
+    </modules>
+</project>
\ No newline at end of file
diff --git a/commons-math-examples/pom.xml b/commons-math-examples/pom.xml
index 595491f..2619557 100644
--- a/commons-math-examples/pom.xml
+++ b/commons-math-examples/pom.xml
@@ -158,6 +158,7 @@
 
   <modules>
     <module>examples-sofm</module>
+	<module>examples-ga</module>
   </modules>
 
 </project>
diff --git a/commons-math-ga/pom.xml b/commons-math-ga/pom.xml
new file mode 100644
index 0000000..a2a3689
--- /dev/null
+++ b/commons-math-ga/pom.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0"?>
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor 
+    license agreements. See the NOTICE file distributed with this work for additional 
+    information regarding copyright ownership. The ASF licenses this file to 
+    You under the Apache License, Version 2.0 (the "License"); you may not use 
+    this file except in compliance with the License. You may obtain a copy of 
+    the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required 
+    by applicable law or agreed to in writing, software distributed under the 
+    License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
+    OF ANY KIND, either express or implied. See the License for the specific 
+    language governing permissions and limitations under the License. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-math-parent</artifactId>
+        <version>4.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>commons-math-ga</artifactId>
+    <name>genetic algorithm</name>
+
+    <description />
+
+    <properties>
+        <!-- The Java Module System Name -->
+        <commons.module.name>org.apache.commons.math4.ga</commons.module.name>
+        <!-- This value must reflect the current name of the base package. -->
+        <commons.osgi.symbolicName>org.apache.commons.math4.ga</commons.osgi.symbolicName>
+        <!-- OSGi -->
+        <commons.osgi.export>org.apache.commons.math4.ga</commons.osgi.export>
+        <!-- Workaround to avoid duplicating config files. -->
+        <math.parent.dir>${basedir}/..</math.parent.dir>
+        <slf4jVersion>1.7.32</slf4jVersion>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-numbers-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-rng-simple</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>${slf4jVersion}</version>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/AbstractGeneticAlgorithm.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/AbstractGeneticAlgorithm.java
new file mode 100644
index 0000000..7f9359f
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/AbstractGeneticAlgorithm.java
@@ -0,0 +1,180 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga;
+
+import org.apache.commons.math4.ga.convergence.StoppingCondition;
+import org.apache.commons.math4.ga.crossover.CrossoverPolicy;
+import org.apache.commons.math4.ga.listener.ConvergenceListenerRegistry;
+import org.apache.commons.math4.ga.mutation.MutationPolicy;
+import org.apache.commons.math4.ga.population.Population;
+import org.apache.commons.math4.ga.selection.SelectionPolicy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class represents an abstraction for all Genetic algorithm implementation
+ * comprising the basic properties and operations.
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public abstract class AbstractGeneticAlgorithm<P> {
+
+    /** instance of logger. **/
+    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractGeneticAlgorithm.class);
+
+    /** the crossover policy used by the algorithm. */
+    private final CrossoverPolicy<P> crossoverPolicy;
+
+    /** the mutation policy used by the algorithm. */
+    private final MutationPolicy<P> mutationPolicy;
+
+    /** the selection policy used by the algorithm. */
+    private final SelectionPolicy<P> selectionPolicy;
+
+    /**
+     * the number of generations evolved to reach {@link StoppingCondition} in the
+     * last run.
+     */
+    private int generationsEvolved;
+
+    /** The elitism rate having default value of .25. */
+    private double elitismRate = .25;
+
+    /**
+     * @param crossoverPolicy The {@link CrossoverPolicy}
+     * @param mutationPolicy  The {@link MutationPolicy}
+     * @param selectionPolicy The {@link SelectionPolicy}
+     */
+    protected AbstractGeneticAlgorithm(final CrossoverPolicy<P> crossoverPolicy,
+            final MutationPolicy<P> mutationPolicy,
+            final SelectionPolicy<P> selectionPolicy) {
+        this.crossoverPolicy = crossoverPolicy;
+        this.mutationPolicy = mutationPolicy;
+        this.selectionPolicy = selectionPolicy;
+    }
+
+    /**
+     * @param crossoverPolicy The {@link CrossoverPolicy}
+     * @param mutationPolicy  The {@link MutationPolicy}
+     * @param selectionPolicy The {@link SelectionPolicy}
+     * @param elitismRate     The elitism rate
+     */
+    protected AbstractGeneticAlgorithm(final CrossoverPolicy<P> crossoverPolicy,
+            final MutationPolicy<P> mutationPolicy,
+            final SelectionPolicy<P> selectionPolicy,
+            double elitismRate) {
+        this.crossoverPolicy = crossoverPolicy;
+        this.mutationPolicy = mutationPolicy;
+        this.selectionPolicy = selectionPolicy;
+        this.elitismRate = elitismRate;
+    }
+
+    /**
+     * Returns the crossover policy.
+     * @return crossover policy
+     */
+    public CrossoverPolicy<P> getCrossoverPolicy() {
+        return crossoverPolicy;
+    }
+
+    /**
+     * Returns the mutation policy.
+     * @return mutation policy
+     */
+    public MutationPolicy<P> getMutationPolicy() {
+        return mutationPolicy;
+    }
+
+    /**
+     * Returns the selection policy.
+     * @return selection policy
+     */
+    public SelectionPolicy<P> getSelectionPolicy() {
+        return selectionPolicy;
+    }
+
+    /**
+     * Returns the number of generations evolved to reach {@link StoppingCondition}
+     * in the last run.
+     *
+     * @return number of generations evolved
+     * @since 2.1
+     */
+    public int getGenerationsEvolved() {
+        return generationsEvolved;
+    }
+
+    /**
+     * Evolve the given population. Evolution stops when the stopping condition is
+     * satisfied. Updates the {@link #getGenerationsEvolved() generationsEvolved}
+     * property with the number of generations evolved before the StoppingCondition
+     * is satisfied.
+     *
+     * @param initial   the initial, seed population.
+     * @param condition the stopping condition used to stop evolution.
+     * @return the population that satisfies the stopping condition.
+     */
+    public Population<P> evolve(final Population<P> initial, final StoppingCondition<P> condition) {
+        Population<P> current = initial;
+
+        LOGGER.info("Starting evolution process.");
+        // check if stopping condition is satisfied otherwise produce the next
+        // generation of population.
+        while (!condition.isSatisfied(current)) {
+            // notify interested listener
+            ConvergenceListenerRegistry.<P>getInstance().notifyAll(generationsEvolved, current);
+
+            current = nextGeneration(current);
+            this.generationsEvolved++;
+        }
+        LOGGER.info("Population convergence achieved after generations: " + generationsEvolved);
+
+        return current;
+    }
+
+    /**
+     * Evolve the given population into the next generation.
+     * <ol>
+     * <li>Get nextGeneration population to fill from <code>current</code>
+     * generation, using its nextGeneration method</li>
+     * <li>Loop until new generation is filled:
+     * <ul>
+     * <li>Apply configured SelectionPolicy to select a pair of parents from
+     * <code>current</code>,</li>
+     * <li>apply configured {@link CrossoverPolicy} to parents,</li>
+     * <li>apply configured {@link MutationPolicy} to each of the offspring</li>
+     * <li>Add offspring individually to nextGeneration, space permitting</li>
+     * </ul>
+     * </li>
+     * <li>Return nextGeneration</li>
+     * </ol>
+     *
+     * @param current the current population
+     * @return the population for the next generation.
+     */
+    protected abstract Population<P> nextGeneration(Population<P> current);
+
+    /**
+     * Returns the elitism rate.
+     * @return elitism rate
+     */
+    public double getElitismRate() {
+        return elitismRate;
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/AdaptiveGeneticAlgorithm.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/AdaptiveGeneticAlgorithm.java
new file mode 100644
index 0000000..07e8913
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/AdaptiveGeneticAlgorithm.java
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.chromosome.ChromosomePair;
+import org.apache.commons.math4.ga.crossover.CrossoverPolicy;
+import org.apache.commons.math4.ga.crossover.rategenerator.CrossoverRateGenerator;
+import org.apache.commons.math4.ga.internal.stats.PopulationStatisticalSummaryImpl;
+import org.apache.commons.math4.ga.mutation.MutationPolicy;
+import org.apache.commons.math4.ga.mutation.rategenerator.MutationRateGenerator;
+import org.apache.commons.math4.ga.population.Population;
+import org.apache.commons.math4.ga.selection.SelectionPolicy;
+import org.apache.commons.math4.ga.stats.PopulationStatisticalSummary;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * An implementation of Genetic Algorithm. The probability of crossover and
+ * mutation is generated in an adaptive way. This implementation allows
+ * configuration of dynamic crossover and mutation rate generator along with
+ * crossover policy, mutation policy, selection policy and optionally elitism
+ * rate.
+ * @param <P> phenotype of chromosome
+ */
+public class AdaptiveGeneticAlgorithm<P> extends AbstractGeneticAlgorithm<P> {
+
+    /** instance of logger. **/
+    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractGeneticAlgorithm.class);
+
+    /** The crossover rate generator. **/
+    private final CrossoverRateGenerator<P> crossoverRateGenerator;
+
+    /** The mutation rate generator. **/
+    private final MutationRateGenerator<P> mutationRateGenerator;
+
+    /**
+     * @param crossoverPolicy               crossover policy
+     * @param crossoverProbabilityGenerator crossover probability generator
+     * @param mutationPolicy                mutation policy
+     * @param mutationProbabilityGenerator  mutation probability generator
+     * @param selectionPolicy               selection policy
+     */
+    public AdaptiveGeneticAlgorithm(CrossoverPolicy<P> crossoverPolicy,
+            CrossoverRateGenerator<P> crossoverProbabilityGenerator,
+            MutationPolicy<P> mutationPolicy,
+            MutationRateGenerator<P> mutationProbabilityGenerator,
+            SelectionPolicy<P> selectionPolicy) {
+        super(crossoverPolicy, mutationPolicy, selectionPolicy);
+        this.crossoverRateGenerator = crossoverProbabilityGenerator;
+        this.mutationRateGenerator = mutationProbabilityGenerator;
+    }
+
+    /**
+     * @param crossoverPolicy               crossover policy
+     * @param crossoverProbabilityGenerator crossover probability generator
+     * @param mutationPolicy                mutation policy
+     * @param mutationProbabilityGenerator  mutation probability generator
+     * @param selectionPolicy               selection policy
+     * @param elitismRate                   elitism rate
+     */
+    public AdaptiveGeneticAlgorithm(CrossoverPolicy<P> crossoverPolicy,
+            CrossoverRateGenerator<P> crossoverProbabilityGenerator,
+            MutationPolicy<P> mutationPolicy,
+            MutationRateGenerator<P> mutationProbabilityGenerator,
+            SelectionPolicy<P> selectionPolicy,
+            double elitismRate) {
+        super(crossoverPolicy, mutationPolicy, selectionPolicy, elitismRate);
+        this.crossoverRateGenerator = crossoverProbabilityGenerator;
+        this.mutationRateGenerator = mutationProbabilityGenerator;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected Population<P> nextGeneration(Population<P> current) {
+
+        LOGGER.debug("Reproducing next generation.");
+
+        // compute statistics of current generation chromosomes.
+        PopulationStatisticalSummary<P> populationStats = new PopulationStatisticalSummaryImpl<>(current);
+
+        // Initialize the next generation with elit chromosomes from previous
+        // generation.
+        final Population<P> nextGeneration = current.nextGeneration(getElitismRate());
+
+        LOGGER.debug(
+                "No of Elite chromosomes selected from previous generation: " + nextGeneration.getPopulationSize());
+
+        final int maxOffspringCount = nextGeneration.getPopulationLimit() - nextGeneration.getPopulationSize();
+
+        // Initialize an empty population for offsprings.
+        final Population<P> offspringPopulation = current.nextGeneration(0);
+
+        // perform crossover and generate new offsprings
+        while (offspringPopulation.getPopulationSize() < maxOffspringCount) {
+
+            // select parent chromosomes
+            ChromosomePair<P> pair = getSelectionPolicy().select(current);
+            LOGGER.debug("Selected Chromosomes: \r\n" + pair.toString());
+
+            final double crossoverRate = crossoverRateGenerator.generate(pair.getFirst(), pair.getSecond(),
+                    populationStats, getGenerationsEvolved());
+            // apply crossover policy to create two offspring
+            pair = getCrossoverPolicy().crossover(pair.getFirst(), pair.getSecond(), crossoverRate);
+            LOGGER.debug("Offsprings after Crossover: \r\n" + pair.toString());
+
+            // add the first chromosome to the population
+            offspringPopulation.addChromosome(pair.getFirst());
+            // is there still a place for the second chromosome?
+            if (offspringPopulation.getPopulationSize() < maxOffspringCount) {
+                // add the second chromosome to the population
+                offspringPopulation.addChromosome(pair.getSecond());
+            }
+        }
+        LOGGER.debug("Performing adaptive mutation of offsprings.");
+
+        // recompute the statistics of the offspring population.
+        populationStats = new PopulationStatisticalSummaryImpl<>(offspringPopulation);
+
+        // apply mutation policy to the offspring chromosomes and add the mutated
+        // chromosomes to next generation.
+        for (Chromosome<P> chromosome : offspringPopulation) {
+            nextGeneration.addChromosome(getMutationPolicy().mutate(chromosome,
+                    mutationRateGenerator.generate(chromosome, populationStats, getGenerationsEvolved())));
+        }
+        LOGGER.debug("New Generation: \r\n" + nextGeneration.toString());
+
+        return nextGeneration;
+    }
+
+    /**
+     * Returns crossover probability generator.
+     * @return crossover probability generator
+     */
+    public CrossoverRateGenerator<P> getCrossoverProbabilityGenerator() {
+        return crossoverRateGenerator;
+    }
+
+    /**
+     * Returns mutation probability generator.
+     * @return mutation probability generator
+     */
+    public MutationRateGenerator<P> getMutationProbabilityGenerator() {
+        return mutationRateGenerator;
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/GeneticAlgorithm.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/GeneticAlgorithm.java
new file mode 100644
index 0000000..94e320d
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/GeneticAlgorithm.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga;
+
+import org.apache.commons.math4.ga.chromosome.ChromosomePair;
+import org.apache.commons.math4.ga.crossover.CrossoverPolicy;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.apache.commons.math4.ga.mutation.MutationPolicy;
+import org.apache.commons.math4.ga.population.Population;
+import org.apache.commons.math4.ga.selection.SelectionPolicy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of a genetic algorithm. All factors that govern the operation
+ * of the algorithm can be configured for a specific problem.
+ *
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public class GeneticAlgorithm<P> extends AbstractGeneticAlgorithm<P> {
+
+    /** instance of logger. **/
+    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractGeneticAlgorithm.class);
+
+    /** crossover rate string. **/
+    private static final String CROSSOVER_RATE = "CROSSOVER_RATE";
+
+    /** mutation rate string. **/
+    private static final String MUTATION_RATE = "MUTATION_RATE";
+
+    /** the rate of crossover for the algorithm. */
+    private final double crossoverRate;
+
+    /** the rate of mutation for the algorithm. */
+    private final double mutationRate;
+
+    /**
+     * Create a new genetic algorithm.
+     * @param crossoverPolicy The {@link CrossoverPolicy}
+     * @param crossoverRate   The crossover rate as a percentage (0-1 inclusive)
+     * @param mutationPolicy  The {@link MutationPolicy}
+     * @param mutationRate    The mutation rate as a percentage (0-1 inclusive)
+     * @param selectionPolicy The {@link SelectionPolicy}
+     */
+    public GeneticAlgorithm(final CrossoverPolicy<P> crossoverPolicy,
+            final double crossoverRate,
+            final MutationPolicy<P> mutationPolicy,
+            final double mutationRate,
+            final SelectionPolicy<P> selectionPolicy) {
+        super(crossoverPolicy, mutationPolicy, selectionPolicy);
+
+        checkValidity(crossoverRate, mutationRate);
+        this.crossoverRate = crossoverRate;
+        this.mutationRate = mutationRate;
+    }
+
+    /**
+     * Create a new genetic algorithm.
+     * @param crossoverPolicy The {@link CrossoverPolicy}
+     * @param crossoverRate   The crossover rate as a percentage (0-1 inclusive)
+     * @param mutationPolicy  The {@link MutationPolicy}
+     * @param mutationRate    The mutation rate as a percentage (0-1 inclusive)
+     * @param selectionPolicy The {@link SelectionPolicy}
+     * @param elitismRate     The rate of elitism
+     */
+    public GeneticAlgorithm(final CrossoverPolicy<P> crossoverPolicy,
+            final double crossoverRate,
+            final MutationPolicy<P> mutationPolicy,
+            final double mutationRate,
+            final SelectionPolicy<P> selectionPolicy,
+            final double elitismRate) {
+        super(crossoverPolicy, mutationPolicy, selectionPolicy, elitismRate);
+
+        checkValidity(crossoverRate, mutationRate);
+        this.crossoverRate = crossoverRate;
+        this.mutationRate = mutationRate;
+    }
+
+    private void checkValidity(final double crossoverRateInput, final double inputMutationRate) {
+        if (crossoverRateInput < 0 || crossoverRateInput > 1) {
+            throw new GeneticException(GeneticException.OUT_OF_RANGE, crossoverRateInput, CROSSOVER_RATE, 0, 1);
+        }
+        if (inputMutationRate < 0 || inputMutationRate > 1) {
+            throw new GeneticException(GeneticException.OUT_OF_RANGE, inputMutationRate, MUTATION_RATE, 0, 1);
+        }
+    }
+
+    /**
+     * Evolve the given population into the next generation.
+     * <ol>
+     * <li>Get nextGeneration population to fill from <code>current</code>
+     * generation, using its nextGeneration method</li>
+     * <li>Loop until new generation is filled:
+     * <ul>
+     * <li>Apply configured SelectionPolicy to select a pair of parents from
+     * <code>current</code></li>
+     * <li>With probability = {@link #getCrossoverRate()}, apply configured
+     * {@link CrossoverPolicy} to parents</li>
+     * <li>With probability = {@link #getMutationRate()}, apply configured
+     * {@link MutationPolicy} to each of the offspring</li>
+     * <li>Add offspring individually to nextGeneration, space permitting</li>
+     * </ul>
+     * </li>
+     * <li>Return nextGeneration</li>
+     * </ol>
+     *
+     * @param current the current population.
+     * @return the population for the next generation.
+     */
+    @Override
+    protected Population<P> nextGeneration(final Population<P> current) {
+
+        LOGGER.debug("Reproducing next generation.");
+        final Population<P> nextGeneration = current.nextGeneration(getElitismRate());
+
+        while (nextGeneration.getPopulationSize() < nextGeneration.getPopulationLimit() - 1) {
+
+            // select parent chromosomes
+            ChromosomePair<P> pair = getSelectionPolicy().select(current);
+            LOGGER.debug("Selected Chromosomes: \r\n" + pair.toString());
+
+            // apply crossover policy to create two offspring
+            pair = getCrossoverPolicy().crossover(pair.getFirst(), pair.getSecond(), crossoverRate);
+            LOGGER.debug("Offsprings after Crossover: \r\n" + pair.toString());
+
+            // apply mutation policy to the chromosomes
+            pair = new ChromosomePair<>(getMutationPolicy().mutate(pair.getFirst(), mutationRate),
+                    getMutationPolicy().mutate(pair.getSecond(), mutationRate));
+            LOGGER.debug("Offsprings after Mutation: \r\n" + pair.toString());
+
+            // add the chromosomes to the population
+            nextGeneration.addChromosome(pair.getFirst());
+            nextGeneration.addChromosome(pair.getSecond());
+        }
+        LOGGER.debug("New Generation : \r\n" + nextGeneration.toString());
+
+        return nextGeneration;
+    }
+
+    /**
+     * Returns the crossover rate.
+     * @return crossover rate
+     */
+    public double getCrossoverRate() {
+        return crossoverRate;
+    }
+
+    /**
+     * Returns the mutation rate.
+     * @return mutation rate
+     */
+    public double getMutationRate() {
+        return mutationRate;
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/AbstractChromosome.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/AbstractChromosome.java
new file mode 100644
index 0000000..4f61ace
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/AbstractChromosome.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.chromosome;
+
+import java.util.Objects;
+import java.util.UUID;
+
+import org.apache.commons.math4.ga.decoder.Decoder;
+import org.apache.commons.math4.ga.fitness.FitnessFunction;
+
+/**
+ * Individual in a population. Chromosomes are compared based on their fitness.
+ * <p>
+ * The chromosomes are IMMUTABLE, and so their fitness is also immutable and
+ * therefore it can be cached.
+ *
+ * @param <P> The phenotype of chromosome. The type should override hashCode()
+ *            and equals() methods.
+ * @since 4.0
+ */
+public abstract class AbstractChromosome<P> implements Chromosome<P> {
+
+    /** Value assigned when no fitness has been computed yet. */
+    private static final double NO_FITNESS = Double.NEGATIVE_INFINITY;
+
+    /** Cached value of the fitness of this chromosome. */
+    private double fitness = NO_FITNESS;
+
+    /** Fitness function to evaluate fitness of chromosome. **/
+    private final FitnessFunction<P> fitnessFunction;
+
+    /** decoder to deode the chromosome's genotype representation. **/
+    private final Decoder<P> decoder;
+
+    /** Id of chromosome. **/
+    private final String id;
+
+    /**
+     * @param fitnessFunction The {@link FitnessFunction}
+     * @param decoder         The {@link Decoder}
+     */
+    protected AbstractChromosome(final FitnessFunction<P> fitnessFunction, final Decoder<P> decoder) {
+        this.fitnessFunction = Objects.requireNonNull(fitnessFunction);
+        this.decoder = Objects.requireNonNull(decoder);
+        this.id = UUID.randomUUID().toString();
+    }
+
+    /**
+     * returns fitness function.
+     * @return fitnessFunction
+     */
+    protected FitnessFunction<P> getFitnessFunction() {
+        return fitnessFunction;
+    }
+
+    /**
+     * Returns the decoder instance.
+     * @return decoder
+     */
+    public Decoder<P> getDecoder() {
+        return decoder;
+    }
+
+    /**
+     * Returns id of chromosome.
+     * @return id
+     */
+    @Override
+    public String getId() {
+        return id;
+    }
+
+    /**
+     * Access the fitness of this chromosome. The bigger the fitness, the better the
+     * chromosome.
+     * <p>
+     * Computation of fitness is usually very time-consuming task, therefore the
+     * fitness is cached.
+     * @return the fitness
+     */
+    @Override
+    public double evaluate() {
+        if (this.fitness == NO_FITNESS) {
+            // no cache - compute the fitness
+            this.fitness = fitnessFunction.compute(decode());
+        }
+        return this.fitness;
+    }
+
+    /**
+     * Decodes the chromosome genotype and returns the phenotype.
+     * @return phenotype
+     */
+    @Override
+    public P decode() {
+        return this.decoder.decode(this);
+    }
+
+    /**
+     * Compares two chromosomes based on their fitness. The bigger the fitness, the
+     * better the chromosome.
+     * @param another another chromosome to compare
+     * @return
+     *         <ul>
+     *         <li>-1 if <code>another</code> is better than <code>this</code></li>
+     *         <li>1 if <code>another</code> is worse than <code>this</code></li>
+     *         <li>0 if the two chromosomes have the same fitness</li>
+     *         </ul>
+     */
+    @Override
+    public int compareTo(final Chromosome<P> another) {
+        return Double.compare(evaluate(), another.evaluate());
+    }
+
+    /**
+     * Returns <code>true</code> iff <code>another</code> has the same
+     * representation and therefore the same fitness. By default, it returns false
+     * -- override it in your implementation if you need it.
+     * @param another chromosome to compare
+     * @return true if <code>another</code> is equivalent to this chromosome
+     */
+    public boolean isSame(final AbstractChromosome<P> another) {
+        final P decodedChromosome = decode();
+        final P otherDecodedChromosome = another.decode();
+        return decodedChromosome.equals(otherDecodedChromosome);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String toString() {
+        return String.format("(f=%s %s)", evaluate(), decode());
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/AbstractListChromosome.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/AbstractListChromosome.java
new file mode 100644
index 0000000..9e1676d
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/AbstractListChromosome.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.chromosome;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+import org.apache.commons.math4.ga.decoder.AbstractListChromosomeDecoder;
+import org.apache.commons.math4.ga.fitness.FitnessFunction;
+
+/**
+ * This class represents an abstract chromosome containing an immutable list of
+ * allele/genes.
+ * @param <T> type of the allele/gene in the representation list. T should be
+ *            immutable.
+ * @param <P> phenotype of chromosome
+ * @since 2.0
+ */
+public abstract class AbstractListChromosome<T, P> extends AbstractChromosome<P> {
+
+    /** List of allele/genes. */
+    private final List<T> representation;
+
+    /**
+     * @param representation  The representation of chromosome genotype as
+     *                        {@link List} of generic T
+     * @param fitnessFunction The {@link FitnessFunction}
+     * @param decoder         An instance of {@link AbstractListChromosomeDecoder},
+     *                        to decode list chromosome.
+     */
+    protected AbstractListChromosome(final List<T> representation,
+            final FitnessFunction<P> fitnessFunction,
+            final AbstractListChromosomeDecoder<T, P> decoder) {
+        this(representation, true, fitnessFunction, decoder);
+    }
+
+    /**
+     * @param representation  The representation of chromosome genotype as an array
+     *                        of generic T
+     * @param fitnessFunction The {@link FitnessFunction}
+     * @param decoder         An instance of {@link AbstractListChromosomeDecoder},
+     *                        to decode list chromosome.
+     */
+    protected AbstractListChromosome(final T[] representation,
+            FitnessFunction<P> fitnessFunction,
+            AbstractListChromosomeDecoder<T, P> decoder) {
+        this(Arrays.asList(representation), fitnessFunction, decoder);
+    }
+
+    /**
+     * @param representation  Internal representation of chromosome genotype as an
+     *                        array of generic T
+     * @param copyList        if {@code true}, the representation will be copied,
+     *                        otherwise it will be referenced.
+     * @param fitnessFunction The {@link FitnessFunction}
+     * @param decoder         The instance of {@link AbstractListChromosomeDecoder}
+     */
+    protected AbstractListChromosome(final List<T> representation,
+            final boolean copyList,
+            final FitnessFunction<P> fitnessFunction,
+            final AbstractListChromosomeDecoder<T, P> decoder) {
+        super(fitnessFunction, decoder);
+        Objects.requireNonNull(representation);
+        this.representation = Collections.unmodifiableList(copyList ? new ArrayList<>(representation) : representation);
+    }
+
+    /**
+     * Returns the (immutable) inner representation of the chromosome.
+     * @return the representation of the chromosome
+     */
+    public List<T> getRepresentation() {
+        return representation;
+    }
+
+    /**
+     * Returns the length of the chromosome.
+     * @return the length of the chromosome
+     */
+    public int getLength() {
+        return getRepresentation().size();
+    }
+
+    /**
+     * returns the decoder.
+     * @return decoder
+     */
+    @SuppressWarnings("unchecked")
+    @Override
+    public AbstractListChromosomeDecoder<T, P> getDecoder() {
+        return (AbstractListChromosomeDecoder<T, P>) super.getDecoder();
+    }
+
+    /**
+     * Creates a new instance of the same class as <code>this</code> is, with a
+     * given <code>arrayRepresentation</code>. This is needed in crossover and
+     * mutation operators, where we need a new instance of the same class, but with
+     * different array representation.
+     * <p>
+     * Usually, this method just calls a constructor of the class.
+     *
+     * @param chromosomeRepresentation the inner array representation of the new
+     *                                 chromosome.
+     * @return new instance extended from FixedLengthChromosome with the given
+     *         arrayRepresentation
+     */
+    public abstract AbstractListChromosome<T, P> newChromosome(List<T> chromosomeRepresentation);
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/BinaryChromosome.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/BinaryChromosome.java
new file mode 100644
index 0000000..a9ef839
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/BinaryChromosome.java
@@ -0,0 +1,303 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.chromosome;
+
+import java.util.List;
+
+import java.util.Objects;
+
+import org.apache.commons.math4.ga.decoder.Decoder;
+import org.apache.commons.math4.ga.fitness.FitnessFunction;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.apache.commons.math4.ga.utils.ChromosomeRepresentationUtils;
+
+/**
+ * BinaryChromosome represented by a vector of 0s and 1s.
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public class BinaryChromosome<P> extends AbstractChromosome<P> {
+
+    /**
+     * maximum allowed length of binary chromosome.
+     */
+    public static final long MAX_LENGTH = Integer.MAX_VALUE;
+
+    /**
+     * length of binary chromosome.
+     */
+    private final long length;
+
+    /**
+     * binary representation of chromosome.
+     */
+    private final long[] representation;
+
+    /**
+     * @param representation  Internal representation of chromosome.
+     * @param length          length of chromosome
+     * @param fitnessFunction The {@link FitnessFunction}
+     * @param decoder         The {@link Decoder}
+     */
+    public BinaryChromosome(List<Long> representation,
+            long length,
+            FitnessFunction<P> fitnessFunction,
+            Decoder<P> decoder) {
+        super(fitnessFunction, decoder);
+        Objects.requireNonNull(representation);
+        checkMaximumLength(length);
+        this.length = length;
+        this.representation = new long[representation.size()];
+        for (int i = 0; i < representation.size(); i++) {
+            this.representation[i] = representation.get(i);
+        }
+    }
+
+    /**
+     * @param representation  Internal representation of chromosome.
+     * @param length          length of chromosome
+     * @param fitnessFunction The {@link FitnessFunction}
+     * @param decoder         The {@link Decoder}
+     */
+    public BinaryChromosome(Long[] representation,
+            long length,
+            FitnessFunction<P> fitnessFunction,
+            Decoder<P> decoder) {
+        super(fitnessFunction, decoder);
+        Objects.requireNonNull(representation);
+        checkMaximumLength(length);
+        this.length = length;
+        this.representation = new long[representation.length];
+        for (int i = 0; i < representation.length; i++) {
+            this.representation[i] = representation[i];
+        }
+    }
+
+    /**
+     * @param inputRepresentation Internal representation of chromosome.
+     * @param length              length of chromosome
+     * @param fitnessFunction     The {@link FitnessFunction}
+     * @param decoder             The {@link Decoder}
+     */
+    public BinaryChromosome(long[] inputRepresentation,
+            long length,
+            FitnessFunction<P> fitnessFunction,
+            Decoder<P> decoder) {
+        super(fitnessFunction, decoder);
+        Objects.requireNonNull(inputRepresentation);
+        checkMaximumLength(length);
+        if (length <= (inputRepresentation.length - 1) * Long.SIZE || length > inputRepresentation.length * Long.SIZE) {
+            throw new GeneticException(GeneticException.ILLEGAL_ARGUMENT,
+                    "provided length does not match expected representation");
+        }
+        this.length = length;
+        this.representation = new long[inputRepresentation.length];
+        System.arraycopy(inputRepresentation, 0, representation, 0, inputRepresentation.length);
+    }
+
+    /**
+     * @param representation  Internal representation of chromosome.
+     * @param fitnessFunction The {@link FitnessFunction}
+     * @param decoder         The {@link Decoder}
+     */
+    public BinaryChromosome(String representation, FitnessFunction<P> fitnessFunction, Decoder<P> decoder) {
+        super(fitnessFunction, decoder);
+        Objects.requireNonNull(representation);
+        this.length = representation.length();
+        this.representation = encode(representation);
+    }
+
+    /**
+     * Checks the input chromosome length against predefined maximum length.
+     * @param chromosomeLength input chromsome length
+     */
+    protected void checkMaximumLength(long chromosomeLength) {
+        if (chromosomeLength > MAX_LENGTH) {
+            throw new GeneticException(GeneticException.ILLEGAL_ARGUMENT,
+                    "length exceeded the max length " + MAX_LENGTH);
+        }
+    }
+
+    /**
+     * Validates the string representation.
+     * @param stringRepresentation binary string representation of chromosome
+     */
+    private void validateStringRepresentation(String stringRepresentation) {
+        char allele = '\0';
+        final int chromosomeLength = stringRepresentation.length();
+        for (int i = 0; i < chromosomeLength; i++) {
+            if ((allele = stringRepresentation.charAt(i)) != '0' && allele != '1') {
+                throw new GeneticException(GeneticException.ILLEGAL_ARGUMENT,
+                        "Only 0 or 1 are acceptable as characters.");
+            }
+        }
+    }
+
+    /**
+     * encodes the binary string representation as an array of long.
+     * @param stringRepresentation binary string
+     * @return encoded representation
+     */
+    private long[] encode(String stringRepresentation) {
+        validateStringRepresentation(stringRepresentation);
+        final int chromosomeLength = stringRepresentation.length();
+        final int arraySize = (int) Math.ceil(chromosomeLength / (double) Long.SIZE);
+        final long[] encodedRepresentation = new long[arraySize];
+        final int offset = (int) (chromosomeLength % Long.SIZE == 0 ? 0 : Long.SIZE - chromosomeLength % Long.SIZE);
+        encodedRepresentation[0] = Long.parseUnsignedLong(stringRepresentation.substring(0, Long.SIZE - offset), 2);
+        for (int i = Long.SIZE - offset, j = 1; i < chromosomeLength; i += Long.SIZE, j++) {
+            encodedRepresentation[j] = Long.parseUnsignedLong(stringRepresentation.substring(i, i + Long.SIZE), 2);
+        }
+        return encodedRepresentation;
+    }
+
+    /**
+     * Returns the chromosome length.
+     * @return length
+     */
+    public long getLength() {
+        return length;
+    }
+
+    /**
+     * Returns the binary representation.
+     * @return representation
+     */
+    public long[] getRepresentation() {
+        final long[] clonedRepresentation = new long[representation.length];
+        System.arraycopy(representation, 0, clonedRepresentation, 0, representation.length);
+        return clonedRepresentation;
+    }
+
+    /**
+     * Returns the binary string representation of the chromosome.
+     * @return the string representation
+     */
+    public String getStringRepresentation() {
+        if (length > Integer.MAX_VALUE) {
+            throw new GeneticException(GeneticException.LENGTH_TOO_LARGE, length);
+        }
+        return getStringRepresentation(0, length);
+    }
+
+    /**
+     * Returns the binary string representation of the chromosome alleles from
+     * start(inclusive) to end(exclusive) index.
+     * @param start start allele/gene index(inclusive)
+     * @param end   end allele/gene index(exclusive)
+     * @return the string representation
+     */
+    public String getStringRepresentation(long start, long end) {
+        if (start >= end) {
+            throw new GeneticException(GeneticException.ILLEGAL_ARGUMENT,
+                    "start " + start + " is greater than end " + end);
+        }
+        if (end - start > Integer.MAX_VALUE) {
+            throw new GeneticException(GeneticException.LENGTH_TOO_LARGE, end - start);
+        }
+        final int offset = (int) (length % Long.SIZE == 0 ? 0 : Long.SIZE - length % Long.SIZE);
+        final long offsettedStart = offset + start;
+        final long offsettedEnd = offset + end;
+        final int startAlleleBlockIndex = (int) (offsettedStart / Long.SIZE);
+        final int endAlleleBlockIndex = (int) (offsettedEnd / Long.SIZE);
+        final int startAlleleElementIndex = (int) (offsettedStart % Long.SIZE);
+        final int endAlleleElementIndex = (int) (offsettedEnd % Long.SIZE);
+
+        if (startAlleleBlockIndex == endAlleleBlockIndex) {
+            return getAlleleBlockString(startAlleleBlockIndex).substring(startAlleleElementIndex,
+                    endAlleleElementIndex);
+        } else {
+            final StringBuilder allelesStrRepresentation = new StringBuilder();
+
+            // extract string representation of first allele block.
+            allelesStrRepresentation
+                    .append(getAlleleBlockString(startAlleleBlockIndex).substring(startAlleleElementIndex));
+
+            // extract string representation of all allele blocks except first and last.
+            for (int i = startAlleleBlockIndex + 1; i < endAlleleBlockIndex; i++) {
+                allelesStrRepresentation.append(getAlleleBlockString(i));
+            }
+
+            // extract string representation from last allele block if end allele index !=
+            // 0.
+            if (endAlleleElementIndex != 0) {
+                allelesStrRepresentation
+                        .append(getAlleleBlockString(endAlleleBlockIndex).substring(0, endAlleleElementIndex));
+            }
+
+            return allelesStrRepresentation.toString();
+        }
+    }
+
+    /**
+     * Returns the allele block as binary string representation.
+     * @param alleleBlockIndex index of allele block i.e. array element
+     * @return the string representation
+     */
+    private String getAlleleBlockString(final int alleleBlockIndex) {
+        return prepareZeroPrefix(representation[alleleBlockIndex] == 0 ? Long.SIZE - 1 :
+                Long.numberOfLeadingZeros(representation[alleleBlockIndex])) +
+                Long.toUnsignedString(representation[alleleBlockIndex], 2);
+    }
+
+    /**
+     * Prepares zero prefix for binary chromosome.
+     * @param count number of zeros
+     * @return prefix
+     */
+    private String prepareZeroPrefix(int count) {
+        final StringBuilder zeroPrefix = new StringBuilder();
+        for (int i = 0; i < count; i++) {
+            zeroPrefix.append('0');
+        }
+        return zeroPrefix.toString();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public FitnessFunction<P> getFitnessFunction() {
+        return super.getFitnessFunction();
+    }
+
+    /**
+     * Creates a new chromosome with provided parameters.
+     * @param chromosomeRepresentation the representation
+     * @param chromosomeLength         length of chromosome
+     * @return chromosome
+     */
+    public BinaryChromosome<P> newChromosome(long[] chromosomeRepresentation, long chromosomeLength) {
+        return new BinaryChromosome<P>(chromosomeRepresentation, chromosomeLength, getFitnessFunction(), getDecoder());
+    }
+
+    /**
+     * Creates an instance of Binary Chromosome with random binary representation.
+     * @param <P>             phenotype fo chromosome
+     * @param length          length of chromosome
+     * @param fitnessFunction The {@link FitnessFunction}
+     * @param decoder         The {@link Decoder}
+     * @return a binary chromosome
+     */
+    public static <P> BinaryChromosome<P> randomChromosome(int length,
+            FitnessFunction<P> fitnessFunction,
+            Decoder<P> decoder) {
+        return new BinaryChromosome<P>(ChromosomeRepresentationUtils.randomBinaryRepresentation(length), length,
+                fitnessFunction, decoder);
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/Chromosome.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/Chromosome.java
new file mode 100644
index 0000000..b29461c
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/Chromosome.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga.chromosome;
+
+/**
+ * This abstraction represents a chromosome.
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public interface Chromosome<P> extends Comparable<Chromosome<P>> {
+
+    /**
+     * Access the fitness of this chromosome. The bigger the fitness, the better the
+     * chromosome.
+     * <p>
+     * Computation of fitness is usually very time-consuming task, therefore the
+     * fitness is cached.
+     * @return the fitness
+     */
+    double evaluate();
+
+    /**
+     * Decodes the chromosome genotype and returns the phenotype.
+     * @return phenotype
+     */
+    P decode();
+
+    /**
+     * Returns unique Id of chromosome.
+     * @return id
+     */
+    String getId();
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/ChromosomePair.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/ChromosomePair.java
new file mode 100644
index 0000000..1157a00
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/ChromosomePair.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.chromosome;
+
+/**
+ * A pair of {@link Chromosome} objects.
+ * @param <P> phenotype of chromosome
+ * @since 2.0
+ */
+public class ChromosomePair<P> {
+
+    /** the first chromosome in the pair. */
+    private final Chromosome<P> first;
+
+    /** the second chromosome in the pair. */
+    private final Chromosome<P> second;
+
+    /**
+     * Create a chromosome pair.
+     * @param c1 the first chromosome.
+     * @param c2 the second chromosome.
+     */
+    public ChromosomePair(final Chromosome<P> c1, final Chromosome<P> c2) {
+        super();
+        first = c1;
+        second = c2;
+    }
+
+    /**
+     * Access the first chromosome.
+     *
+     * @return the first chromosome.
+     */
+    public Chromosome<P> getFirst() {
+        return first;
+    }
+
+    /**
+     * Access the second chromosome.
+     *
+     * @return the second chromosome.
+     */
+    public Chromosome<P> getSecond() {
+        return second;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String toString() {
+        return String.format("(%s,%s)", getFirst(), getSecond());
+    }
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/IntegralValuedChromosome.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/IntegralValuedChromosome.java
new file mode 100644
index 0000000..91fcfd2
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/IntegralValuedChromosome.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.chromosome;
+
+import java.util.List;
+
+import org.apache.commons.math4.ga.decoder.AbstractListChromosomeDecoder;
+import org.apache.commons.math4.ga.fitness.FitnessFunction;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.apache.commons.math4.ga.utils.ChromosomeRepresentationUtils;
+
+/**
+ * Chromosome represented by a list of integral values. The acceptable integral
+ * values should belong to the range min(inclusive) to max(exclusive).
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public class IntegralValuedChromosome<P> extends AbstractListChromosome<Integer, P> {
+
+    /** minimum acceptable value of allele. **/
+    private final int min;
+
+    /** maximum acceptable value of allele. **/
+    private final int max;
+
+    /**
+     * @param representation  Internal representation of chromosome.
+     * @param fitnessFunction The {@link FitnessFunction}
+     * @param decoder         The {@link AbstractListChromosomeDecoder}
+     * @param min             minimum inclusive value of allele
+     * @param max             maximum exclusive value of allele
+     */
+    public IntegralValuedChromosome(List<Integer> representation,
+            FitnessFunction<P> fitnessFunction,
+            AbstractListChromosomeDecoder<Integer, P> decoder,
+            int min,
+            int max) {
+        super(representation, fitnessFunction, decoder);
+        this.min = min;
+        this.max = max;
+        checkValidity();
+    }
+
+    /**
+     * @param representation  Internal representation of chromosome.
+     * @param fitnessFunction The {@link FitnessFunction}
+     * @param decoder         The {@link AbstractListChromosomeDecoder}
+     * @param min             minimum inclusive value of allele
+     * @param max             maximum exclusive value of allele
+     */
+    public IntegralValuedChromosome(Integer[] representation,
+            FitnessFunction<P> fitnessFunction,
+            AbstractListChromosomeDecoder<Integer, P> decoder,
+            int min,
+            int max) {
+        super(representation, fitnessFunction, decoder);
+        this.min = min;
+        this.max = max;
+        checkValidity();
+    }
+
+    /**
+     * Returns the minimum acceptable value of allele.
+     * @return minimum value
+     */
+    public int getMin() {
+        return min;
+    }
+
+    /**
+     * Returns the maximum acceptable value of allele.
+     * @return maximum value
+     */
+    public int getMax() {
+        return max;
+    }
+
+    /**
+     * Asserts that <code>representation</code> can represent a valid chromosome.
+     */
+    private void checkValidity() {
+        if (min >= max) {
+            throw new GeneticException(GeneticException.TOO_LARGE, min, max);
+        }
+        for (int i : getRepresentation()) {
+            if (i < min || i >= max) {
+                throw new GeneticException(GeneticException.ILLEGAL_ARGUMENT, i);
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public IntegralValuedChromosome<P> newChromosome(List<Integer> chromosomeRepresentation) {
+        return new IntegralValuedChromosome<>(chromosomeRepresentation, getFitnessFunction(), getDecoder(), this.min,
+                this.max);
+    }
+
+    /**
+     * Creates an instance of Integral valued Chromosome with random binary
+     * representation.
+     * @param <P>             phenotype fo chromosome
+     * @param length          length of chromosome
+     * @param fitnessFunction The {@link FitnessFunction}
+     * @param decoder         The {@link AbstractListChromosomeDecoder}
+     * @param min             minimum inclusive value of allele
+     * @param max             maximum exclusive value of allele
+     * @return an integral-valued chromosome
+     */
+    public static <P> IntegralValuedChromosome<P> randomChromosome(int length,
+            FitnessFunction<P> fitnessFunction,
+            AbstractListChromosomeDecoder<Integer, P> decoder,
+            int min,
+            int max) {
+        return new IntegralValuedChromosome<>(
+                ChromosomeRepresentationUtils.randomIntegralRepresentation(length, min, max), fitnessFunction, decoder,
+                min, max);
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/RealValuedChromosome.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/RealValuedChromosome.java
new file mode 100644
index 0000000..603a1e2
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/RealValuedChromosome.java
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.chromosome;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.commons.math4.ga.decoder.AbstractListChromosomeDecoder;
+import org.apache.commons.math4.ga.fitness.FitnessFunction;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.apache.commons.math4.ga.utils.ChromosomeRepresentationUtils;
+
+/**
+ * DoubleEncodedChromosome is used for representing chromosome encoded as
+ * Double. It is a vector of a fixed length of real numbers.The acceptable real
+ * values should belong to the range min(inclusive) to max(exclusive).
+ * <p>
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public class RealValuedChromosome<P> extends AbstractListChromosome<Double, P> {
+
+    /** minimum acceptable value of allele. **/
+    private final double min;
+
+    /** maximum acceptable value of allele. **/
+    private final double max;
+
+    /**
+     * @param representation  an array of real values
+     * @param fitnessFunction the fitness function
+     * @param decoder         the {@link AbstractListChromosomeDecoder}
+     */
+    public RealValuedChromosome(final List<Double> representation,
+            FitnessFunction<P> fitnessFunction,
+            AbstractListChromosomeDecoder<Double, P> decoder) {
+        super(representation, fitnessFunction, decoder);
+        this.min = 0;
+        this.max = 1d;
+        checkValidity();
+    }
+
+    /**
+     * @param representation  an array of real values
+     * @param fitnessFunction the fitness function
+     * @param decoder         the {@link AbstractListChromosomeDecoder}
+     * @param min             minimum inclusive value of allele
+     * @param max             maximum exclusive value of allele
+     */
+    public RealValuedChromosome(final List<Double> representation,
+            FitnessFunction<P> fitnessFunction,
+            AbstractListChromosomeDecoder<Double, P> decoder,
+            double min,
+            double max) {
+        super(representation, fitnessFunction, decoder);
+        this.min = min;
+        this.max = max;
+        checkValidity();
+    }
+
+    /**
+     * @param representation  Internal representation of chromosome as genotype
+     * @param fitnessFunction The {@link FitnessFunction}
+     * @param decoder         The {@link AbstractListChromosomeDecoder}
+     */
+    public RealValuedChromosome(final Double[] representation,
+            FitnessFunction<P> fitnessFunction,
+            AbstractListChromosomeDecoder<Double, P> decoder) {
+        this(Arrays.asList(representation), fitnessFunction, decoder);
+    }
+
+    /**
+     * @param representation  Internal representation of chromosome as genotype
+     * @param fitnessFunction The {@link FitnessFunction}
+     * @param decoder         The {@link AbstractListChromosomeDecoder}
+     * @param min             minimum inclusive value of allele
+     * @param max             maximum exclusive value of allele
+     */
+    public RealValuedChromosome(final Double[] representation,
+            FitnessFunction<P> fitnessFunction,
+            AbstractListChromosomeDecoder<Double, P> decoder,
+            double min,
+            double max) {
+        this(Arrays.asList(representation), fitnessFunction, decoder, min, max);
+    }
+
+    /**
+     * Return the minimum allele value.
+     * @return minimum
+     */
+    public double getMin() {
+        return min;
+    }
+
+    /**
+     * Returns the maximum allele value.
+     * @return maximum
+     */
+    public double getMax() {
+        return max;
+    }
+
+    /**
+     * Asserts that <code>representation</code> can represent a valid chromosome.
+     */
+    private void checkValidity() {
+        if (min >= max) {
+            throw new GeneticException(GeneticException.TOO_LARGE, min, max);
+        }
+        for (double i : getRepresentation()) {
+            if (i < min || i >= max) {
+                throw new GeneticException(GeneticException.ILLEGAL_ARGUMENT, i);
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public RealValuedChromosome<P> newChromosome(List<Double> chromosomeRepresentation) {
+        return new RealValuedChromosome<>(chromosomeRepresentation, getFitnessFunction(), getDecoder(), this.min,
+                this.max);
+    }
+
+    /**
+     * Creates an instance of RealValued chromosome with randomly generated
+     * representation.
+     * @param <P>             phenotype of chromosome
+     * @param length          length of chromosome genotype
+     * @param fitnessFunction The {@link FitnessFunction}
+     * @param decoder         The {@link AbstractListChromosomeDecoder}
+     * @param min             minimum inclusive value generated as allele
+     * @param max             maximum exclusive value generated as allele
+     * @return A real-valued chromosome
+     */
+    public static <P> RealValuedChromosome<P> randomChromosome(int length,
+            FitnessFunction<P> fitnessFunction,
+            AbstractListChromosomeDecoder<Double, P> decoder,
+            double min,
+            double max) {
+        return new RealValuedChromosome<>(ChromosomeRepresentationUtils.randomDoubleRepresentation(length, min, max),
+                fitnessFunction, decoder, min, max);
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/package-info.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/package-info.java
new file mode 100644
index 0000000..196ddd9
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/chromosome/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.ga.chromosome;
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/convergence/FixedElapsedTime.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/convergence/FixedElapsedTime.java
new file mode 100644
index 0000000..8fda02b
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/convergence/FixedElapsedTime.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.convergence;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.apache.commons.math4.ga.population.Population;
+
+/**
+ * Stops after a fixed amount of time has elapsed.
+ * <p>
+ * The first time {@link #isSatisfied(Population)} is invoked, the end time of
+ * the evolution is determined based on the provided <code>maxTime</code> value.
+ * Once the elapsed time reaches the configured <code>maxTime</code> value,
+ * {@link #isSatisfied(Population)} returns true.
+ *
+ * @param <P> phenotype of chromosome
+ * @since 3.1
+ */
+public class FixedElapsedTime<P> implements StoppingCondition<P> {
+
+    /** Maximum allowed time period (in nanoseconds). */
+    private final long maxTimePeriod;
+
+    /** The predetermined termination time (stopping condition). */
+    private long endTime = -1;
+
+    /**
+     * Create a new {@link FixedElapsedTime} instance.
+     *
+     * @param maxTime maximum number of seconds generations are allowed to evolve
+     */
+    public FixedElapsedTime(final long maxTime) {
+        this(maxTime, TimeUnit.SECONDS);
+    }
+
+    /**
+     * Create a new {@link FixedElapsedTime} instance.
+     *
+     * @param maxTime maximum time generations are allowed to evolve
+     * @param unit    {@link TimeUnit} of the maxTime argument
+     */
+    public FixedElapsedTime(final long maxTime, final TimeUnit unit) {
+        if (maxTime < 0) {
+            throw new GeneticException(GeneticException.TOO_SMALL, maxTime, 0);
+        }
+        maxTimePeriod = unit.toNanos(maxTime);
+    }
+
+    /**
+     * Determine whether or not the maximum allowed time has passed. The termination
+     * time is determined after the first generation.
+     *
+     * @return <code>true</code> IFF the maximum allowed time period has elapsed
+     */
+    @Override
+    public boolean isSatisfied(Population<P> population) {
+        if (endTime < 0) {
+            endTime = System.nanoTime() + maxTimePeriod;
+        }
+
+        return System.nanoTime() >= endTime;
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/convergence/FixedGenerationCount.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/convergence/FixedGenerationCount.java
new file mode 100644
index 0000000..37cfff9
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/convergence/FixedGenerationCount.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.convergence;
+
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.apache.commons.math4.ga.population.Population;
+
+/**
+ * Stops after a fixed number of generations.
+ * <p>
+ * Each time {@link #isSatisfied(Population)} is invoked, a generation counter
+ * is incremented. Once the counter reaches the configured
+ * {@code maxGenerations} value, {@link #isSatisfied(Population)} returns true.
+ *
+ * @param <P> phenotype of chromosome
+ * @since 2.0
+ */
+public class FixedGenerationCount<P> implements StoppingCondition<P> {
+    /** Number of generations that have passed. */
+    private int numGenerations;
+
+    /** Maximum number of generations (stopping criteria). */
+    private final int maxGenerations;
+
+    /**
+     * Create a new FixedGenerationCount instance.
+     *
+     * @param maxGenerations number of generations to evolve
+     */
+    public FixedGenerationCount(final int maxGenerations) {
+        if (maxGenerations <= 0) {
+            throw new GeneticException(GeneticException.TOO_SMALL, maxGenerations, 1);
+        }
+        this.maxGenerations = maxGenerations;
+    }
+
+    /**
+     * Determine whether or not the given number of generations have passed.
+     * Increments the number of generations counter if the maximum has not been
+     * reached.
+     *
+     * @return <code>true</code> IFF the maximum number of generations has been
+     *         exceeded
+     */
+    @Override
+    public boolean isSatisfied(Population<P> population) {
+        if (this.numGenerations < this.maxGenerations) {
+            numGenerations++;
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Returns the number of generations that have already passed.
+     * @return the number of generations that have passed
+     */
+    public int getNumGenerations() {
+        return numGenerations;
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/convergence/StoppingCondition.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/convergence/StoppingCondition.java
new file mode 100644
index 0000000..601c098
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/convergence/StoppingCondition.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.convergence;
+
+import org.apache.commons.math4.ga.population.Population;
+
+/**
+ * Algorithm used to determine when to stop evolution.
+ *
+ * @param <P> phenotype of chromosome
+ * @since 2.0
+ */
+public interface StoppingCondition<P> {
+
+    /**
+     * Determine whether or not the given population satisfies the stopping
+     * condition.
+     * @param population population of chromosome
+     *
+     * @return <code>true</code> if this stopping condition is met by the given
+     *         population, <code>false</code> otherwise.
+     */
+    boolean isSatisfied(Population<P> population);
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/convergence/UnchangedBestFitness.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/convergence/UnchangedBestFitness.java
new file mode 100644
index 0000000..2281b2a
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/convergence/UnchangedBestFitness.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga.convergence;
+
+import org.apache.commons.math4.ga.population.Population;
+
+/**
+ * This class represents a stopping condition based on best fitness value.
+ * Convergence will be stopped once best fitness remains unchanged for
+ * predefined number of generations.
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public class UnchangedBestFitness<P> implements StoppingCondition<P> {
+
+    /** best fitness of previous generation. **/
+    private double lastBestFitness = Double.MIN_VALUE;
+
+    /**
+     * The configured number of generations for which optimization process will
+     * continue with unchanged best fitness value.
+     **/
+    private final int maxGenerationsWithUnchangedBestFitness;
+
+    /** Number of generations the best fitness value has not been changed. **/
+    private int generationsHavingUnchangedBestFitness;
+
+    /**
+     * @param maxGenerationsWithUnchangedAverageFitness maximum number of
+     *                                                  generations with unchanged
+     *                                                  best fitness
+     */
+    public UnchangedBestFitness(final int maxGenerationsWithUnchangedAverageFitness) {
+        this.maxGenerationsWithUnchangedBestFitness = maxGenerationsWithUnchangedAverageFitness;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean isSatisfied(Population<P> population) {
+        final double currentBestFitness = population.getFittestChromosome().evaluate();
+
+        if (lastBestFitness == currentBestFitness) {
+            generationsHavingUnchangedBestFitness++;
+            if (generationsHavingUnchangedBestFitness == maxGenerationsWithUnchangedBestFitness) {
+                return true;
+            }
+        } else {
+            this.generationsHavingUnchangedBestFitness = 0;
+            lastBestFitness = currentBestFitness;
+        }
+
+        return false;
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/convergence/UnchangedMeanFitness.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/convergence/UnchangedMeanFitness.java
new file mode 100644
index 0000000..a729e0a
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/convergence/UnchangedMeanFitness.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga.convergence;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.population.Population;
+
+/**
+ * This class represents a stopping condition based on mean fitness value.
+ * Convergence will be stopped once mean fitness remains unchanged for
+ * predefined number of generations.
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public class UnchangedMeanFitness<P> implements StoppingCondition<P> {
+
+    /** Mean fitness of previous generation. **/
+    private double lastMeanFitness = Double.MIN_VALUE;
+
+    /**
+     * The configured number of generations for which optimization process will
+     * continue with unchanged best fitness value.
+     **/
+    private final int maxGenerationsWithUnchangedMeanFitness;
+
+    /** Number of generations the mean fitness value has not been changed. **/
+    private int generationsHavingUnchangedMeanFitness;
+
+    /**
+     * @param maxGenerationsWithUnchangedMeanFitness maximum number of generations
+     *                                               with unchanged mean fitness
+     */
+    public UnchangedMeanFitness(final int maxGenerationsWithUnchangedMeanFitness) {
+        this.maxGenerationsWithUnchangedMeanFitness = maxGenerationsWithUnchangedMeanFitness;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean isSatisfied(Population<P> population) {
+
+        final double currentMeanFitness = calculateMeanFitness(population);
+
+        if (lastMeanFitness == currentMeanFitness) {
+            generationsHavingUnchangedMeanFitness++;
+            if (generationsHavingUnchangedMeanFitness == maxGenerationsWithUnchangedMeanFitness) {
+                return true;
+            }
+        } else {
+            this.generationsHavingUnchangedMeanFitness = 0;
+            lastMeanFitness = currentMeanFitness;
+        }
+
+        return false;
+    }
+
+    /**
+     * calculates mean fitness of the population.
+     * @param population
+     * @return mean fitness
+     */
+    private double calculateMeanFitness(Population<P> population) {
+        double totalFitness = 0.0;
+        for (Chromosome<P> chromosome : population) {
+            totalFitness += chromosome.evaluate();
+        }
+        return totalFitness / population.getPopulationSize();
+    }
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/convergence/package-info.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/convergence/package-info.java
new file mode 100644
index 0000000..d386944
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/convergence/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.ga.convergence;
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/AbstractChromosomeCrossoverPolicy.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/AbstractChromosomeCrossoverPolicy.java
new file mode 100644
index 0000000..c56434d
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/AbstractChromosomeCrossoverPolicy.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga.crossover;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.chromosome.ChromosomePair;
+import org.apache.commons.math4.ga.utils.RandomProviderManager;
+
+/**
+ * An abstraction to represent the base crossover policy.
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public abstract class AbstractChromosomeCrossoverPolicy<P> implements CrossoverPolicy<P> {
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public ChromosomePair<P> crossover(final Chromosome<P> first,
+            final Chromosome<P> second,
+            final double crossoverRate) {
+        if (RandomProviderManager.getRandomProvider().nextDouble() < crossoverRate) {
+            return crossover(first, second);
+        } else {
+            return new ChromosomePair<>(first, second);
+        }
+    }
+
+    /**
+     * Performs crossover of two chromosomes.
+     * @param first  The first parent chromosome participating in crossover
+     * @param second The second parent chromosome participating in crossover
+     * @return chromosome pair
+     */
+    protected abstract ChromosomePair<P> crossover(Chromosome<P> first, Chromosome<P> second);
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/AbstractListChromosomeCrossoverPolicy.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/AbstractListChromosomeCrossoverPolicy.java
new file mode 100644
index 0000000..2184310
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/AbstractListChromosomeCrossoverPolicy.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga.crossover;
+
+import org.apache.commons.math4.ga.chromosome.AbstractListChromosome;
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.chromosome.ChromosomePair;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+
+/**
+ * An abstraction of crossover policy for list chromosomes.
+ * @param <T> genetype of chromosome
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public abstract class AbstractListChromosomeCrossoverPolicy<T, P> extends AbstractChromosomeCrossoverPolicy<P> {
+
+    /**
+     * {@inheritDoc}
+     */
+    @SuppressWarnings("unchecked")
+    @Override
+    public ChromosomePair<P> crossover(final Chromosome<P> first, final Chromosome<P> second) {
+        // check for validity.
+        checkValidity(first, second);
+
+        final AbstractListChromosome<T, P> firstListChromosome = (AbstractListChromosome<T, P>) first;
+        final AbstractListChromosome<T, P> secondListChromosome = (AbstractListChromosome<T, P>) second;
+
+        return mate(firstListChromosome, secondListChromosome);
+    }
+
+    /**
+     * Validates the chromosome pair.
+     * @param first  first chromosome
+     * @param second second chromosome
+     */
+    @SuppressWarnings("unchecked")
+    protected void checkValidity(final Chromosome<P> first, final Chromosome<P> second) {
+        if (!(first instanceof AbstractListChromosome<?, ?> && second instanceof AbstractListChromosome<?, ?>)) {
+            throw new GeneticException(GeneticException.INVALID_FIXED_LENGTH_CHROMOSOME);
+        }
+        final AbstractListChromosome<T, P> firstListChromosome = (AbstractListChromosome<T, P>) first;
+        final AbstractListChromosome<T, P> secondListChromosome = (AbstractListChromosome<T, P>) second;
+
+        final int length = firstListChromosome.getLength();
+        if (length != secondListChromosome.getLength()) {
+            throw new GeneticException(GeneticException.SIZE_MISMATCH, secondListChromosome.getLength(), length);
+        }
+
+    }
+
+    /**
+     * Performs mating between two chromosomes and returns the offspring pair.
+     * @param first  The first parent chromosome participating in crossover
+     * @param second The second parent chromosome participating in crossover
+     * @return chromosome pair
+     */
+    protected abstract ChromosomePair<P> mate(AbstractListChromosome<T, P> first, AbstractListChromosome<T, P> second);
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/CrossoverPolicy.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/CrossoverPolicy.java
new file mode 100644
index 0000000..65aa191
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/CrossoverPolicy.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.crossover;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.chromosome.ChromosomePair;
+
+/**
+ * Policy used to create a pair of new chromosomes by performing a crossover
+ * operation on a source pair of chromosomes.
+ * @param <P> phenotype of chromosome
+ * @since 2.0
+ */
+public interface CrossoverPolicy<P> {
+
+    /**
+     * Perform a crossover operation on the given chromosomes.
+     *
+     * @param first         the first chromosome.
+     * @param second        the second chromosome.
+     * @param crossoverRate the probability of crossover
+     * @return the pair of new chromosomes that resulted from the crossover.
+     */
+    ChromosomePair<P> crossover(Chromosome<P> first, Chromosome<P> second, double crossoverRate);
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/CycleCrossover.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/CycleCrossover.java
new file mode 100644
index 0000000..1d0da03
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/CycleCrossover.java
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.crossover;
+
+import java.util.ArrayList;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.math4.ga.chromosome.AbstractListChromosome;
+import org.apache.commons.math4.ga.chromosome.ChromosomePair;
+import org.apache.commons.math4.ga.utils.RandomProviderManager;
+
+/**
+ * Cycle Crossover [CX] builds offspring from <b>ordered</b> chromosomes by
+ * identifying cycles between two parent chromosomes. To form the children, the
+ * cycles are copied from the respective parents.
+ * <p>
+ * To form a cycle the following procedure is applied:
+ * <ol>
+ * <li>start with the first gene of parent 1</li>
+ * <li>look at the gene at the same position of parent 2</li>
+ * <li>go to the position with the same gene in parent 1</li>
+ * <li>add this gene index to the cycle</li>
+ * <li>repeat the steps 2-5 until we arrive at the starting gene of this
+ * cycle</li>
+ * </ol>
+ * The indices that form a cycle are then used to form the children in
+ * alternating order, i.e. in cycle 1, the genes of parent 1 are copied to child
+ * 1, while in cycle 2 the genes of parent 1 are copied to child 2, and so forth
+ * ...
+ *
+ * Example (zero-start cycle):
+ * <pre>
+ * p1 = (8 4 7 3 6 2 5 1 9 0)    X   c1 = (8 1 2 3 4 5 6 7 9 0)
+ * p2 = (0 1 2 3 4 5 6 7 8 9)    X   c2 = (0 4 7 3 6 2 5 1 8 9)
+ *
+ * cycle 1: 8 0 9
+ * cycle 2: 4 1 7 2 5 6
+ * cycle 3: 3
+ * </pre>
+ *
+ * This policy works only on {@link AbstractListChromosome}, and therefore it is
+ * parameterized by T. Moreover, the chromosomes must have same lengths.
+ *
+ * @see <a href=
+ *      "http://www.rubicite.com/Tutorials/GeneticAlgorithms/CrossoverOperators/CycleCrossoverOperator.aspx">
+ *      Cycle Crossover Operator</a>
+ * @param <T> generic type of the {@link AbstractListChromosome}s for crossover
+ * @param <P> phenotype of chromosome
+ * @since 3.1
+ */
+public class CycleCrossover<T, P> extends AbstractListChromosomeCrossoverPolicy<T, P> {
+
+    /** If the start index shall be chosen randomly. */
+    private final boolean randomStart;
+
+    /**
+     * Creates a new {@link CycleCrossover} policy.
+     */
+    public CycleCrossover() {
+        this(false);
+    }
+
+    /**
+     * Creates a new {@link CycleCrossover} policy using the given
+     * {@code randomStart} behavior.
+     *
+     * @param randomStart whether the start index shall be chosen randomly or be set
+     *                    to 0
+     */
+    public CycleCrossover(final boolean randomStart) {
+        this.randomStart = randomStart;
+    }
+
+    /**
+     * Returns whether the starting index is chosen randomly or set to zero.
+     *
+     * @return {@code true} if the starting index is chosen randomly, {@code false}
+     *         otherwise
+     */
+    public boolean isRandomStart() {
+        return randomStart;
+    }
+
+    /**
+     * Helper for {@link #crossover(Chromosome, Chromosome, double)}. Performs the
+     * actual crossover.
+     *
+     * @param first  the first chromosome
+     * @param second the second chromosome
+     * @return the pair of new chromosomes that resulted from the crossover
+     */
+    @Override
+    protected ChromosomePair<P> mate(final AbstractListChromosome<T, P> first,
+            final AbstractListChromosome<T, P> second) {
+
+        final int length = first.getLength();
+        // array representations of the parents
+        final List<T> parent1Rep = first.getRepresentation();
+        final List<T> parent2Rep = second.getRepresentation();
+        // and of the children: do a crossover copy to simplify the later processing
+        final List<T> child1Rep = new ArrayList<>(second.getRepresentation());
+        final List<T> child2Rep = new ArrayList<>(first.getRepresentation());
+
+        // the set of all visited indices so far
+        final Set<Integer> visitedIndices = new HashSet<>(length);
+        // the indices of the current cycle
+        final List<Integer> indices = new ArrayList<>(length);
+
+        // determine the starting index
+        int idx = randomStart ? RandomProviderManager.getRandomProvider().nextInt(length) : 0;
+        int cycle = 1;
+
+        while (visitedIndices.size() < length) {
+            indices.add(idx);
+
+            T item = parent2Rep.get(idx);
+            idx = parent1Rep.indexOf(item);
+
+            while (idx != indices.get(0)) {
+                // add that index to the cycle indices
+                indices.add(idx);
+                // get the item in the second parent at that index
+                item = parent2Rep.get(idx);
+                // get the index of that item in the first parent
+                idx = parent1Rep.indexOf(item);
+            }
+
+            // for even cycles: swap the child elements on the indices found in this cycle
+            if (cycle++ % 2 != 0) {
+                for (int i : indices) {
+                    final T tmp = child1Rep.get(i);
+                    child1Rep.set(i, child2Rep.get(i));
+                    child2Rep.set(i, tmp);
+                }
+            }
+
+            visitedIndices.addAll(indices);
+            // find next starting index: last one + 1 until we find an unvisited index
+            idx = (indices.get(0) + 1) % length;
+            while (visitedIndices.contains(idx) && visitedIndices.size() < length) {
+                idx++;
+                if (idx >= length) {
+                    idx = 0;
+                }
+            }
+            indices.clear();
+        }
+
+        return new ChromosomePair<>(first.newChromosome(child1Rep), second.newChromosome(child2Rep));
+    }
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/NPointCrossover.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/NPointCrossover.java
new file mode 100644
index 0000000..f0313c1
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/NPointCrossover.java
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.crossover;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.math4.ga.chromosome.AbstractListChromosome;
+import org.apache.commons.math4.ga.chromosome.ChromosomePair;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.apache.commons.math4.ga.utils.RandomProviderManager;
+import org.apache.commons.rng.UniformRandomProvider;
+
+/**
+ * N-point crossover policy. For each iteration a random crossover point is
+ * selected and the first part from each parent is copied to the corresponding
+ * child, and the second parts are copied crosswise.
+ *
+ * Example (2-point crossover):
+ * <pre>
+ * -C- denotes a crossover point
+ *           -C-       -C-                         -C-        -C-
+ * p1 = (1 0  | 1 0 0 1 | 0 1 1)    X    p2 = (0 1  | 1 0 1 0  | 1 1 1)
+ *      \----/ \-------/ \-----/              \----/ \--------/ \-----/
+ *        ||      (*)       ||                  ||      (**)       ||
+ *        VV      (**)      VV                  VV      (*)        VV
+ *      /----\ /--------\ /-----\             /----\ /--------\ /-----\
+ * c1 = (1 0  | 1 0 1 0  | 0 1 1)    X   c2 = (0 1  | 1 0 0 1  | 0 1 1)
+ * </pre>
+ *
+ * This policy works only on {@link AbstractListChromosome}, and therefore it is
+ * parameterized by T. Moreover, the chromosomes must have same lengths.
+ *
+ * @param <T> generic type of the {@link AbstractListChromosome}s for crossover
+ * @param <P> phenotype of chromosome
+ * @since 3.1
+ */
+public class NPointCrossover<T, P> extends AbstractListChromosomeCrossoverPolicy<T, P> {
+
+    /** The number of crossover points. */
+    private final int crossoverPoints;
+
+    /**
+     * Creates a new {@link NPointCrossover} policy using the given number of
+     * points.
+     * <p>
+     * <b>Note</b>: the number of crossover points must be &lt;
+     * <code>chromosome length - 1</code>. This condition can only be checked at
+     * runtime, as the chromosome length is not known in advance.
+     *
+     * @param crossoverPoints the number of crossover points
+     */
+    public NPointCrossover(final int crossoverPoints) {
+        if (crossoverPoints <= 0) {
+            throw new GeneticException(GeneticException.NOT_STRICTLY_POSITIVE, crossoverPoints);
+        }
+        this.crossoverPoints = crossoverPoints;
+    }
+
+    /**
+     * Returns the number of crossover points used by this {@link CrossoverPolicy}.
+     *
+     * @return the number of crossover points
+     */
+    public int getCrossoverPoints() {
+        return crossoverPoints;
+    }
+
+    /**
+     * Performs a N-point crossover. N random crossover points are selected and are
+     * used to divide the parent chromosomes into segments. The segments are copied
+     * in alternate order from the two parents to the corresponding child
+     * chromosomes.
+     *
+     * Example (2-point crossover):
+     * <pre>
+     * -C- denotes a crossover point
+     *           -C-       -C-                         -C-        -C-
+     * p1 = (1 0  | 1 0 0 1 | 0 1 1)    X    p2 = (0 1  | 1 0 1 0  | 1 1 1)
+     *      \----/ \-------/ \-----/              \----/ \--------/ \-----/
+     *        ||      (*)       ||                  ||      (**)       ||
+     *        VV      (**)      VV                  VV      (*)        VV
+     *      /----\ /--------\ /-----\             /----\ /--------\ /-----\
+     * c1 = (1 0  | 1 0 1 0  | 0 1 1)    X   c2 = (0 1  | 1 0 0 1  | 0 1 1)
+     * </pre>
+     *
+     * @param first  first parent (p1)
+     * @param second second parent (p2)
+     * @return pair of two children (c1,c2)
+     */
+    @Override
+    protected ChromosomePair<P> mate(final AbstractListChromosome<T, P> first,
+            final AbstractListChromosome<T, P> second) {
+
+        final int length = first.getLength();
+        if (crossoverPoints >= length) {
+            throw new GeneticException(GeneticException.TOO_LARGE, crossoverPoints, length);
+        }
+
+        // array representations of the parents
+        final List<T> parent1Rep = first.getRepresentation();
+        final List<T> parent2Rep = second.getRepresentation();
+        // and of the children
+        final List<T> child1Rep = new ArrayList<>(length);
+        final List<T> child2Rep = new ArrayList<>(length);
+
+        final UniformRandomProvider random = RandomProviderManager.getRandomProvider();
+
+        List<T> c1 = child1Rep;
+        List<T> c2 = child2Rep;
+
+        int remainingPoints = crossoverPoints;
+        int lastIndex = 0;
+        for (int i = 0; i < crossoverPoints; i++, remainingPoints--) {
+            // select the next crossover point at random
+            final int crossoverIndex = 1 + lastIndex + random.nextInt(length - lastIndex - remainingPoints);
+
+            // copy the current segment
+            for (int j = lastIndex; j < crossoverIndex; j++) {
+                c1.add(parent1Rep.get(j));
+                c2.add(parent2Rep.get(j));
+            }
+
+            // swap the children for the next segment
+            final List<T> tmp = c1;
+            c1 = c2;
+            c2 = tmp;
+
+            lastIndex = crossoverIndex;
+        }
+
+        // copy the last segment
+        for (int j = lastIndex; j < length; j++) {
+            c1.add(parent1Rep.get(j));
+            c2.add(parent2Rep.get(j));
+        }
+
+        return new ChromosomePair<>(first.newChromosome(child1Rep), second.newChromosome(child2Rep));
+    }
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/OnePointBinaryCrossover.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/OnePointBinaryCrossover.java
new file mode 100644
index 0000000..f860798
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/OnePointBinaryCrossover.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.crossover;
+
+import org.apache.commons.math4.ga.chromosome.BinaryChromosome;
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.chromosome.ChromosomePair;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.apache.commons.math4.ga.utils.RandomProviderManager;
+
+/**
+ * OnePoint Crossover Policy for Binary chromosomes.
+ * @param <P> the phenotype
+ */
+public class OnePointBinaryCrossover<P> extends AbstractChromosomeCrossoverPolicy<P> {
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected ChromosomePair<P> crossover(Chromosome<P> first, Chromosome<P> second) {
+
+        if (!(first instanceof BinaryChromosome<?> && second instanceof BinaryChromosome<?>)) {
+            throw new GeneticException(GeneticException.INVALID_FIXED_LENGTH_CHROMOSOME);
+        }
+        final BinaryChromosome<P> firstChromosome = (BinaryChromosome<P>) first;
+        final BinaryChromosome<P> secondChromosome = (BinaryChromosome<P>) second;
+
+        final long alleleCount = firstChromosome.getLength();
+
+        // array representations of the parents
+        final long[] parent1Rep = firstChromosome.getRepresentation();
+        final long[] parent2Rep = secondChromosome.getRepresentation();
+
+        // and of the children
+        final long[] child1Rep = new long[parent1Rep.length];
+        final long[] child2Rep = new long[parent2Rep.length];
+
+        // select a crossover point at random (0 and length makes no sense)
+        final long crossoverIndex = 1 + (RandomProviderManager.getRandomProvider().nextLong(alleleCount - 1));
+
+        final int offset = (int) (alleleCount % Long.SIZE == 0 ? 0 : Long.SIZE - alleleCount % Long.SIZE);
+        final long offsettedCrossoverIndex = crossoverIndex + offset;
+
+        final int crossoverBlockIndex = (int) (offsettedCrossoverIndex / Long.SIZE);
+        final int crossoverBlockAlleleIndex = (int) offsettedCrossoverIndex % Long.SIZE;
+
+        if (crossoverBlockAlleleIndex == 0) {
+            // if the offsetted-crossover index is divisible by
+            // Long.SIZE then first copy all
+            // elements of previous array elements.
+            for (int i = 0; i < crossoverBlockIndex; i++) {
+                child1Rep[i] = parent1Rep[i];
+                child2Rep[i] = parent2Rep[i];
+            }
+            // copy all elements from crossover block index.
+            for (int i = crossoverBlockIndex; i < parent1Rep.length; i++) {
+                child1Rep[i] = parent2Rep[i];
+                child2Rep[i] = parent1Rep[i];
+            }
+        } else {
+            // copy all parent array elements to child till crossover block index - 1.
+            for (int i = 0; i < crossoverBlockIndex; i++) {
+                child1Rep[i] = parent1Rep[i];
+                child2Rep[i] = parent2Rep[i];
+            }
+            // do exchange of alleles of the array element indexed at crossover block index.
+            final long parent1CrossoverBlockRep = parent1Rep[crossoverBlockIndex];
+            final long parent2CrossoverBlockRep = parent2Rep[crossoverBlockIndex];
+            final long leftMask = Long.MIN_VALUE >> crossoverBlockAlleleIndex - 1;
+            final long rightMask = crossoverBlockAlleleIndex != 1 ?
+                    (long) Math.pow(2, Long.SIZE - crossoverBlockAlleleIndex) - 1 :
+                    Long.MAX_VALUE;
+
+            final long child1CrossoverBlockRep = (parent1CrossoverBlockRep & leftMask) |
+                    (parent2CrossoverBlockRep & rightMask);
+            final long child2CrossoverBlockRep = (parent2CrossoverBlockRep & leftMask) |
+                    (parent1CrossoverBlockRep & rightMask);
+
+            child1Rep[crossoverBlockIndex] = child1CrossoverBlockRep;
+            child2Rep[crossoverBlockIndex] = child2CrossoverBlockRep;
+
+            // Copy all the alleles which belong to array elements having index >
+            // crossover block index.
+            if (crossoverBlockIndex < parent1Rep.length - 1) {
+                for (int i = crossoverBlockIndex + 1; i < parent1Rep.length; i++) {
+                    child1Rep[i] = parent2Rep[i];
+                    child2Rep[i] = parent1Rep[i];
+                }
+            }
+        }
+
+        final BinaryChromosome<P> childChromosome1 = new BinaryChromosome<>(child1Rep, alleleCount,
+                firstChromosome.getFitnessFunction(), firstChromosome.getDecoder());
+        final BinaryChromosome<P> childChromosome2 = new BinaryChromosome<>(child2Rep, alleleCount,
+                secondChromosome.getFitnessFunction(), secondChromosome.getDecoder());
+
+        return new ChromosomePair<>(childChromosome1, childChromosome2);
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/OnePointCrossover.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/OnePointCrossover.java
new file mode 100644
index 0000000..2c6da54
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/OnePointCrossover.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.crossover;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.math4.ga.chromosome.AbstractListChromosome;
+import org.apache.commons.math4.ga.chromosome.ChromosomePair;
+import org.apache.commons.math4.ga.utils.RandomProviderManager;
+
+/**
+ * One point crossover policy. A random crossover point is selected and the
+ * first part from each parent is copied to the corresponding child, and the
+ * second parts are copied crosswise.
+ *
+ * Example:
+ * <pre>
+ * -C- denotes a crossover point
+ *                   -C-                                 -C-
+ * p1 = (1 0 1 0 0 1  | 0 1 1)    X    p2 = (0 1 1 0 1 0  | 1 1 1)
+ *      \------------/ \-----/              \------------/ \-----/
+ *            ||         (*)                       ||        (**)
+ *            VV         (**)                      VV        (*)
+ *      /------------\ /-----\              /------------\ /-----\
+ * c1 = (1 0 1 0 0 1  | 1 1 1)    X    c2 = (0 1 1 0 1 0  | 0 1 1)
+ * </pre>
+ *
+ * This policy works only on {@link AbstractListChromosome}, and therefore it is
+ * parameterized by T. Moreover, the chromosomes must have same lengths.
+ *
+ * @param <T> generic type of the {@link AbstractListChromosome}s for crossover
+ * @param <P> phenotype of chromosome
+ * @since 2.0
+ *
+ */
+public class OnePointCrossover<T, P> extends AbstractListChromosomeCrossoverPolicy<T, P> {
+
+    /**
+     * Performs one point crossover. A random crossover point is selected and the
+     * first part from each parent is copied to the corresponding child, and the
+     * second parts are copied crosswise.
+     *
+     * Example:
+     * <pre>
+     * -C- denotes a crossover point
+     *                   -C-                                 -C-
+     * p1 = (1 0 1 0 0 1  | 0 1 1)    X    p2 = (0 1 1 0 1 0  | 1 1 1)
+     *      \------------/ \-----/              \------------/ \-----/
+     *            ||         (*)                       ||        (**)
+     *            VV         (**)                      VV        (*)
+     *      /------------\ /-----\              /------------\ /-----\
+     * c1 = (1 0 1 0 0 1  | 1 1 1)    X    c2 = (0 1 1 0 1 0  | 0 1 1)
+     * </pre>
+     *
+     * @param first  first parent (p1)
+     * @param second second parent (p2)
+     * @return pair of two children (c1,c2)
+     */
+    @Override
+    protected ChromosomePair<P> mate(final AbstractListChromosome<T, P> first,
+            final AbstractListChromosome<T, P> second) {
+        final int length = first.getLength();
+        // array representations of the parents
+        final List<T> parent1Rep = first.getRepresentation();
+        final List<T> parent2Rep = second.getRepresentation();
+        // and of the children
+        final List<T> child1Rep = new ArrayList<>(length);
+        final List<T> child2Rep = new ArrayList<>(length);
+
+        // select a crossover point at random (0 and length makes no sense)
+        final int crossoverIndex = 1 + (RandomProviderManager.getRandomProvider().nextInt(length - 1));
+
+        // copy the first part
+        for (int i = 0; i < crossoverIndex; i++) {
+            child1Rep.add(parent1Rep.get(i));
+            child2Rep.add(parent2Rep.get(i));
+        }
+        // and switch the second part
+        for (int i = crossoverIndex; i < length; i++) {
+            child1Rep.add(parent2Rep.get(i));
+            child2Rep.add(parent1Rep.get(i));
+        }
+
+        return new ChromosomePair<>(first.newChromosome(child1Rep), second.newChromosome(child2Rep));
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/OrderedCrossover.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/OrderedCrossover.java
new file mode 100644
index 0000000..24608f9
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/OrderedCrossover.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.crossover;
+
+import java.util.ArrayList;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.math4.ga.chromosome.AbstractListChromosome;
+import org.apache.commons.math4.ga.chromosome.ChromosomePair;
+import org.apache.commons.math4.ga.utils.RandomProviderManager;
+import org.apache.commons.rng.UniformRandomProvider;
+
+/**
+ * Order 1 Crossover [OX1] builds offspring from <b>ordered</b> chromosomes by
+ * copying a consecutive slice from one parent, and filling up the remaining
+ * genes from the other parent as they appear.
+ * <p>
+ * This policy works by applying the following rules:
+ * <ol>
+ * <li>select a random slice of consecutive genes from parent 1</li>
+ * <li>copy the slice to child 1 and mark out the genes in parent 2</li>
+ * <li>starting from the right side of the slice, copy genes from parent 2 as
+ * they appear to child 1 if they are not yet marked out.</li>
+ * </ol>
+ * <p>
+ * Example (random sublist from index 3 to 7, underlined):
+ * <pre>
+ * p1 = (8 4 7 3 6 2 5 1 9 0)   X   c1 = (0 4 7 3 6 2 5 1 8 9)
+ *             ---------                        ---------
+ * p2 = (0 1 2 3 4 5 6 7 8 9)   X   c2 = (8 1 2 3 4 5 6 7 9 0)
+ * </pre>
+ * <p>
+ * This policy works only on {@link AbstractListChromosome}, and therefore it is
+ * parameterized by T. Moreover, the chromosomes must have same lengths.
+ *
+ * @see <a href=
+ *      "http://www.rubicite.com/Tutorials/GeneticAlgorithms/CrossoverOperators/Order1CrossoverOperator.aspx">
+ *      Order 1 Crossover Operator</a>
+ *
+ * @param <T> generic type of the {@link AbstractListChromosome}s for crossover
+ * @param <P> phenotype of chromosome
+ * @since 3.1
+ */
+public class OrderedCrossover<T, P> extends AbstractListChromosomeCrossoverPolicy<T, P> {
+
+    /**
+     * Helper for {@link #crossover(Chromosome, Chromosome, double)}. Performs the
+     * actual crossover.
+     *
+     * @param first  the first chromosome
+     * @param second the second chromosome
+     * @return the pair of new chromosomes that resulted from the crossover
+     */
+    @Override
+    protected ChromosomePair<P> mate(final AbstractListChromosome<T, P> first,
+            final AbstractListChromosome<T, P> second) {
+
+        final int length = first.getLength();
+        // array representations of the parents
+        final List<T> parent1Rep = first.getRepresentation();
+        final List<T> parent2Rep = second.getRepresentation();
+        // and of the children
+        final List<T> child1 = new ArrayList<>(length);
+        final List<T> child2 = new ArrayList<>(length);
+        // sets of already inserted items for quick access
+        final Set<T> child1Set = new HashSet<>(length);
+        final Set<T> child2Set = new HashSet<>(length);
+
+        final UniformRandomProvider random = RandomProviderManager.getRandomProvider();
+        // choose random points, making sure that lb < ub.
+        final int a = random.nextInt(length);
+        int b;
+        do {
+            b = random.nextInt(length);
+        } while (a == b);
+        // determine the lower and upper bounds
+        final int lb = Math.min(a, b);
+        final int ub = Math.max(a, b);
+
+        // add the subLists that are between lb and ub
+        child1.addAll(parent1Rep.subList(lb, ub + 1));
+        child1Set.addAll(child1);
+        child2.addAll(parent2Rep.subList(lb, ub + 1));
+        child2Set.addAll(child2);
+
+        // iterate over every item in the parents
+        for (int i = 1; i <= length; i++) {
+            final int idx = (ub + i) % length;
+
+            // retrieve the current item in each parent
+            final T item1 = parent1Rep.get(idx);
+            final T item2 = parent2Rep.get(idx);
+
+            // if the first child already contains the item in the second parent add it
+            if (!child1Set.contains(item2)) {
+                child1.add(item2);
+                child1Set.add(item2);
+            }
+
+            // if the second child already contains the item in the first parent add it
+            if (!child2Set.contains(item1)) {
+                child2.add(item1);
+                child2Set.add(item1);
+            }
+        }
+
+        // rotate so that the original slice is in the same place as in the parents.
+        Collections.rotate(child1, lb);
+        Collections.rotate(child2, lb);
+
+        return new ChromosomePair<>(first.newChromosome(child1), second.newChromosome(child2));
+    }
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/UniformCrossover.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/UniformCrossover.java
new file mode 100644
index 0000000..23292f7
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/UniformCrossover.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.crossover;
+
+import java.util.ArrayList;
+
+import java.util.List;
+
+import org.apache.commons.math4.ga.chromosome.AbstractListChromosome;
+import org.apache.commons.math4.ga.chromosome.ChromosomePair;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.apache.commons.math4.ga.utils.RandomProviderManager;
+import org.apache.commons.rng.UniformRandomProvider;
+
+/**
+ * Perform Uniform Crossover [UX] on the specified chromosomes. A fixed mixing
+ * ratio is used to combine genes from the first and second parents, e.g. using
+ * a ratio of 0.5 would result in approximately 50% of genes coming from each
+ * parent. This is typically a poor method of crossover, but empirical evidence
+ * suggests that it is more exploratory and results in a larger part of the
+ * problem space being searched.
+ * <p>
+ * This crossover policy evaluates each gene of the parent chromosomes by
+ * choosing a uniform random number {@code p} in the range [0, 1]. If {@code p}
+ * &lt; {@code ratio}, the parent genes are swapped. This means with a ratio of
+ * 0.7, 30% of the genes from the first parent and 70% from the second parent
+ * will be selected for the first offspring (and vice versa for the second
+ * offspring).
+ * <p>
+ * This policy works only on {@link AbstractListChromosome}, and therefore it is
+ * parameterized by T. Moreover, the chromosomes must have same lengths.
+ *
+ * @see <a href=
+ *      "http://en.wikipedia.org/wiki/Crossover_%28genetic_algorithm%29">Crossover
+ *      techniques (Wikipedia)</a>
+ * @see <a href=
+ *      "http://www.obitko.com/tutorials/genetic-algorithms/crossover-mutation.php">Crossover
+ *      (Obitko.com)</a>
+ * @see <a href="http://www.tomaszgwiazda.com/uniformX.htm">Uniform
+ *      crossover</a>
+ * @param <T> generic type of the {@link AbstractListChromosome}s for crossover
+ * @param <P> phenotype of chromosome
+ * @since 3.1
+ */
+public class UniformCrossover<T, P> extends AbstractListChromosomeCrossoverPolicy<T, P> {
+
+    /** crossover rate. **/
+    public static final String CROSSOVER_RATE = "CROSSOVER_RATE";
+
+    /** The mixing ratio. */
+    private final double ratio;
+
+    /**
+     * Creates a new {@link UniformCrossover} policy using the given mixing ratio.
+     *
+     * @param ratio the mixing ratio
+     */
+    public UniformCrossover(final double ratio) {
+        if (ratio < 0.0d || ratio > 1.0d) {
+            throw new GeneticException(GeneticException.OUT_OF_RANGE, ratio, CROSSOVER_RATE, 0.0d, 1.0d);
+        }
+        this.ratio = ratio;
+    }
+
+    /**
+     * Returns the mixing ratio used by this {@link CrossoverPolicy}.
+     *
+     * @return the mixing ratio
+     */
+    public double getRatio() {
+        return ratio;
+    }
+
+    /**
+     * Helper for {@link #crossover(Chromosome, Chromosome, double)}. Performs the
+     * actual crossover.
+     *
+     * @param first  the first chromosome
+     * @param second the second chromosome
+     * @return the pair of new chromosomes that resulted from the crossover
+     */
+    @Override
+    protected ChromosomePair<P> mate(final AbstractListChromosome<T, P> first,
+            final AbstractListChromosome<T, P> second) {
+        final int length = first.getLength();
+        // array representations of the parents
+        final List<T> parent1Rep = first.getRepresentation();
+        final List<T> parent2Rep = second.getRepresentation();
+        // and of the children
+        final List<T> child1Rep = new ArrayList<>(length);
+        final List<T> child2Rep = new ArrayList<>(length);
+
+        final UniformRandomProvider random = RandomProviderManager.getRandomProvider();
+
+        for (int index = 0; index < length; index++) {
+
+            if (random.nextDouble() < ratio) {
+                // swap the bits -> take other parent
+                child1Rep.add(parent2Rep.get(index));
+                child2Rep.add(parent1Rep.get(index));
+            } else {
+                child1Rep.add(parent1Rep.get(index));
+                child2Rep.add(parent2Rep.get(index));
+            }
+        }
+
+        return new ChromosomePair<>(first.newChromosome(child1Rep), second.newChromosome(child2Rep));
+    }
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/package-info.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/package-info.java
new file mode 100644
index 0000000..68c9282
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.ga.crossover;
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/rategenerator/AdaptiveLinearAverageRankBasedCrossoverRateGenerator.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/rategenerator/AdaptiveLinearAverageRankBasedCrossoverRateGenerator.java
new file mode 100644
index 0000000..1b1057d
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/rategenerator/AdaptiveLinearAverageRankBasedCrossoverRateGenerator.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga.crossover.rategenerator;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.stats.PopulationStatisticalSummary;
+
+/**
+ * Generates crossover rate based on linear function of relative average rank of
+ * input chromosomes in population.
+ * @param <P> phenotype of chromosome
+ */
+public class AdaptiveLinearAverageRankBasedCrossoverRateGenerator<P> implements CrossoverRateGenerator<P> {
+
+    /** minimum crossover rate. **/
+    private final double minimumRate;
+
+    /** maximum crossover rate. **/
+    private final double maximumRate;
+
+    /**
+     * @param minimumRate minimum crossover rate
+     * @param maximumRate maximum crossover rate
+     */
+    public AdaptiveLinearAverageRankBasedCrossoverRateGenerator(double minimumRate, double maximumRate) {
+        this.maximumRate = maximumRate;
+        this.minimumRate = minimumRate;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public double generate(Chromosome<P> first,
+            Chromosome<P> second,
+            PopulationStatisticalSummary<P> populationStats,
+            int generation) {
+        final int averageRank = (populationStats.findRank(first) + populationStats.findRank(second)) / 2;
+        return minimumRate +
+                (maximumRate - minimumRate) * (1.0 - (double) averageRank / (populationStats.getPopulationSize() - 1));
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/rategenerator/AdaptiveLinearMaximumRankBasedCrossoverRateGenerator.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/rategenerator/AdaptiveLinearMaximumRankBasedCrossoverRateGenerator.java
new file mode 100644
index 0000000..c03f488
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/rategenerator/AdaptiveLinearMaximumRankBasedCrossoverRateGenerator.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga.crossover.rategenerator;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.stats.PopulationStatisticalSummary;
+
+/**
+ * Generates crossover rate based on linear function of relative maximum rank of
+ * input chromosomes in population.
+ * @param <P> phenotype of chromosome
+ */
+public class AdaptiveLinearMaximumRankBasedCrossoverRateGenerator<P> implements CrossoverRateGenerator<P> {
+
+    /** minimum crossover rate. **/
+    private final double minimumRate;
+
+    /** maximum crossover rate. **/
+    private final double maximumRate;
+
+    /**
+     * @param minimumRate minimum crossover rate
+     * @param maximumRate maximum crossover rate
+     */
+    public AdaptiveLinearMaximumRankBasedCrossoverRateGenerator(double minimumRate, double maximumRate) {
+        this.maximumRate = maximumRate;
+        this.minimumRate = minimumRate;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public double generate(Chromosome<P> first,
+            Chromosome<P> second,
+            PopulationStatisticalSummary<P> populationStats,
+            int generation) {
+        final int maximumRank = Math.max(populationStats.findRank(first), populationStats.findRank(second));
+        return minimumRate +
+                (maximumRate - minimumRate) * (1.0 - (double) maximumRank / (populationStats.getPopulationSize() - 1));
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/rategenerator/ConstantCrossoverRateGenerator.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/rategenerator/ConstantCrossoverRateGenerator.java
new file mode 100644
index 0000000..2f77ce1
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/rategenerator/ConstantCrossoverRateGenerator.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga.crossover.rategenerator;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.stats.PopulationStatisticalSummary;
+
+/**
+ * This class represents a constant crossover rate generator.
+ * @param <P> phenotype of chromosome
+ */
+public class ConstantCrossoverRateGenerator<P> implements CrossoverRateGenerator<P> {
+
+    /** the fixed value of crossover rate. **/
+    private final double crossoverRate;
+
+    /**
+     * @param crossoverRate crossover rate
+     */
+    public ConstantCrossoverRateGenerator(double crossoverRate) {
+        this.crossoverRate = crossoverRate;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public double generate(Chromosome<P> first,
+            Chromosome<P> second,
+            PopulationStatisticalSummary<P> populationStats,
+            int generation) {
+        return crossoverRate;
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/rategenerator/CrossoverRateGenerator.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/rategenerator/CrossoverRateGenerator.java
new file mode 100644
index 0000000..438aeed
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/rategenerator/CrossoverRateGenerator.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga.crossover.rategenerator;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.stats.PopulationStatisticalSummary;
+
+/**
+ * This abstraction represents crossover rate generator.
+ * @param <P> phenotype of chromosome
+ */
+public interface CrossoverRateGenerator<P> {
+
+    /**
+     * Generates crossover rate.
+     * @param first           first chromosome
+     * @param second          second chromosome
+     * @param populationStats population statistics summary
+     * @param generation      generation number
+     * @return crossover rate rate of crossover
+     */
+    double generate(Chromosome<P> first,
+            Chromosome<P> second,
+            PopulationStatisticalSummary<P> populationStats,
+            int generation);
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/rategenerator/package-info.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/rategenerator/package-info.java
new file mode 100644
index 0000000..886eab7
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/crossover/rategenerator/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.ga.crossover.rategenerator;
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/decoder/AbstractListChromosomeDecoder.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/decoder/AbstractListChromosomeDecoder.java
new file mode 100644
index 0000000..96a1920
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/decoder/AbstractListChromosomeDecoder.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.decoder;
+
+import org.apache.commons.math4.ga.chromosome.AbstractListChromosome;
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+
+/**
+ * An abstract Decoder of ListChromosome.
+ * @param <T> genotype fo chromosome
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public abstract class AbstractListChromosomeDecoder<T, P> implements Decoder<P> {
+
+    /**
+     * {@inheritDoc}
+     */
+    @SuppressWarnings("unchecked")
+    @Override
+    public P decode(Chromosome<P> chromosome) {
+        checkValidity(chromosome);
+
+        return decode((AbstractListChromosome<T, P>) chromosome);
+    }
+
+    /**
+     * Checks validity of {@link Chromosome}.
+     * @param chromosome the {@link Chromosome}
+     */
+    protected void checkValidity(Chromosome<P> chromosome) {
+        if (!AbstractListChromosome.class.isAssignableFrom(chromosome.getClass())) {
+            throw new GeneticException(GeneticException.ILLEGAL_ARGUMENT, chromosome.getClass().getSimpleName());
+        }
+    }
+
+    /**
+     * Decodes the chromosome genotype and returns the phenotype.
+     * @param chromosome The list chromosome to decode
+     * @return decoded phenotype of chromosome
+     */
+    protected abstract P decode(AbstractListChromosome<T, P> chromosome);
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/decoder/Decoder.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/decoder/Decoder.java
new file mode 100644
index 0000000..50f2ba9
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/decoder/Decoder.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.decoder;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+
+/**
+ * Decoder is responsible for converting chromosome genotype to phenotype.
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public interface Decoder<P> {
+
+    /**
+     * Converts genotype to phenotype.
+     * @param chromosome The {@link Chromosome}
+     * @return phenotype The phenotype of chromosome
+     */
+    P decode(Chromosome<P> chromosome);
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/decoder/RandomKeyDecoder.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/decoder/RandomKeyDecoder.java
new file mode 100644
index 0000000..037ccfd
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/decoder/RandomKeyDecoder.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.decoder;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+import org.apache.commons.math4.ga.chromosome.AbstractListChromosome;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+
+/**
+ * A concrete implementation of RandomKey decoder. This class is responsible for
+ * decoding permutation chromosome encoded with random key.
+ * @param <U> type of the permutation element
+ * @since 4.0
+ */
+public final class RandomKeyDecoder<U> extends AbstractListChromosomeDecoder<Double, List<U>> {
+
+    /** base sequence for decoding chromosome. **/
+    private final List<U> baseSequence;
+
+    /**
+     * @param baseSequence the unpermuted sequence
+     */
+    public RandomKeyDecoder(List<U> baseSequence) {
+        this.baseSequence = Collections.unmodifiableList(Objects.requireNonNull(baseSequence));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected List<U> decode(AbstractListChromosome<Double, List<U>> chromosome) {
+        final List<Double> representation = chromosome.getRepresentation();
+        final List<Double> sortedRepresentation = new ArrayList<>(representation);
+        Collections.sort(sortedRepresentation);
+
+        final int sequenceLength = baseSequence.size();
+
+        // the size of the three lists must be equal
+        if (representation.size() != sequenceLength) {
+            throw new GeneticException(GeneticException.SIZE_MISMATCH, representation.size(), sequenceLength);
+        }
+
+        // do not modify the original representation
+        final List<Double> representationCopy = new ArrayList<>(representation);
+
+        // now find the indices in the original repr and use them for permuting
+        final List<U> res = new ArrayList<>(sequenceLength);
+        for (int i = 0; i < sequenceLength; i++) {
+            final int index = representationCopy.indexOf(sortedRepresentation.get(i));
+            res.add(baseSequence.get(index));
+            representationCopy.set(index, null);
+        }
+
+        return res;
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/decoder/TransparentListChromosomeDecoder.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/decoder/TransparentListChromosomeDecoder.java
new file mode 100644
index 0000000..b8d0be7
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/decoder/TransparentListChromosomeDecoder.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.decoder;
+
+import java.util.List;
+
+import org.apache.commons.math4.ga.chromosome.AbstractListChromosome;
+
+/**
+ * A concrete implementation of transparent decoder for List Chromosome. Treats
+ * the gentype as phenotype.
+ * @param <T> the genotype of chromosome
+ * @since 4.0
+ */
+public final class TransparentListChromosomeDecoder<T> extends AbstractListChromosomeDecoder<T, List<T>> {
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected List<T> decode(AbstractListChromosome<T, List<T>> chromosome) {
+        return chromosome.getRepresentation();
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/decoder/package-info.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/decoder/package-info.java
new file mode 100644
index 0000000..57e19a8
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/decoder/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.ga.decoder;
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/fitness/FitnessFunction.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/fitness/FitnessFunction.java
new file mode 100644
index 0000000..ade6dea
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/fitness/FitnessFunction.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga.fitness;
+
+/**
+ * This interface represents fitness function.
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public interface FitnessFunction<P> {
+
+    /**
+     * computes the fitness value of the input chromosome's phenotype.
+     * @param decodedChromosome chromosome decoded as phenotype
+     * @return fitness value
+     */
+    double compute(P decodedChromosome);
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/fitness/package-info.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/fitness/package-info.java
new file mode 100644
index 0000000..5b6d4c5
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/fitness/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.ga.fitness;
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/internal/exception/GeneticException.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/internal/exception/GeneticException.java
new file mode 100644
index 0000000..7209472
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/internal/exception/GeneticException.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga.internal.exception;
+
+import java.text.MessageFormat;
+
+/**
+ * This class represents the Exception encountered during GA optimization.
+ * @since 4.0
+ */
+public class GeneticException extends RuntimeException {
+
+    /** Error message for "out of range" condition. */
+    public static final String OUT_OF_RANGE = "Value {0} of {1} is out of range [{2}, {3}]";
+
+    /** Error message for "not strictly positive" condition. */
+    public static final String NOT_STRICTLY_POSITIVE = "Number {0} is not strictly positive";
+
+    /** Error message for "too large" condition. */
+    public static final String TOO_LARGE = "Number {0} is larger than {1}";
+
+    /** Error message for "too small" condition. */
+    public static final String TOO_SMALL = "Number {0} is smaller than {1}";
+
+    /** Error message for "out of range" condition. */
+    public static final String NO_DATA = "No data";
+
+    /** Error message for "size mismatch" condition. */
+    public static final String SIZE_MISMATCH = "Size mismatch: {0} != {1}";
+
+    /** Error message for "generic illegal argument" condition. */
+    public static final String ILLEGAL_ARGUMENT = "Illegal Argument Exception: {0}";
+
+    /** Error message for "generic illegal argument" condition. */
+    public static final String ILLEGAL_RANGE = "Illegal Range of Value Exception: " +
+            "[Expected min-{0}, max-{1}], [Passed min-{2}, max-{3}]";
+
+    /** Error message for "generic illegal argument" condition. */
+    public static final String INVALID_FIXED_LENGTH_CHROMOSOME = "Invalid Fixed Length Chromosome.";
+
+    /** Error message for "NULL ARGUMENT" condition. */
+    public static final String NULL_ARGUMENT = "Null Argument Exception: {0}";
+
+    /**
+     * Error message for "List of Chromosome bigger than population size" condition.
+     */
+    public static final String LIST_OF_CHROMOSOMES_BIGGER_THAN_POPULATION_SIZE = "List of chromosome bigger than " +
+            "population size: {0} > {1}";
+
+    /**
+     * Error message for "population limit not positive" condition.
+     */
+    public static final String POPULATION_LIMIT_NOT_POSITIVE = "Population limit not positive :{0}";
+
+    /**
+     * Error message for " population limit less than list of chromosomes size"
+     * condition.
+     */
+    public static final String POPULATION_LIMIT_LESS_THAN_LIST_OF_CHROMOSOMES_SIZE = "Population limit is " +
+            " lesser than list of chromosomes size : {0} < {1}";
+
+    /**
+     * Error message for different origin and permuted data.
+     */
+    public static final String DIFFERENT_ORIG_AND_PERMUTED_DATA = "Different original and permuted data";
+
+    /**
+     * Error message for chromosome length larger than expected.
+     */
+    public static final String LENGTH_TOO_LARGE = "Chromosome length larger than {0} not supported for" +
+            " string representation.";
+
+    /** Serializable version identifier. */
+    private static final long serialVersionUID = 20210516L;
+
+    /**
+     * Create an exception where the message is constructed by applying the
+     * {@code format()} method from {@code java.text.MessageFormat}.
+     *
+     * @param message         Message format (with replaceable parameters).
+     * @param formatArguments Actual arguments to be displayed in the message.
+     */
+    public GeneticException(String message, Object... formatArguments) {
+        super(MessageFormat.format(message, formatArguments));
+    }
+
+    /**
+     * Create an exception.
+     * @param t instance of {@link Throwable}
+     */
+    public GeneticException(Throwable t) {
+        super(t);
+    }
+
+    /**
+     * Create an exception having both stacktrace and message.
+     * @param message         the exception message
+     * @param t               the instance of {@link Throwable}
+     * @param formatArguments arguments to format the exception message
+     */
+    public GeneticException(String message, Throwable t, Object... formatArguments) {
+        super(MessageFormat.format(message, formatArguments), t);
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/internal/exception/package-info.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/internal/exception/package-info.java
new file mode 100644
index 0000000..b55e918
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/internal/exception/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.ga.internal.exception;
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/internal/stats/PopulationStatisticalSummaryImpl.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/internal/stats/PopulationStatisticalSummaryImpl.java
new file mode 100644
index 0000000..b95b60f
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/internal/stats/PopulationStatisticalSummaryImpl.java
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.internal.stats;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.population.Population;
+import org.apache.commons.math4.ga.stats.PopulationStatisticalSummary;
+
+/**
+ * This class represents an implementation of population statistical summary.
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public class PopulationStatisticalSummaryImpl<P> implements PopulationStatisticalSummary<P> {
+
+    /** maximum fitness of the population. **/
+    private final double maxFitness;
+
+    /** minimum fitness of the population. **/
+    private final double minFitness;
+
+    /** mean fitness of the population. **/
+    private double meanFitness;
+
+    /** variance of population fitness. **/
+    private final double variance;
+
+    /** population size. **/
+    private final int populationSize;
+
+    /** a map of chromosome Id and corresponding rank in population. **/
+    private final Map<String, Integer> chromosomeIdRankMap = new HashMap<>();
+
+    /**
+     * @param population current population {@link Population} of chromosomes
+     */
+    public PopulationStatisticalSummaryImpl(Population<P> population) {
+
+        // Fetch all chromosomes.
+        List<Chromosome<P>> chromosomes = getChromosomes(Objects.requireNonNull(population));
+
+        // Sort all chromosomes.
+        Collections.sort(chromosomes);
+
+        this.populationSize = chromosomes.size();
+        this.maxFitness = chromosomes.get(chromosomes.size() - 1).evaluate();
+        this.minFitness = chromosomes.get(0).evaluate();
+        this.meanFitness = calculateMeanFitness(chromosomes);
+        this.variance = calculateVariance(chromosomes);
+
+        updateChromosomeIdRankMap(chromosomes);
+
+    }
+
+    /**
+     * Updates chromosome Id and rank.
+     * @param chromosomes list of chromosomes
+     */
+    private void updateChromosomeIdRankMap(List<Chromosome<P>> chromosomes) {
+        for (int rank = 0; rank < chromosomes.size(); rank++) {
+            this.chromosomeIdRankMap.put(chromosomes.get(rank).getId(), rank);
+        }
+    }
+
+    /**
+     * Fetches chromosomes.
+     * @param population
+     * @return list of chromosomes
+     */
+    private List<Chromosome<P>> getChromosomes(Population<P> population) {
+        List<Chromosome<P>> chromosomes = new ArrayList<>(population.getPopulationSize());
+        for (Chromosome<P> chromosome : population) {
+            chromosomes.add(chromosome);
+        }
+        return chromosomes;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public double getMeanFitness() {
+        return this.meanFitness;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public double getFitnessVariance() {
+        return this.variance;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public double getMaxFitness() {
+        return this.maxFitness;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public double getMinFitness() {
+        return this.minFitness;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public long getPopulationSize() {
+        return this.populationSize;
+    }
+
+    /**
+     * Calculate mean fitness.
+     * @param chromosomes list of chromosomes
+     * @return returns mean fitness
+     */
+    private double calculateMeanFitness(List<Chromosome<P>> chromosomes) {
+        double sum = 0.0;
+        for (Chromosome<P> chromosome : chromosomes) {
+            sum += chromosome.evaluate();
+        }
+        return sum / chromosomes.size();
+    }
+
+    /**
+     * Calculate variance of population fitness.
+     * @param chromosomes List of chromosomes
+     * @return fitness variance
+     */
+    private double calculateVariance(List<Chromosome<P>> chromosomes) {
+        if (this.meanFitness == 0) {
+            this.meanFitness = calculateMeanFitness(chromosomes);
+        }
+        double sumOfSquare = 0.0;
+        for (Chromosome<P> chromosome : chromosomes) {
+            sumOfSquare += Math.pow(chromosome.evaluate(), 2);
+        }
+
+        return (sumOfSquare / chromosomes.size()) - Math.pow(this.meanFitness, 2);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int findRank(Chromosome<P> chromosome) {
+        return chromosomeIdRankMap.get(chromosome.getId());
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/internal/stats/package-info.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/internal/stats/package-info.java
new file mode 100644
index 0000000..a0ae55d
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/internal/stats/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.ga.internal.stats;
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/listener/ConvergenceListener.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/listener/ConvergenceListener.java
new file mode 100644
index 0000000..f99d585
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/listener/ConvergenceListener.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga.listener;
+
+import org.apache.commons.math4.ga.population.Population;
+
+/**
+ * This interface represents a convergence listener. Any implementation of the
+ * same will be notified about the population statics.
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public interface ConvergenceListener<P> {
+
+    /**
+     * Notifies about the population statistics.
+     * @param generation current generation
+     * @param population population of chromosome
+     */
+    void notify(int generation, Population<P> population);
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/listener/ConvergenceListenerRegistry.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/listener/ConvergenceListenerRegistry.java
new file mode 100644
index 0000000..7fce28e
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/listener/ConvergenceListenerRegistry.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga.listener;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import org.apache.commons.math4.ga.population.Population;
+
+/**
+ * This class is the default implementation of ConvergenceListenerRegistry. It
+ * will be responsible for registering the interested listeners and notifying
+ * all when required.
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public final class ConvergenceListenerRegistry<P> {
+
+    /**
+     * The instance of the singleton class.
+     */
+    @SuppressWarnings("rawtypes")
+    private static final ConvergenceListenerRegistry INSTANCE = new ConvergenceListenerRegistry<>();
+
+    /**
+     * List of registered listeners.
+     */
+    private final List<ConvergenceListener<P>> listeners = new ArrayList<>();
+
+    /**
+     * private constructor to construct the singleton instance.
+     */
+    private ConvergenceListenerRegistry() {
+    }
+
+    /**
+     * Registers the interested ConvergenceListener passed as an argument.
+     * @param convergenceListener The {@link ConvergenceListener}
+     */
+    public void addConvergenceListener(ConvergenceListener<P> convergenceListener) {
+        this.listeners.add(convergenceListener);
+    }
+
+    /**
+     * Notifies all registered ConvergenceListeners about the population statistics.
+     * @param generation current generation
+     * @param population population of chromosomes
+     */
+    public synchronized void notifyAll(int generation, Population<P> population) {
+        for (ConvergenceListener<P> convergenceListener : listeners) {
+            convergenceListener.notify(generation, population);
+        }
+    }
+
+    /**
+     * Add instance of convergence listener.
+     * @param convergenceListeners list of {@link ConvergenceListener}
+     */
+    public void addConvergenceListeners(List<ConvergenceListener<P>> convergenceListeners) {
+        for (ConvergenceListener<P> convergenceListener : Objects.requireNonNull(convergenceListeners)) {
+            addConvergenceListener(convergenceListener);
+        }
+    }
+
+    /**
+     * Returns instance of this class.
+     * @param <P> The phenotype of chromosome
+     * @return instance
+     */
+    @SuppressWarnings("unchecked")
+    public static <P> ConvergenceListenerRegistry<P> getInstance() {
+        return INSTANCE;
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/listener/PopulationStatisticsLogger.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/listener/PopulationStatisticsLogger.java
new file mode 100644
index 0000000..b0f7276
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/listener/PopulationStatisticsLogger.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga.listener;
+
+import org.apache.commons.math4.ga.internal.stats.PopulationStatisticalSummaryImpl;
+import org.apache.commons.math4.ga.population.Population;
+import org.apache.commons.math4.ga.stats.PopulationStatisticalSummary;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Logs population statistics during the convergence process.
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public final class PopulationStatisticsLogger<P> implements ConvergenceListener<P> {
+
+    /** instance of log4j logger. **/
+    private static final Logger LOGGER = LoggerFactory.getLogger(PopulationStatisticsLogger.class);
+
+    /**
+     * Logs the population statistics during the process of convergence.
+     */
+    @Override
+    public void notify(int generation, Population<P> population) {
+        final PopulationStatisticalSummary<P> populationStatisticalSummary = new PopulationStatisticalSummaryImpl<>(
+                population);
+        LOGGER.info(
+                "Population statistics for generation %d ::: Mean Fitness: %f, Max Fitness: %f, Fitness Variance: %f",
+                generation, populationStatisticalSummary.getMeanFitness(), populationStatisticalSummary.getMaxFitness(),
+                populationStatisticalSummary.getFitnessVariance());
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/listener/package-info.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/listener/package-info.java
new file mode 100644
index 0000000..f2e0d4a
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/listener/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.ga.listener;
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/AbstractListChromosomeMutationPolicy.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/AbstractListChromosomeMutationPolicy.java
new file mode 100644
index 0000000..3e41fc2
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/AbstractListChromosomeMutationPolicy.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga.mutation;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.math4.ga.chromosome.AbstractListChromosome;
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.utils.RandomProviderManager;
+import org.apache.commons.rng.UniformRandomProvider;
+
+/**
+ * This abstraction represents an abstract mutation policy for ListChromosomes.
+ * @param <T> genotype of chromosome
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public abstract class AbstractListChromosomeMutationPolicy<T, P> implements MutationPolicy<P> {
+
+    /**
+     * Mutate the given chromosome. Randomly changes few genes depending on mutation
+     * rate.
+     * @param original     the original chromosome.
+     * @param mutationRate the rate of mutation per gene
+     * @return the mutated chromosome.
+     */
+    @Override
+    public Chromosome<P> mutate(Chromosome<P> original, double mutationRate) {
+        // check for validity.
+        checkValidity(original);
+
+        @SuppressWarnings("unchecked")
+        final AbstractListChromosome<T, P> chromosome = (AbstractListChromosome<T, P>) original;
+        final List<T> newRep = new ArrayList<>(chromosome.getRepresentation());
+
+        final Set<Integer> mutableGeneIndexes = getMutableGeneIndexes(chromosome.getLength(), mutationRate);
+        for (int mutableGeneIndex : mutableGeneIndexes) {
+            newRep.set(mutableGeneIndex, mutateGene(newRep.get(mutableGeneIndex)));
+        }
+
+        return chromosome.newChromosome(newRep);
+    }
+
+    /**
+     * Checks input chromosome validity.
+     * @param original chromosome to be mutated
+     */
+    protected abstract void checkValidity(Chromosome<P> original);
+
+    /**
+     * Selects and returns mutable gene indexes based on mutation rate.
+     * @param length       no of alleles/genes in chromosome
+     * @param mutationRate mutation rate of the allele/gene
+     * @return mutable gene indexes
+     */
+    protected Set<Integer> getMutableGeneIndexes(int length, double mutationRate) {
+
+        // calculate the total mutation rate of all the alleles i.e. chromosome.
+        final double chromosomeMutationRate = mutationRate * length;
+        final Set<Integer> indexSet = new HashSet<>();
+        final UniformRandomProvider randomProvider = RandomProviderManager.getRandomProvider();
+
+        // if chromosomeMutationRate >= 1 then more than one allele will be mutated.
+        if (chromosomeMutationRate >= 1) {
+            final int noOfMutation = (int) Math.round(chromosomeMutationRate);
+            while (indexSet.size() < noOfMutation) {
+                indexSet.add(randomProvider.nextInt(length));
+            }
+        } else if (randomProvider.nextDouble() < chromosomeMutationRate) {
+            indexSet.add(randomProvider.nextInt(length));
+        }
+
+        return indexSet;
+    }
+
+    /**
+     * Mutates an individual gene/allele.
+     * @param originalValue the original value of gene
+     * @return mutated value of gene
+     */
+    protected abstract T mutateGene(T originalValue);
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/BinaryMutation.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/BinaryMutation.java
new file mode 100644
index 0000000..2470f38
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/BinaryMutation.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.mutation;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.commons.math4.ga.chromosome.BinaryChromosome;
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.apache.commons.math4.ga.utils.RandomProviderManager;
+
+/**
+ * Mutation for {@link BinaryChromosome}s. Randomly changes few genes.
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public class BinaryMutation<P> implements MutationPolicy<P> {
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Chromosome<P> mutate(Chromosome<P> original, double mutationRate) {
+        // check for validity.
+        checkValidity(original);
+        final BinaryChromosome<P> chromosome = (BinaryChromosome<P>) original;
+        final long[] representation = chromosome.getRepresentation();
+        final long[] newRep = new long[representation.length];
+        System.arraycopy(representation, 0, newRep, 0, representation.length);
+
+        final Map<Integer, Set<Integer>> mutableGeneIndexMap = getMutableGeneIndexes(chromosome.getLength(),
+                mutationRate);
+        for (Entry<Integer, Set<Integer>> entry : mutableGeneIndexMap.entrySet()) {
+            final int alleleBlockIndex = entry.getKey();
+            long mask = 0;
+            final Set<Integer> alleleElementIndexes = mutableGeneIndexMap.get(alleleBlockIndex);
+            for (int index : alleleElementIndexes) {
+                mask += index == 0 ? Long.MIN_VALUE : Math.pow(2, Long.SIZE - 1 - index);
+            }
+            newRep[alleleBlockIndex] = newRep[alleleBlockIndex] ^ mask;
+        }
+//        for (int alleleBlockIndex : mutableGeneIndexMap.keySet()) {
+//            long mask = 0;
+//            final Set<Integer> alleleElementIndexes = mutableGeneIndexMap.get(alleleBlockIndex);
+//            for (int index : alleleElementIndexes) {
+//                mask += index == 0 ? Long.MIN_VALUE : Math.pow(2, Long.SIZE - 1 - index);
+//            }
+//            newRep[alleleBlockIndex] = newRep[alleleBlockIndex] ^ mask;
+//        }
+
+        return chromosome.newChromosome(newRep, chromosome.getLength());
+    }
+
+    /**
+     * Checks input chromosome validity.
+     * @param original chromosome to be mutated
+     */
+    protected void checkValidity(Chromosome<P> original) {
+        if (!BinaryChromosome.class.isAssignableFrom(original.getClass())) {
+            throw new GeneticException(GeneticException.ILLEGAL_ARGUMENT, original.getClass().getSimpleName());
+        }
+    }
+
+    /**
+     * Selects and returns mutable gene indexes based on mutation rate.
+     * @param length       no of alleles/genes in chromosome
+     * @param mutationRate mutation rate of the allele/gene
+     * @return mutable gene indexes
+     */
+    protected Map<Integer, Set<Integer>> getMutableGeneIndexes(long length, double mutationRate) {
+
+        // calculate the total mutation rate of all the alleles i.e. chromosome.
+        final double chromosomeMutationRate = mutationRate * length;
+        final Map<Integer, Set<Integer>> indexMap = new HashMap<>();
+
+        // if chromosomeMutationRate >= 1 then more than one allele will be mutated.
+        if (chromosomeMutationRate >= 1) {
+            final int noOfMutation = (int) Math.round(chromosomeMutationRate);
+            final Set<Long> mutationIndexes = new HashSet<>();
+            for (int i = 0; i < noOfMutation; i++) {
+                final long mutationIndex = generateMutationIndex(length, mutationIndexes);
+                mutationIndexes.add(mutationIndex);
+                updateIndexMap(indexMap, length, mutationIndex);
+            }
+        } else if (RandomProviderManager.getRandomProvider().nextDouble() < chromosomeMutationRate) {
+            updateIndexMap(indexMap, length);
+        }
+        return indexMap;
+    }
+
+    private long generateMutationIndex(long length, Set<Long> mutationIndexes) {
+        long mutationIndex = 0;
+        do {
+            mutationIndex = RandomProviderManager.getRandomProvider().nextLong(length);
+        } while (mutationIndexes.contains(mutationIndex));
+        return mutationIndex;
+    }
+
+    private void updateIndexMap(Map<Integer, Set<Integer>> indexMap, long length, long mutationIndex) {
+        final int offset = (int) (length % Long.SIZE == 0 ? 0 : Long.SIZE - length % Long.SIZE);
+        final long offsettedMutableAlleleIndex = offset + mutationIndex;
+
+        final int alleleBlockIndex = (int) (offsettedMutableAlleleIndex / Long.SIZE);
+
+        if (!indexMap.containsKey(alleleBlockIndex)) {
+            indexMap.put(alleleBlockIndex, new HashSet<>());
+        }
+        final int alleleElementIndex = (int) (offsettedMutableAlleleIndex % Long.SIZE);
+
+        indexMap.get(alleleBlockIndex).add(alleleElementIndex);
+    }
+
+    private void updateIndexMap(Map<Integer, Set<Integer>> indexMap, long length) {
+        updateIndexMap(indexMap, length, RandomProviderManager.getRandomProvider().nextLong(length));
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/IntegralValuedMutation.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/IntegralValuedMutation.java
new file mode 100644
index 0000000..2ff7f0f
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/IntegralValuedMutation.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.mutation;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.chromosome.IntegralValuedChromosome;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.apache.commons.math4.ga.utils.RandomProviderManager;
+
+/**
+ * Mutation for {@link IntegralValuedChromosome}. Randomly changes few genes.
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public class IntegralValuedMutation<P> extends AbstractListChromosomeMutationPolicy<Integer, P> {
+
+    /** minimum acceptable value of allele. **/
+    private final int min;
+
+    /** maximum acceptable value of allele. **/
+    private final int max;
+
+    /**
+     * @param min minimum value of allele
+     * @param max maximum value of allele
+     */
+    public IntegralValuedMutation(final int min, final int max) {
+        this.min = min;
+        this.max = max;
+        if (min >= max) {
+            throw new GeneticException(GeneticException.TOO_LARGE, min, max);
+        }
+    }
+
+    /**
+     * Returns the minimum acceptable value.
+     * @return minimum
+     */
+    public int getMin() {
+        return min;
+    }
+
+    /**
+     * Returns the maximum acceptable value.
+     * @return maximum
+     */
+    public int getMax() {
+        return max;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void checkValidity(Chromosome<P> original) {
+        if (!IntegralValuedChromosome.class.isAssignableFrom(original.getClass())) {
+            throw new GeneticException(GeneticException.ILLEGAL_ARGUMENT, original.getClass().getSimpleName());
+        }
+        final IntegralValuedChromosome<P> chromosome = (IntegralValuedChromosome<P>) original;
+        if (chromosome.getMin() != this.min || chromosome.getMax() != this.max) {
+            throw new GeneticException(GeneticException.ILLEGAL_RANGE, this.min, this.max, chromosome.getMin(),
+                    chromosome.getMax());
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected Integer mutateGene(Integer originalValue) {
+        return min + RandomProviderManager.getRandomProvider().nextInt(max - min);
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/MutationPolicy.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/MutationPolicy.java
new file mode 100644
index 0000000..096e419
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/MutationPolicy.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.mutation;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+
+/**
+ * Algorithm used to mutate a chromosome.
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public interface MutationPolicy<P> {
+
+    /**
+     * Mutate the given chromosome.
+     * @param original     the original chromosome.
+     * @param mutationRate The probability of mutation
+     * @return the mutated chromosome.
+     */
+    Chromosome<P> mutate(Chromosome<P> original, double mutationRate);
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/RealValuedMutation.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/RealValuedMutation.java
new file mode 100644
index 0000000..3dcbdcf
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/RealValuedMutation.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.mutation;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.chromosome.RealValuedChromosome;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.apache.commons.math4.ga.utils.RandomProviderManager;
+
+/**
+ * This class mutates real-valued chromosome.
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public class RealValuedMutation<P> extends AbstractListChromosomeMutationPolicy<Double, P> {
+
+    /** minimum value of chromosome gene/allele. **/
+    private final double min;
+
+    /** maximum value of chromosome gene/allele. **/
+    private final double max;
+
+    /**
+     * Constructs the mutation operator with normalized range of double values.
+     */
+    public RealValuedMutation() {
+        this.min = 0d;
+        this.max = 1d;
+    }
+
+    /**
+     * Constructs the mutation operator with provided range of double values.
+     * @param min minimum inclusive value of allele
+     * @param max maximum exclusive value of allele
+     */
+    public RealValuedMutation(double min, double max) {
+        this.min = min;
+        this.max = max;
+        if (min >= max) {
+            throw new GeneticException(GeneticException.TOO_LARGE, min, max);
+        }
+    }
+
+    /**
+     * Returns the minimum acceptable value.
+     * @return minimum
+     */
+    public double getMin() {
+        return min;
+    }
+
+    /**
+     * Returns the maximum acceptable value.
+     * @return maximum
+     */
+    public double getMax() {
+        return max;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void checkValidity(Chromosome<P> original) {
+        if (!RealValuedChromosome.class.isAssignableFrom(original.getClass())) {
+            throw new GeneticException(GeneticException.ILLEGAL_ARGUMENT, original.getClass().getSimpleName());
+        }
+        final RealValuedChromosome<P> chromosome = (RealValuedChromosome<P>) original;
+        if (chromosome.getMin() != this.min || chromosome.getMax() != this.max) {
+            throw new GeneticException(GeneticException.ILLEGAL_RANGE, this.min, this.max, chromosome.getMin(),
+                    chromosome.getMax());
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected Double mutateGene(Double originalValue) {
+        return min + RandomProviderManager.getRandomProvider().nextDouble() * (max - min);
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/package-info.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/package-info.java
new file mode 100644
index 0000000..30c90e4
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.ga.mutation;
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/rategenerator/AdaptiveLinearMutationRateGenerator.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/rategenerator/AdaptiveLinearMutationRateGenerator.java
new file mode 100644
index 0000000..555465f
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/rategenerator/AdaptiveLinearMutationRateGenerator.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga.mutation.rategenerator;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.stats.PopulationStatisticalSummary;
+
+/**
+ * Generates mutation rate using linear function of relative rank of input
+ * chromosome in population.
+ * @param <P> phenotype of chromosome
+ */
+public class AdaptiveLinearMutationRateGenerator<P> implements MutationRateGenerator<P> {
+
+    /** minimum crossover rate. **/
+    private final double minimumRate;
+
+    /** maximum crossover rate. **/
+    private final double maximumRate;
+
+    /**
+     * @param minimumRate minimum mutation rate
+     * @param maximumRate maximum mutation rate
+     */
+    public AdaptiveLinearMutationRateGenerator(double minimumRate, double maximumRate) {
+        this.minimumRate = minimumRate;
+        this.maximumRate = maximumRate;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public double generate(Chromosome<P> chromosome, PopulationStatisticalSummary<P> populationStats, int generation) {
+        return minimumRate + (maximumRate - minimumRate) *
+                (1.0 - (double) populationStats.findRank(chromosome) / (populationStats.getPopulationSize() - 1));
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/rategenerator/ConstantMutationRateGenerator.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/rategenerator/ConstantMutationRateGenerator.java
new file mode 100644
index 0000000..097e98d
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/rategenerator/ConstantMutationRateGenerator.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga.mutation.rategenerator;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.stats.PopulationStatisticalSummary;
+
+/**
+ * This class represents a constant mutation rate generator.
+ * @param <P> phenotype of chromosome
+ */
+public class ConstantMutationRateGenerator<P> implements MutationRateGenerator<P> {
+
+    /** the constant mutationRate. **/
+    private final double mutationRate;
+
+    /**
+     * @param mutationRate mutation rate
+     */
+    public ConstantMutationRateGenerator(double mutationRate) {
+        this.mutationRate = mutationRate;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public double generate(Chromosome<P> chromosome, PopulationStatisticalSummary<P> populationStats, int generation) {
+        return mutationRate;
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/rategenerator/MutationRateGenerator.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/rategenerator/MutationRateGenerator.java
new file mode 100644
index 0000000..a206e02
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/rategenerator/MutationRateGenerator.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga.mutation.rategenerator;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.stats.PopulationStatisticalSummary;
+
+/**
+ * This abstraction represents mutation rate generator.
+ * @param <P> phenotype of chromosome
+ */
+public interface MutationRateGenerator<P> {
+
+    /**
+     * Generates mutation rate based on input params.
+     * @param chromosome      chromosome
+     * @param populationStats population statictics summary
+     * @param generation      generation count
+     * @return mutation rate
+     */
+    double generate(Chromosome<P> chromosome, PopulationStatisticalSummary<P> populationStats, int generation);
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/rategenerator/package-info.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/rategenerator/package-info.java
new file mode 100644
index 0000000..c7e56ce
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/mutation/rategenerator/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.ga.mutation.rategenerator;
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/package-info.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/package-info.java
new file mode 100644
index 0000000..40fa263
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.ga;
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/population/ListPopulation.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/population/ListPopulation.java
new file mode 100644
index 0000000..1622d9c
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/population/ListPopulation.java
@@ -0,0 +1,220 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.population;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+
+/**
+ * Population of chromosomes represented by a {@link List}.
+ *
+ * @param <P> phenotype of chromosome
+ * @since 2.0
+ */
+public class ListPopulation<P> implements Population<P> {
+
+    /** new line constant. **/
+    public static final String NEW_LINE = System.getProperty("line.separator");
+
+    /** List of chromosomes. */
+    private final List<Chromosome<P>> chromosomes;
+
+    /** maximal size of the population. */
+    private int populationLimit;
+
+    /**
+     * Creates a new ListPopulation instance and initializes its inner chromosome
+     * list.
+     *
+     * @param populationLimit maximal size of the population
+     */
+    public ListPopulation(final int populationLimit) {
+        this(Collections.<Chromosome<P>>emptyList(), populationLimit);
+    }
+
+    /**
+     * Creates a new ListPopulation instance.
+     * <p>
+     * Note: the chromosomes of the specified list are added to the population.
+     *
+     * @param chromosomes     list of chromosomes to be added to the population
+     * @param populationLimit maximal size of the population
+     */
+    public ListPopulation(final List<Chromosome<P>> chromosomes, final int populationLimit) {
+
+        Objects.requireNonNull(chromosomes);
+
+        if (populationLimit <= 0) {
+            throw new GeneticException(GeneticException.NOT_STRICTLY_POSITIVE, populationLimit);
+        }
+        if (chromosomes.size() > populationLimit) {
+            throw new GeneticException(GeneticException.LIST_OF_CHROMOSOMES_BIGGER_THAN_POPULATION_SIZE,
+                    chromosomes.size(), populationLimit);
+        }
+        this.populationLimit = populationLimit;
+        this.chromosomes = new ArrayList<>(populationLimit);
+        this.chromosomes.addAll(chromosomes);
+    }
+
+    /**
+     * Add a {@link Collection} of chromosomes to this {@link Population}.
+     * @param chromosomeColl a {@link Collection} of chromosomes
+     * @since 3.1
+     */
+    public void addChromosomes(final Collection<Chromosome<P>> chromosomeColl) {
+        if (chromosomes.size() + chromosomeColl.size() > populationLimit) {
+            throw new GeneticException(GeneticException.LIST_OF_CHROMOSOMES_BIGGER_THAN_POPULATION_SIZE,
+                    chromosomes.size(), populationLimit);
+        }
+        this.chromosomes.addAll(chromosomeColl);
+    }
+
+    /**
+     * Returns an unmodifiable list of the chromosomes in this population.
+     * @return the unmodifiable list of chromosomes
+     */
+    public List<Chromosome<P>> getChromosomes() {
+        return Collections.unmodifiableList(chromosomes);
+    }
+
+    /**
+     * Access the list of chromosomes.
+     * @return the list of chromosomes
+     * @since 3.1
+     */
+    protected List<Chromosome<P>> getChromosomeList() {
+        return chromosomes;
+    }
+
+    /**
+     * Add the given chromosome to the population.
+     * @param chromosome the chromosome to add.
+     */
+    @Override
+    public void addChromosome(final Chromosome<P> chromosome) {
+        if (chromosomes.size() >= populationLimit) {
+            throw new GeneticException(GeneticException.LIST_OF_CHROMOSOMES_BIGGER_THAN_POPULATION_SIZE,
+                    chromosomes.size(), populationLimit);
+        }
+        this.chromosomes.add(chromosome);
+    }
+
+    /**
+     * Access the fittest chromosome in this population.
+     * @return the fittest chromosome.
+     */
+    @Override
+    public Chromosome<P> getFittestChromosome() {
+        // best so far
+        return Collections.max(this.chromosomes);
+    }
+
+    /**
+     * Access the maximum population size.
+     * @return the maximum population size.
+     */
+    @Override
+    public int getPopulationLimit() {
+        return this.populationLimit;
+    }
+
+    /**
+     * Sets the maximal population size.
+     * @param populationLimit maximal population size.
+     */
+    public void setPopulationLimit(final int populationLimit) {
+        if (populationLimit <= 0) {
+            throw new GeneticException(GeneticException.POPULATION_LIMIT_NOT_POSITIVE, populationLimit);
+        }
+        if (populationLimit < chromosomes.size()) {
+            throw new GeneticException(GeneticException.POPULATION_LIMIT_LESS_THAN_LIST_OF_CHROMOSOMES_SIZE,
+                    populationLimit, chromosomes.size());
+        }
+        this.populationLimit = populationLimit;
+    }
+
+    /**
+     * Access the current population size.
+     * @return the current population size.
+     */
+    @Override
+    public int getPopulationSize() {
+        return this.chromosomes.size();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        final StringBuilder populationStrRepr = new StringBuilder();
+        for (Chromosome<P> chromosome : chromosomes) {
+            populationStrRepr.append(chromosome.toString());
+            populationStrRepr.append(NEW_LINE);
+        }
+        return populationStrRepr.toString();
+    }
+
+    /**
+     * Returns an iterator over the unmodifiable list of chromosomes.
+     * <p>
+     * Any call to {@link Iterator#remove()} will result in a
+     * {@link UnsupportedOperationException}.
+     * </p>
+     *
+     * @return chromosome iterator
+     */
+    @Override
+    public Iterator<Chromosome<P>> iterator() {
+        return getChromosomes().iterator();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Population<P> nextGeneration(final double elitismRate) {
+        final List<Chromosome<P>> oldChromosomes = getChromosomeList();
+
+        if ((int) (oldChromosomes.size() * elitismRate) == 0) {
+            // if no of elite chromosome is 0 crete and return an empty population instance.
+            return new ListPopulation<>(getPopulationLimit());
+        } else {
+            // create a new generation of chromosomes with same parameters and add the elit
+            // individuals.
+            final ListPopulation<P> nextGeneration = new ListPopulation<>(getPopulationLimit());
+
+            // Sort the chromosome according to ascending order of fitness.
+            Collections.sort(oldChromosomes);
+
+            // index of the last "not good enough" chromosome
+            final int boundIndex = (int) Math.ceil((1.0 - elitismRate) * oldChromosomes.size());
+            for (int i = boundIndex; i < oldChromosomes.size(); i++) {
+                nextGeneration.addChromosome(oldChromosomes.get(i));
+            }
+            return nextGeneration;
+        }
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/population/Population.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/population/Population.java
new file mode 100644
index 0000000..65cfe5f
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/population/Population.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.population;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+
+/**
+ * A collection of chromosomes that facilitates generational evolution.
+ *
+ * @param <P> phenotype of chromosome
+ * @since 2.0
+ */
+public interface Population<P> extends Iterable<Chromosome<P>> {
+
+    /**
+     * Access the current population size.
+     * @return the current population size.
+     */
+    int getPopulationSize();
+
+    /**
+     * Access the maximum population size.
+     * @return the maximum population size.
+     */
+    int getPopulationLimit();
+
+    /**
+     * Start the population for the next generation.
+     * @param elitismRate the Elitism Rate
+     * @return the beginnings of the next generation.
+     */
+    Population<P> nextGeneration(double elitismRate);
+
+    /**
+     * Add the given chromosome to the population.
+     * @param chromosome the chromosome to add.
+     */
+    void addChromosome(Chromosome<P> chromosome);
+
+    /**
+     * Access the fittest chromosome in this population.
+     * @return the fittest chromosome.
+     */
+    Chromosome<P> getFittestChromosome();
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/population/package-info.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/population/package-info.java
new file mode 100644
index 0000000..4d77dc9
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/population/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.ga.population;
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/selection/SelectionPolicy.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/selection/SelectionPolicy.java
new file mode 100644
index 0000000..7c8682a
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/selection/SelectionPolicy.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.selection;
+
+import org.apache.commons.math4.ga.chromosome.ChromosomePair;
+import org.apache.commons.math4.ga.population.Population;
+
+/**
+ * Algorithm used to select a chromosome pair from a population.
+ * @param <P> phenotype of chromosome
+ * @since 2.0
+ */
+public interface SelectionPolicy<P> {
+
+    /**
+     * Select two chromosomes from the population.
+     * @param population the population from which the chromosomes are chosen.
+     * @return the selected chromosomes.
+     */
+    ChromosomePair<P> select(Population<P> population);
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/selection/TournamentSelection.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/selection/TournamentSelection.java
new file mode 100644
index 0000000..8240f5d
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/selection/TournamentSelection.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.selection;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.chromosome.ChromosomePair;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.apache.commons.math4.ga.population.ListPopulation;
+import org.apache.commons.math4.ga.population.Population;
+import org.apache.commons.math4.ga.utils.RandomProviderManager;
+
+/**
+ * Tournament selection scheme. Each of the two selected chromosomes is selected
+ * based on n-ary tournament -- this is done by drawing {@link #arity} random
+ * chromosomes without replacement from the population, and then selecting the
+ * fittest chromosome among them.
+ * @param <P> phenotype of chromosome
+ * @since 2.0
+ */
+public class TournamentSelection<P> implements SelectionPolicy<P> {
+
+    /** number of chromosomes included in the tournament selections. */
+    private final int arity;
+
+    /**
+     * Creates a new TournamentSelection instance.
+     *
+     * @param arity how many chromosomes will be drawn to the tournament
+     */
+    public TournamentSelection(final int arity) {
+        this.arity = arity;
+    }
+
+    /**
+     * Select two chromosomes from the population. Each of the two selected
+     * chromosomes is selected based on n-ary tournament -- this is done by drawing
+     * {@link #arity} random chromosomes without replacement from the population,
+     * and then selecting the fittest chromosome among them.
+     *
+     * @param population the population from which the chromosomes are chosen.
+     * @return the selected chromosomes.
+     */
+    @Override
+    public ChromosomePair<P> select(final Population<P> population) {
+        if (!(population instanceof ListPopulation<?>)) {
+            throw new GeneticException(GeneticException.ILLEGAL_ARGUMENT, population);
+        }
+        return new ChromosomePair<>(tournament((ListPopulation<P>) population),
+                tournament((ListPopulation<P>) population));
+    }
+
+    /**
+     * Helper for {@link #select(Population)}. Draw {@link #arity} random
+     * chromosomes without replacement from the population, and then select the
+     * fittest chromosome among them.
+     *
+     * @param population the population from which the chromosomes are chosen.
+     * @return the selected chromosome.
+     */
+    private Chromosome<P> tournament(final ListPopulation<P> population) {
+        if (population.getPopulationSize() < this.arity) {
+            throw new GeneticException(GeneticException.TOO_LARGE, arity, population.getPopulationSize());
+        }
+
+        // create a copy of the chromosome list
+        final List<Chromosome<P>> chromosomes = new ArrayList<>(population.getChromosomes());
+        final List<Chromosome<P>> selectedChromosomes = new ArrayList<>();
+
+        for (int i = 0; i < this.arity; i++) {
+            // select a random individual and add it to the tournament
+            final int rind = RandomProviderManager.getRandomProvider().nextInt(chromosomes.size());
+            selectedChromosomes.add(chromosomes.get(rind));
+            // do not select it again
+            chromosomes.remove(rind);
+        }
+
+        // the winner takes it all
+        return Collections.max(selectedChromosomes);
+    }
+
+    /**
+     * Gets the arity (number of chromosomes drawn to the tournament).
+     *
+     * @return arity of the tournament
+     */
+    public int getArity() {
+        return arity;
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/selection/package-info.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/selection/package-info.java
new file mode 100644
index 0000000..b8ba3ae
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/selection/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.ga.selection;
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/stats/PopulationStatisticalSummary.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/stats/PopulationStatisticalSummary.java
new file mode 100644
index 0000000..e24f3a0
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/stats/PopulationStatisticalSummary.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga.stats;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+
+/**
+ * This interface represents the statistical summary for population fitness.
+ * @param <P> phenotype of chromosome
+ * @since 4.0
+ */
+public interface PopulationStatisticalSummary<P> {
+
+    /**
+     * Returns the arithmetic mean of population fitness.
+     * @return The mean or Double.NaN if no values have been added.
+     */
+    double getMeanFitness();
+
+    /**
+     * Returns the variance of the population fitness.
+     * @return The variance, Double.NaN if no values have been added or 0.0 for a
+     *         single value set.
+     */
+    double getFitnessVariance();
+
+    /**
+     * Returns the minimum fitness of the population.
+     * @return The max or Double.NaN if no values have been added.
+     */
+    double getMinFitness();
+
+    /**
+     * Returns the maximum fitness of the population.
+     * @return The max or Double.NaN if no values have been added.
+     */
+    double getMaxFitness();
+
+    /**
+     * Returns the population size.
+     * @return The number of available values
+     */
+    long getPopulationSize();
+
+    /**
+     * Calculates the rank of chromosome in population based on its fitness.
+     * @param chromosome chromosome, for which rank would be found
+     * @return the rank of chromosome
+     */
+    int findRank(Chromosome<P> chromosome);
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/stats/package-info.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/stats/package-info.java
new file mode 100644
index 0000000..f40707d
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/stats/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.ga.stats;
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/utils/ChromosomeRepresentationUtils.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/utils/ChromosomeRepresentationUtils.java
new file mode 100644
index 0000000..4750335
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/utils/ChromosomeRepresentationUtils.java
@@ -0,0 +1,211 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.utils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Objects;
+
+import org.apache.commons.math4.ga.chromosome.BinaryChromosome;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.apache.commons.rng.UniformRandomProvider;
+
+/**
+ * This interface generates all random representations for chromosomes.
+ * @since 4.0
+ */
+public interface ChromosomeRepresentationUtils {
+
+    /**
+     * Generates a representation corresponding to a random permutation of length l
+     * which can be passed to the RandomKey constructor.
+     *
+     * @param l length of the permutation
+     * @return representation of a random permutation
+     */
+    static List<Double> randomPermutation(final int l) {
+        final UniformRandomProvider randomProvider = RandomProviderManager.getRandomProvider();
+        final List<Double> repr = new ArrayList<>(l);
+        for (int i = 0; i < l; i++) {
+            repr.add(randomProvider.nextDouble());
+        }
+        return repr;
+    }
+
+    /**
+     * Generates a representation corresponding to an identity permutation of length
+     * l which can be passed to the RandomKey constructor.
+     *
+     * @param l length of the permutation
+     * @return representation of an identity permutation
+     */
+    static List<Double> identityPermutation(final int l) {
+        final List<Double> repr = new ArrayList<>(l);
+        for (int i = 0; i < l; i++) {
+            repr.add((double) i / l);
+        }
+        return repr;
+    }
+
+    /**
+     * Generates a representation of a permutation corresponding to the
+     * <code>data</code> sorted by <code>comparator</code>. The <code>data</code> is
+     * not modified during the process.
+     *
+     * This is useful if you want to inject some permutations to the initial
+     * population.
+     *
+     * @param <S>        type of the data
+     * @param data       list of data determining the order
+     * @param comparator how the data will be compared
+     * @return list representation of the permutation corresponding to the
+     *         parameters
+     */
+    static <S> List<Double> comparatorPermutation(final List<S> data, final Comparator<S> comparator) {
+        final List<S> sortedData = new ArrayList<>(data);
+        Collections.sort(sortedData, comparator);
+
+        return inducedPermutation(data, sortedData);
+    }
+
+    /**
+     * Generates a representation of a permutation corresponding to a permutation
+     * which yields <code>permutedData</code> when applied to
+     * <code>originalData</code>.
+     *
+     * This method can be viewed as an inverse to decode().
+     *
+     * @param <S>          type of the data
+     * @param originalData the original, unpermuted data
+     * @param permutedData the data, somehow permuted
+     * @return representation of a permutation corresponding to the permutation
+     *         {@code originalData -> permutedData}
+     */
+    static <S> List<Double> inducedPermutation(final List<S> originalData, final List<S> permutedData) {
+
+        if (originalData.size() != permutedData.size()) {
+            throw new GeneticException(GeneticException.SIZE_MISMATCH, permutedData.size(), originalData.size());
+        }
+        final int l = originalData.size();
+
+        final List<S> origDataCopy = new ArrayList<>(originalData);
+
+        final Double[] res = new Double[l];
+        for (int i = 0; i < l; i++) {
+            final int index = origDataCopy.indexOf(permutedData.get(i));
+            if (index == -1) {
+                throw new GeneticException(GeneticException.DIFFERENT_ORIG_AND_PERMUTED_DATA);
+            }
+            res[index] = (double) i / l;
+            origDataCopy.set(index, null);
+        }
+        return Arrays.asList(res);
+    }
+
+    /**
+     * Returns a representation of a random binary array of length
+     * <code>length</code>.
+     * @param length length of the array
+     * @param min    minimum inclusive value of allele
+     * @param max    maximum exclusive value of allele
+     * @return a random binary array of length <code>length</code>
+     */
+    static List<Integer> randomIntegralRepresentation(final int length, final int min, final int max) {
+        final UniformRandomProvider randomProvider = RandomProviderManager.getRandomProvider();
+        final List<Integer> rList = new ArrayList<>(length);
+        for (int j = 0; j < length; j++) {
+            rList.add(min + randomProvider.nextInt(max - min));
+        }
+        return rList;
+    }
+
+    /**
+     * Returns a representation of a random binary array of length
+     * <code>length</code>.
+     * @param length length of the array
+     * @return a random binary array of length <code>length</code>
+     */
+    static long[] randomBinaryRepresentation(final long length) {
+        if (length > BinaryChromosome.MAX_LENGTH) {
+            throw new GeneticException(GeneticException.ILLEGAL_ARGUMENT,
+                    "length exceeded the max length " + BinaryChromosome.MAX_LENGTH);
+        }
+        final UniformRandomProvider randomProvider = RandomProviderManager.getRandomProvider();
+        int elementCount = (int) Math.ceil(length / (double)Long.SIZE);
+        // random binary list
+        final long[] representation = new long[elementCount];
+        int remainder = (int) (length % Long.SIZE);
+        representation[0] = remainder == 0 ? randomProvider.nextLong() :
+                randomProvider.nextLong((long) Math.pow(2, remainder));
+        for (int i = 1; i < elementCount; i++) {
+            representation[i] = randomProvider.nextLong();
+        }
+        return representation;
+    }
+
+    /**
+     * Generates a random string representation of chromosome with specified
+     * characters.
+     * @param alleles characters representing alleles
+     * @param length  length of chromosome
+     * @return returns chromosome representation as string
+     */
+    static String randomStringRepresentation(char[] alleles, final long length) {
+        Objects.requireNonNull(alleles);
+        final StringBuilder representationStr = new StringBuilder();
+        for (int i = 0; i < length; i++) {
+            representationStr
+                    .append(alleles[(int) (RandomProviderManager.getRandomProvider().nextInt(alleles.length))]);
+        }
+        return representationStr.toString();
+    }
+
+    /**
+     * Generates a representation corresponding to a random double values[0..1] of
+     * length l.
+     * @param l length of the permutation
+     * @return representation of a random permutation
+     */
+    static List<Double> randomNormalizedDoubleRepresentation(final int l) {
+        return randomDoubleRepresentation(l, 0, 1);
+    }
+
+    /**
+     * Generates a representation corresponding to a random double values of length
+     * l.
+     * @param l   length of representation
+     * @param min minimum inclusive value of chromosome gene
+     * @param max maximum exclusive value of chromosome gene
+     * @return representation as List of Double
+     */
+    static List<Double> randomDoubleRepresentation(final int l, double min, double max) {
+        if (min >= max) {
+            throw new GeneticException(GeneticException.TOO_LARGE, min, max);
+        }
+        final double range = max - min;
+        final UniformRandomProvider randomProvider = RandomProviderManager.getRandomProvider();
+        final List<Double> repr = new ArrayList<>(l);
+        for (int i = 0; i < l; i++) {
+            repr.add(min + randomProvider.nextDouble() * range);
+        }
+        return repr;
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/utils/RandomProviderManager.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/utils/RandomProviderManager.java
new file mode 100644
index 0000000..0c01896
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/utils/RandomProviderManager.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math4.ga.utils;
+
+import org.apache.commons.rng.UniformRandomProvider;
+import org.apache.commons.rng.simple.RandomSource;
+import org.apache.commons.rng.simple.ThreadLocalRandomSource;
+
+/**
+ * An utility to generate per thread {@link UniformRandomProvider} instance.
+ * @since 4.0
+ */
+public final class RandomProviderManager {
+
+    /** The default RandomSource for random number generation. **/
+    private static RandomSource randomSource = RandomSource.XO_RO_SHI_RO_128_PP;
+
+    /**
+     * constructs the singleton instance.
+     */
+    private RandomProviderManager() {
+    }
+
+    /**
+     * Returns the (static) random generator.
+     * @return the static random generator shared by GA implementation classes
+     */
+    public static UniformRandomProvider getRandomProvider() {
+        return ThreadLocalRandomSource.current(RandomProviderManager.randomSource);
+    }
+
+}
diff --git a/commons-math-ga/src/main/java/org/apache/commons/math4/ga/utils/package-info.java b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/utils/package-info.java
new file mode 100644
index 0000000..0e8c79a
--- /dev/null
+++ b/commons-math-ga/src/main/java/org/apache/commons/math4/ga/utils/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * This package provides Genetic Algorithms components and implementations.
+ */
+package org.apache.commons.math4.ga.utils;
diff --git a/commons-math-ga/src/test/java/org/apache/commons/math4/ga/GeneticAlgorithmTestBinaryOneMax.java b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/GeneticAlgorithmTestBinaryOneMax.java
new file mode 100644
index 0000000..99a3785
--- /dev/null
+++ b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/GeneticAlgorithmTestBinaryOneMax.java
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.commons.math4.ga.chromosome.BinaryChromosome;
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.convergence.FixedGenerationCount;
+import org.apache.commons.math4.ga.convergence.StoppingCondition;
+import org.apache.commons.math4.ga.crossover.OnePointBinaryCrossover;
+import org.apache.commons.math4.ga.crossover.OnePointCrossover;
+import org.apache.commons.math4.ga.decoder.Decoder;
+import org.apache.commons.math4.ga.fitness.FitnessFunction;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.apache.commons.math4.ga.listener.ConvergenceListener;
+import org.apache.commons.math4.ga.listener.ConvergenceListenerRegistry;
+import org.apache.commons.math4.ga.mutation.BinaryMutation;
+import org.apache.commons.math4.ga.population.ListPopulation;
+import org.apache.commons.math4.ga.population.Population;
+import org.apache.commons.math4.ga.selection.TournamentSelection;
+import org.apache.commons.math4.ga.utils.ChromosomeRepresentationUtils;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * This is also an example of usage.
+ */
+public class GeneticAlgorithmTestBinaryOneMax {
+
+    // parameters for the GA
+    private static final int DIMENSION = 50;
+    private static final int POPULATION_SIZE = 50;
+    private static final int NUM_GENERATIONS = 50;
+    private static final double CROSSOVER_RATE = 1;
+    private static final double MUTATION_RATE = 0.1;
+    private static final int TOURNAMENT_ARITY = 2;
+
+    @Test
+    public void test() {
+        removeListeners();
+
+        // initialize a new genetic algorithm
+        GeneticAlgorithm<List<Integer>> ga = new GeneticAlgorithm<>(new OnePointBinaryCrossover<List<Integer>>(),
+                CROSSOVER_RATE, new BinaryMutation<List<Integer>>(), MUTATION_RATE,
+                new TournamentSelection<List<Integer>>(TOURNAMENT_ARITY));
+
+        Assertions.assertEquals(0, ga.getGenerationsEvolved());
+
+        // initial population
+        Population<List<Integer>> initial = randomPopulation();
+        // stopping conditions
+        StoppingCondition<List<Integer>> stopCond = new FixedGenerationCount<>(NUM_GENERATIONS);
+
+        // best initial chromosome
+        Chromosome<List<Integer>> bestInitial = initial.getFittestChromosome();
+
+        // run the algorithm
+        Population<List<Integer>> finalPopulation = ga.evolve(initial, stopCond);
+
+        // best chromosome from the final population
+        Chromosome<List<Integer>> bestFinal = finalPopulation.getFittestChromosome();
+
+        // the only thing we can test is whether the final solution is not worse than
+        // the initial one
+        // however, for some implementations of GA, this need not be true :)
+
+        Assertions.assertTrue(bestFinal.compareTo(bestInitial) > 0);
+        Assertions.assertEquals(NUM_GENERATIONS, ga.getGenerationsEvolved());
+
+    }
+
+    private void removeListeners() {
+        try {
+            ConvergenceListenerRegistry<String> registry = ConvergenceListenerRegistry.<String>getInstance();
+            Field listenersField = registry.getClass().getDeclaredField("listeners");
+            boolean accessible = listenersField.isAccessible();
+            if (!accessible) {
+                listenersField.setAccessible(true);
+            }
+            @SuppressWarnings("unchecked")
+            List<ConvergenceListener<String>> listeners = (List<ConvergenceListener<String>>) listenersField
+                    .get(ConvergenceListenerRegistry.getInstance());
+            listeners.clear();
+            listenersField.setAccessible(accessible);
+        } catch (NoSuchFieldException | SecurityException e) {
+            e.printStackTrace();
+        } catch (IllegalArgumentException e) {
+            e.printStackTrace();
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Initializes a random population.
+     */
+    private ListPopulation<List<Integer>> randomPopulation() {
+        List<Chromosome<List<Integer>>> popList = new LinkedList<>();
+
+        for (int i = 0; i < POPULATION_SIZE; i++) {
+            BinaryChromosome<List<Integer>> randChrom = new FindOnes(
+                    ChromosomeRepresentationUtils.randomBinaryRepresentation(DIMENSION), DIMENSION);
+            popList.add(randChrom);
+        }
+        return new ListPopulation<>(popList, popList.size());
+    }
+
+    /**
+     * Chromosomes represented by a binary chromosome.
+     *
+     * The goal is to set all bits (genes) to 1.
+     */
+    private class FindOnes extends BinaryChromosome<List<Integer>> {
+
+        FindOnes(long[] representation, long length) {
+            super(representation, length, new OneMaxFitnessFunction(), new OneMaxDecoder());
+        }
+    }
+
+    private class OneMaxFitnessFunction implements FitnessFunction<List<Integer>> {
+
+        @Override
+        public double compute(List<Integer> decodedChromosome) {
+            double value = 0;
+            for (Integer allele : decodedChromosome) {
+                value += allele;
+            }
+            return value;
+        }
+
+    }
+
+    private class OneMaxDecoder implements Decoder<List<Integer>> {
+
+        @Override
+        public List<Integer> decode(Chromosome<List<Integer>> chromosome) {
+            BinaryChromosome<List<Integer>> binaryChromosome = (BinaryChromosome<List<Integer>>) chromosome;
+            List<Integer> phenotype = new ArrayList<>();
+            long[] representation = binaryChromosome.getRepresentation();
+            for (int i = 0; i < representation.length; i++) {
+                String value = Long.toUnsignedString(representation[i], 2);
+                for (int j = 64 - value.length(); j > 0; j--) {
+                    phenotype.add(Integer.valueOf(0));
+                }
+                for (int j = 0; j < value.length(); j++) {
+                    phenotype.add(Integer.parseInt("" + value.charAt(j)));
+                }
+            }
+            return phenotype;
+        }
+    }
+
+    @Test
+    public void testCrossoverRate() {
+        Assertions.assertThrows(GeneticException.class, () -> {
+            new GeneticAlgorithm<>(new OnePointCrossover<>(), 1.5, new BinaryMutation<>(), .01,
+                    new TournamentSelection<>(10));
+        });
+    }
+
+    @Test
+    public void testMutationRate() {
+        Assertions.assertThrows(GeneticException.class, () -> {
+            new GeneticAlgorithm<>(new OnePointCrossover<>(), .5, new BinaryMutation<>(), 1.5,
+                    new TournamentSelection<>(10));
+        });
+    }
+
+}
diff --git a/commons-math-ga/src/test/java/org/apache/commons/math4/ga/GeneticAlgorithmTestPermutations.java b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/GeneticAlgorithmTestPermutations.java
new file mode 100644
index 0000000..4bfb2ec
--- /dev/null
+++ b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/GeneticAlgorithmTestPermutations.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.chromosome.RealValuedChromosome;
+import org.apache.commons.math4.ga.convergence.FixedGenerationCount;
+import org.apache.commons.math4.ga.convergence.StoppingCondition;
+import org.apache.commons.math4.ga.crossover.OnePointCrossover;
+import org.apache.commons.math4.ga.decoder.RandomKeyDecoder;
+import org.apache.commons.math4.ga.fitness.FitnessFunction;
+import org.apache.commons.math4.ga.mutation.RealValuedMutation;
+import org.apache.commons.math4.ga.population.ListPopulation;
+import org.apache.commons.math4.ga.population.Population;
+import org.apache.commons.math4.ga.selection.TournamentSelection;
+import org.apache.commons.math4.ga.utils.ChromosomeRepresentationUtils;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * This is also an example of usage.
+ *
+ * This algorithm does "stochastic sorting" of a sequence 0,...,N.
+ *
+ */
+public class GeneticAlgorithmTestPermutations {
+
+    // parameters for the GA
+    private static final int DIMENSION = 20;
+    private static final int POPULATION_SIZE = 80;
+    private static final int NUM_GENERATIONS = 200;
+    private static final double ELITISM_RATE = 0.2;
+    private static final double CROSSOVER_RATE = 1;
+    private static final double MUTATION_RATE = 0.08;
+    private static final int TOURNAMENT_ARITY = 2;
+
+    // numbers from 0 to N-1
+    private static final List<Integer> sequence = new ArrayList<>();
+    static {
+        for (int i = 0; i < DIMENSION; i++) {
+            sequence.add(i);
+        }
+    }
+
+    @Test
+    public void test() {
+        // to test a stochastic algorithm is hard, so this will rather be an usage
+        // example
+
+        // initialize a new genetic algorithm
+        GeneticAlgorithm<List<Integer>> ga = new GeneticAlgorithm<>(new OnePointCrossover<Integer, List<Integer>>(),
+                CROSSOVER_RATE, new RealValuedMutation<List<Integer>>(), MUTATION_RATE,
+                new TournamentSelection<List<Integer>>(TOURNAMENT_ARITY), ELITISM_RATE);
+
+        // initial population
+        Population<List<Integer>> initial = randomPopulation();
+        // stopping conditions
+        StoppingCondition<List<Integer>> stopCond = new FixedGenerationCount<>(NUM_GENERATIONS);
+
+        // best initial chromosome
+        Chromosome<List<Integer>> bestInitial = initial.getFittestChromosome();
+
+        // run the algorithm
+        Population<List<Integer>> finalPopulation = ga.evolve(initial, stopCond);
+
+        // best chromosome from the final population
+        Chromosome<List<Integer>> bestFinal = finalPopulation.getFittestChromosome();
+
+        // the only thing we can test is whether the final solution is not worse than
+        // the initial one
+        // however, for some implementations of GA, this need not be true :)
+
+        Assertions.assertTrue(bestFinal.compareTo(bestInitial) > 0);
+
+    }
+
+    /**
+     * Initializes a random population
+     */
+    private static Population<List<Integer>> randomPopulation() {
+        List<Chromosome<List<Integer>>> popList = new ArrayList<>();
+        for (int i = 0; i < POPULATION_SIZE; i++) {
+            Chromosome<List<Integer>> randChrom = new MinPermutations(
+                    ChromosomeRepresentationUtils.randomPermutation(DIMENSION));
+            popList.add(randChrom);
+        }
+        return new ListPopulation<List<Integer>>(popList, popList.size());
+    }
+
+    /**
+     * Chromosomes representing a permutation of (0,1,2,...,DIMENSION-1).
+     *
+     * The goal is to sort the sequence.
+     */
+    private static class MinPermutations extends RealValuedChromosome<List<Integer>> {
+
+        MinPermutations(List<Double> representation) {
+            super(representation, new MinPermutationsFitnessFunction(), new RandomKeyDecoder<>(sequence));
+        }
+
+        @Override
+        public RealValuedChromosome<List<Integer>> newChromosome(List<Double> chromosomeRepresentation) {
+            return new MinPermutations(chromosomeRepresentation);
+        }
+
+    }
+
+    private static class MinPermutationsFitnessFunction implements FitnessFunction<List<Integer>> {
+
+        @Override
+        public double compute(List<Integer> decodedChromosome) {
+            double res = 0.0;
+            for (int i = 0; i < decodedChromosome.size(); i++) {
+                int value = decodedChromosome.get(i);
+                if (value != i) {
+                    // bad position found
+                    res += Math.abs(value - i);
+                }
+            }
+            // the most fitted chromosome is the one with minimal error
+            // therefore we must return negative value
+            return -res;
+        }
+
+    }
+
+}
diff --git a/commons-math-ga/src/test/java/org/apache/commons/math4/ga/chromosome/AbstractChromosomeTest.java b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/chromosome/AbstractChromosomeTest.java
new file mode 100644
index 0000000..a682024
--- /dev/null
+++ b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/chromosome/AbstractChromosomeTest.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.chromosome;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class AbstractChromosomeTest {
+
+    @Test
+    public void testGetFitness() {
+        Chromosome<String> c1 = new AbstractChromosome<String>(chromosome -> 1, chromosome -> "1") {
+        };
+        Assertions.assertEquals(1, c1.evaluate(), .001);
+    }
+
+    @Test
+    public void testDecode() {
+        Chromosome<String> c1 = new AbstractChromosome<String>(chromosome -> 1, chromosome -> "1") {
+        };
+        Assertions.assertEquals("1", c1.decode());
+    }
+
+    @Test
+    public void testCompareTo() {
+        Chromosome<String> c1 = new AbstractChromosome<String>(chromosome -> 0, chromosome -> "0") {
+        };
+        Chromosome<String> c2 = new AbstractChromosome<String>(chromosome -> 10, chromosome -> "10") {
+        };
+        Chromosome<String> c3 = new AbstractChromosome<String>(chromosome -> 10, chromosome -> "10") {
+        };
+
+        Assertions.assertTrue(c1.compareTo(c2) < 0);
+        Assertions.assertTrue(c2.compareTo(c1) > 0);
+        Assertions.assertEquals(0, c3.compareTo(c2));
+        Assertions.assertEquals(0, c2.compareTo(c3));
+    }
+
+    @Test
+    public void testIsSame() {
+        AbstractChromosome<String> c1 = new AbstractChromosome<String>(chromosome -> 1, chromosome -> "1") {
+        };
+        AbstractChromosome<String> c2 = new AbstractChromosome<String>(chromosome -> 2, chromosome -> "2") {
+        };
+        AbstractChromosome<String> c3 = new AbstractChromosome<String>(chromosome -> 3, chromosome -> "1") {
+        };
+        Assertions.assertTrue(c1.isSame(c3));
+        Assertions.assertFalse(c1.isSame(c2));
+    }
+
+}
diff --git a/commons-math-ga/src/test/java/org/apache/commons/math4/ga/chromosome/BinaryChromosomeTest.java b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/chromosome/BinaryChromosomeTest.java
new file mode 100644
index 0000000..ef6669a
--- /dev/null
+++ b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/chromosome/BinaryChromosomeTest.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.chromosome;
+
+import org.apache.commons.math4.ga.dummy.DummyListChromosomeDecoder;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.apache.commons.math4.ga.utils.ChromosomeRepresentationUtils;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class BinaryChromosomeTest {
+
+    @Test
+    public void testInvalidConstructor() {
+        Assertions.assertThrows(GeneticException.class, () -> {
+            new BinaryChromosome<String>(ChromosomeRepresentationUtils.randomBinaryRepresentation(10), Long.MAX_VALUE,
+                c -> 0, c -> "0");
+        });
+        Assertions.assertThrows(GeneticException.class, () -> {
+            new BinaryChromosome<String>(ChromosomeRepresentationUtils.randomBinaryRepresentation(10), 100, c -> 0,
+                c -> "0");
+        });
+    }
+
+    @Test
+    public void testRandomConstructor() {
+        for (int i = 0; i < 20; i++) {
+            BinaryChromosome.<String>randomChromosome(10, c -> 1, new DummyListChromosomeDecoder<>("1"));
+        }
+    }
+
+    @Test
+    public void testGetStringRepresentation() {
+        int length = 10;
+        int startToEndGap = 1;
+        testStringRepresentationWithRanges(length, startToEndGap);
+
+        length = 64;
+        startToEndGap = 10;
+        testStringRepresentationWithRanges(length, startToEndGap);
+
+        length = 100;
+        startToEndGap = 50;
+        testStringRepresentationWithRanges(length, startToEndGap);
+
+        length = 128;
+        startToEndGap = 70;
+        testStringRepresentationWithRanges(length, startToEndGap);
+
+        length = 250;
+        startToEndGap = 128;
+        testStringRepresentationWithRanges(length, startToEndGap);
+
+        length = 350;
+        startToEndGap = 228;
+        testStringRepresentationWithRanges(length, startToEndGap);
+
+        length = 450;
+        startToEndGap = 108;
+        testStringRepresentationWithRanges(length, startToEndGap);
+
+    }
+
+    private void testStringRepresentationWithRanges(int length, int startToEndGap) {
+        for (int i = 0; i < 50; i++) {
+            String representationStr = ChromosomeRepresentationUtils.randomStringRepresentation(new char[] {'0', '1'},
+                    length);
+            BinaryChromosome<String> chromosome = new BinaryChromosome<>(representationStr, c -> 0, c -> "0");
+            Assertions.assertEquals(representationStr, chromosome.getStringRepresentation());
+            for (int j = 0; j < length - startToEndGap; j++) {
+                int index = (int) ((length + 1 - startToEndGap) * Math.random());
+                Assertions.assertEquals(representationStr.substring(index, index + startToEndGap),
+                        chromosome.getStringRepresentation(index, index + startToEndGap));
+            }
+        }
+    }
+
+}
diff --git a/commons-math-ga/src/test/java/org/apache/commons/math4/ga/chromosome/ChromosomePairTest.java b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/chromosome/ChromosomePairTest.java
new file mode 100644
index 0000000..f43a27c
--- /dev/null
+++ b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/chromosome/ChromosomePairTest.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.chromosome;
+
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+public class ChromosomePairTest {
+
+    @Test
+    public void testChromosomePair() {
+        Chromosome<String> chromosome1 = new AbstractChromosome<String>(c -> 0, c -> "0") {
+        };
+        Chromosome<String> chromosome2 = new AbstractChromosome<String>(c -> 1, c -> "1") {
+        };
+        ChromosomePair<String> chromosomePair = new ChromosomePair<>(chromosome1, chromosome2);
+
+        Assertions.assertEquals(chromosomePair.getFirst(), chromosome1);
+        Assertions.assertEquals(chromosomePair.getSecond(), chromosome2);
+
+        Assertions.assertNotNull(chromosomePair.toString());
+    }
+
+}
diff --git a/commons-math-ga/src/test/java/org/apache/commons/math4/ga/chromosome/IntegralValuedChromosomeTest.java b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/chromosome/IntegralValuedChromosomeTest.java
new file mode 100644
index 0000000..e2a89fe
--- /dev/null
+++ b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/chromosome/IntegralValuedChromosomeTest.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.chromosome;
+
+import org.apache.commons.math4.ga.dummy.DummyListChromosomeDecoder;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+
+import org.apache.commons.math4.ga.utils.ChromosomeRepresentationUtils;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class IntegralValuedChromosomeTest {
+
+    @Test
+    public void testIntegralValuedChromosome() {
+        int min = 0;
+        int max = 10;
+        IntegralValuedChromosome<String> chromosome = new IntegralValuedChromosome<>(
+                ChromosomeRepresentationUtils.randomIntegralRepresentation(10, min, max), c -> 0,
+                new DummyListChromosomeDecoder<>("0"), min, max);
+        Assertions.assertEquals(min, chromosome.getMin());
+        Assertions.assertEquals(max, chromosome.getMax());
+
+        IntegralValuedChromosome<String> chromosome1 = new IntegralValuedChromosome<>(
+                ChromosomeRepresentationUtils.randomIntegralRepresentation(10, min, max).toArray(new Integer[10]),
+            c -> 0, new DummyListChromosomeDecoder<>("0"), min, max);
+        Assertions.assertEquals(min, chromosome1.getMin());
+        Assertions.assertEquals(max, chromosome1.getMax());
+    }
+
+    @Test
+    public void testCheckValidity() {
+        int min = 0;
+        int max = 10;
+        Assertions.assertThrows(GeneticException.class, () -> {
+            new IntegralValuedChromosome<>(ChromosomeRepresentationUtils.randomIntegralRepresentation(10, min, max),
+                c -> 0, new DummyListChromosomeDecoder<>("0"), max, min);
+        });
+    }
+
+    @Test
+    public void testCheckValidity1() {
+        int min = 0;
+        int max = 10;
+        Assertions.assertThrows(GeneticException.class, () -> {
+            new IntegralValuedChromosome<>(
+                    ChromosomeRepresentationUtils.randomIntegralRepresentation(10, min - 10, max + 10), c -> 0,
+                    new DummyListChromosomeDecoder<>("0"), min, max);
+        });
+
+    }
+
+    @Test
+    public void testNewChromosome() {
+        int min = 0;
+        int max = 10;
+        IntegralValuedChromosome<String> chromosome = new IntegralValuedChromosome<>(
+                ChromosomeRepresentationUtils.randomIntegralRepresentation(10, min, max), c -> 0,
+                new DummyListChromosomeDecoder<>("0"), min, max);
+        IntegralValuedChromosome<String> newChromosome = chromosome
+                .newChromosome(ChromosomeRepresentationUtils.randomIntegralRepresentation(10, min, max));
+        Assertions.assertEquals(chromosome.getMin(), newChromosome.getMin());
+        Assertions.assertEquals(chromosome.getMax(), newChromosome.getMax());
+        Assertions.assertEquals(chromosome.getDecoder(), newChromosome.getDecoder());
+        Assertions.assertEquals(chromosome.getFitnessFunction(), newChromosome.getFitnessFunction());
+
+    }
+
+    @Test
+    public void testRandomChromosome() {
+        int min = 0;
+        int max = 10;
+        IntegralValuedChromosome<String> chromosome = IntegralValuedChromosome.<String>randomChromosome(10, c -> 0,
+                new DummyListChromosomeDecoder<>("0"), min, max);
+        Assertions.assertEquals(min, chromosome.getMin());
+        Assertions.assertEquals(max, chromosome.getMax());
+    }
+
+}
diff --git a/commons-math-ga/src/test/java/org/apache/commons/math4/ga/chromosome/RealValuedChromosomeTest.java b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/chromosome/RealValuedChromosomeTest.java
new file mode 100644
index 0000000..333e2ca
--- /dev/null
+++ b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/chromosome/RealValuedChromosomeTest.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.chromosome;
+
+import org.apache.commons.math4.ga.dummy.DummyListChromosomeDecoder;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.apache.commons.math4.ga.utils.ChromosomeRepresentationUtils;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class RealValuedChromosomeTest {
+
+    @Test
+    public void test() {
+        for (int i = 0; i < 10; i++) {
+            new RealValuedChromosome<>(ChromosomeRepresentationUtils.randomDoubleRepresentation(10, 0, 1), c1 -> 1,
+                    new DummyListChromosomeDecoder<>("1"));
+            new RealValuedChromosome<>(
+                    ChromosomeRepresentationUtils.randomDoubleRepresentation(10, 0, 1).toArray(new Double[10]), c -> 0,
+                    new DummyListChromosomeDecoder<>("0"));
+        }
+    }
+
+    @Test
+    public void testNewChromosome() {
+        for (int i = 0; i < 10; i++) {
+            RealValuedChromosome<String> chromosome = new RealValuedChromosome<>(
+                    ChromosomeRepresentationUtils.randomDoubleRepresentation(10, 0, 1), c1 -> 1,
+                    new DummyListChromosomeDecoder<>("1"));
+            chromosome.newChromosome(ChromosomeRepresentationUtils.randomDoubleRepresentation(10, 0, 1));
+        }
+    }
+
+    @Test
+    public void testRandomChromosome() {
+        for (int i = 0; i < 10; i++) {
+            RealValuedChromosome.randomChromosome(5, c -> 0, new DummyListChromosomeDecoder<>("0"), 0, 2);
+        }
+    }
+
+    @Test
+    public void testCheckValidity() {
+        int min = 0;
+        int max = 10;
+        Assertions.assertThrows(GeneticException.class, () -> {
+            new RealValuedChromosome<>(ChromosomeRepresentationUtils.randomDoubleRepresentation(10, min, max), c -> 0,
+                    new DummyListChromosomeDecoder<>("0"), max, min);
+        });
+    }
+
+    @Test
+    public void testCheckValidity1() {
+        int min = 0;
+        int max = 10;
+        Assertions.assertThrows(GeneticException.class, () -> {
+            new RealValuedChromosome<>(ChromosomeRepresentationUtils.randomDoubleRepresentation(10, min - 10, max + 10),
+                c -> 0, new DummyListChromosomeDecoder<>("0"), min, max);
+        });
+    }
+
+}
diff --git a/commons-math-ga/src/test/java/org/apache/commons/math4/ga/convergencecond/FixedElapsedTimeTest.java b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/convergencecond/FixedElapsedTimeTest.java
new file mode 100644
index 0000000..e2681ab
--- /dev/null
+++ b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/convergencecond/FixedElapsedTimeTest.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.convergencecond;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.math4.ga.convergence.FixedElapsedTime;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.apache.commons.math4.ga.population.ListPopulation;
+import org.apache.commons.math4.ga.population.Population;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class FixedElapsedTimeTest {
+
+    @Test
+    public void testIsSatisfied() {
+        final Population<String> pop = new ListPopulation<>(10);
+
+        final long start = System.nanoTime();
+        final long duration = 3;
+        final FixedElapsedTime<String> tec = new FixedElapsedTime<String>(duration);
+
+        while (!tec.isSatisfied(pop)) {
+            try {
+                Thread.sleep(50);
+            } catch (InterruptedException e) {
+                // ignore
+            }
+        }
+
+        final long end = System.nanoTime();
+        final long elapsedTime = end - start;
+        final long diff = Math.abs(elapsedTime - TimeUnit.SECONDS.toNanos(duration));
+
+        Assertions.assertTrue(diff < TimeUnit.MILLISECONDS.toNanos(100));
+    }
+
+    @Test
+    public void testNegativeTime() {
+        Assertions.assertThrows(GeneticException.class, () -> {
+            new FixedElapsedTime<>(-10);
+        });
+    }
+}
diff --git a/commons-math-ga/src/test/java/org/apache/commons/math4/ga/convergencecond/FixedGenerationCountTest.java b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/convergencecond/FixedGenerationCountTest.java
new file mode 100644
index 0000000..5bf1567
--- /dev/null
+++ b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/convergencecond/FixedGenerationCountTest.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.convergencecond;
+
+import org.apache.commons.math4.ga.convergence.FixedGenerationCount;
+
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.apache.commons.math4.ga.population.ListPopulation;
+import org.apache.commons.math4.ga.population.Population;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class FixedGenerationCountTest {
+
+    @Test
+    public void testIsSatisfied() {
+        FixedGenerationCount<String> fgc = new FixedGenerationCount<String>(20);
+
+        int cnt = 0;
+        Population<String> pop = new ListPopulation<>(10);
+
+        while (!fgc.isSatisfied(pop)) {
+            cnt++;
+        }
+        Assertions.assertEquals(cnt, fgc.getNumGenerations());
+    }
+
+    @Test
+    public void testNegativeGenerationCount() {
+        Assertions.assertThrows(GeneticException.class, () -> {
+            new FixedGenerationCount<String>(-1);
+        });
+    }
+}
diff --git a/commons-math-ga/src/test/java/org/apache/commons/math4/ga/convergencecond/UnchangedBestFitnessTest.java b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/convergencecond/UnchangedBestFitnessTest.java
new file mode 100644
index 0000000..5fffd06
--- /dev/null
+++ b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/convergencecond/UnchangedBestFitnessTest.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.convergencecond;
+
+import java.util.ArrayList;
+
+import java.util.List;
+
+import org.apache.commons.math4.ga.chromosome.AbstractChromosome;
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.convergence.StoppingCondition;
+import org.apache.commons.math4.ga.convergence.UnchangedBestFitness;
+import org.apache.commons.math4.ga.internal.stats.PopulationStatisticalSummaryImpl;
+import org.apache.commons.math4.ga.population.ListPopulation;
+import org.apache.commons.math4.ga.population.Population;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class UnchangedBestFitnessTest {
+
+    @Test
+    public void testIsSatisfied() {
+
+        final int noOfGenerationsWithUnchangedBestFitness = 5;
+        StoppingCondition<String> stoppingCondition = new UnchangedBestFitness<>(
+                noOfGenerationsWithUnchangedBestFitness);
+
+        double[] fitnesses = new double[10];
+        for (int i = 0; i < 10; i++) {
+            fitnesses[i] = i;
+        }
+        List<Chromosome<String>> chromosomes = new ArrayList<>();
+        for (int i = 0; i < 10; i++) {
+            final double fitness = fitnesses[i];
+            Chromosome<String> ch = new AbstractChromosome<String>(c -> fitness, c -> "Fixed") {
+            };
+            chromosomes.add(ch);
+        }
+        Population<String> pop = new ListPopulation<>(chromosomes, 10);
+
+        double initialMaxFitness = new PopulationStatisticalSummaryImpl<>(pop).getMaxFitness();
+
+        int counter = 0;
+        while (!stoppingCondition.isSatisfied(pop)) {
+            counter++;
+        }
+
+        double maxFitnessAfterConvergence = new PopulationStatisticalSummaryImpl<>(pop).getMaxFitness();
+
+        Assertions.assertEquals(initialMaxFitness, maxFitnessAfterConvergence, .001);
+        Assertions.assertEquals(noOfGenerationsWithUnchangedBestFitness, counter);
+    }
+
+}
diff --git a/commons-math-ga/src/test/java/org/apache/commons/math4/ga/convergencecond/UnchangedMeanFitnessTest.java b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/convergencecond/UnchangedMeanFitnessTest.java
new file mode 100644
index 0000000..6e4042c
--- /dev/null
+++ b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/convergencecond/UnchangedMeanFitnessTest.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.convergencecond;
+
+import java.util.ArrayList;
+
+import java.util.List;
+
+import org.apache.commons.math4.ga.chromosome.AbstractChromosome;
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.convergence.StoppingCondition;
+import org.apache.commons.math4.ga.convergence.UnchangedMeanFitness;
+import org.apache.commons.math4.ga.internal.stats.PopulationStatisticalSummaryImpl;
+import org.apache.commons.math4.ga.population.ListPopulation;
+import org.apache.commons.math4.ga.population.Population;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class UnchangedMeanFitnessTest {
+
+    @Test
+    public void testIsSatisfied() {
+
+        final int noOfGenerationsWithUnchangedMeanFitness = 5;
+        StoppingCondition<String> stoppingCondition = new UnchangedMeanFitness<>(
+                noOfGenerationsWithUnchangedMeanFitness);
+
+        double[] fitnesses = new double[10];
+        for (int i = 0; i < 10; i++) {
+            fitnesses[i] = i;
+        }
+        List<Chromosome<String>> chromosomes = new ArrayList<>();
+        for (int i = 0; i < 10; i++) {
+            final double fitness = fitnesses[i];
+            Chromosome<String> ch = new AbstractChromosome<String>(c -> fitness, c -> "Fixed") {
+            };
+            chromosomes.add(ch);
+        }
+        Population<String> pop = new ListPopulation<>(chromosomes, 10);
+
+        double initialAverageFitness = new PopulationStatisticalSummaryImpl<>(pop).getMeanFitness();
+
+        int counter = 0;
+        while (!stoppingCondition.isSatisfied(pop)) {
+            counter++;
+        }
+
+        double averageFitnessAfterConvergence = new PopulationStatisticalSummaryImpl<>(pop).getMeanFitness();
+
+        Assertions.assertEquals(initialAverageFitness, averageFitnessAfterConvergence, .001);
+        Assertions.assertEquals(noOfGenerationsWithUnchangedMeanFitness, counter);
+    }
+
+}
diff --git a/commons-math-ga/src/test/java/org/apache/commons/math4/ga/crossover/AbstractChromosomeCrossoverPolicyTest.java b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/crossover/AbstractChromosomeCrossoverPolicyTest.java
new file mode 100644
index 0000000..c1249b5
--- /dev/null
+++ b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/crossover/AbstractChromosomeCrossoverPolicyTest.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.crossover;
+
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.chromosome.ChromosomePair;
+import org.apache.commons.math4.ga.dummy.DummyChromosome;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class AbstractChromosomeCrossoverPolicyTest {
+
+    @Test
+    public void testCrossoverProbability() {
+
+        CrossoverPolicy<String> crossoverPolicy = new AbstractChromosomeCrossoverPolicy<String>() {
+            @Override
+            protected ChromosomePair<String> crossover(Chromosome<String> first, Chromosome<String> second) {
+                return null;
+            }
+        };
+
+        Chromosome<String> ch1 = new DummyChromosome();
+
+        Chromosome<String> ch2 = new DummyChromosome();
+
+        Assertions.assertNull(crossoverPolicy.crossover(ch1, ch2, 1.0));
+        Assertions.assertNotNull(crossoverPolicy.crossover(ch1, ch2, 0.0));
+    }
+
+}
diff --git a/commons-math-ga/src/test/java/org/apache/commons/math4/ga/crossover/AbstractListChromosomeCrossoverPolicyTest.java b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/crossover/AbstractListChromosomeCrossoverPolicyTest.java
new file mode 100644
index 0000000..0739f0d
--- /dev/null
+++ b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/crossover/AbstractListChromosomeCrossoverPolicyTest.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.crossover;
+
+import org.apache.commons.math4.ga.chromosome.AbstractChromosome;
+import org.apache.commons.math4.ga.chromosome.AbstractListChromosome;
+import org.apache.commons.math4.ga.chromosome.Chromosome;
+import org.apache.commons.math4.ga.chromosome.ChromosomePair;
+import org.apache.commons.math4.ga.dummy.DummyListChromosome;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.apache.commons.math4.ga.utils.ChromosomeRepresentationUtils;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class AbstractListChromosomeCrossoverPolicyTest {
+
+    @Test
+    public void testCrossoverWithNonListChromosome() {
+
+        CrossoverPolicy<String> crossoverPolicy = new AbstractListChromosomeCrossoverPolicy<Integer, String>() {
+
+            @Override
+            protected ChromosomePair<String> mate(AbstractListChromosome<Integer, String> first,
+                    AbstractListChromosome<Integer, String> second) {
+                return new ChromosomePair<>(first, second);
+            }
+        };
+        Chromosome<String> ch1 = new AbstractChromosome<String>(c -> 0, c -> "0") {
+        };
+
+        Chromosome<String> ch2 = new AbstractChromosome<String>(c -> 1, c -> "1") {
+        };
+
+        Assertions.assertThrows(GeneticException.class, () -> {
+            crossoverPolicy.crossover(ch1, ch2, 1.0);
+        });
+
+    }
+
+    @Test
+    public void testCrossoverWithUnEqualLengthChromosome() {
+
+        CrossoverPolicy<String> crossoverPolicy = new AbstractListChromosomeCrossoverPolicy<Integer, String>() {
+
+            @Override
+            protected ChromosomePair<String> mate(AbstractListChromosome<Integer, String> first,
+                    AbstractListChromosome<Integer, String> second) {
+                return new ChromosomePair<>(first, second);
+            }
+        };
+        Chromosome<String> ch1 = new DummyListChromosome(
+                ChromosomeRepresentationUtils.randomIntegralRepresentation(10, 0, 2));
+
+        Chromosome<String> ch2 = new DummyListChromosome(
+                ChromosomeRepresentationUtils.randomIntegralRepresentation(12, 0, 2));
+
+        Assertions.assertThrows(GeneticException.class, () -> {
+            crossoverPolicy.crossover(ch1, ch2, 1.0);
+        });
+
+    }
+
+}
diff --git a/commons-math-ga/src/test/java/org/apache/commons/math4/ga/crossover/CycleCrossoverTest.java b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/crossover/CycleCrossoverTest.java
new file mode 100644
index 0000000..e8ac820
--- /dev/null
+++ b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/crossover/CycleCrossoverTest.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.crossover;
+
+import org.apache.commons.math4.ga.chromosome.ChromosomePair;
+import org.apache.commons.math4.ga.dummy.DummyListChromosome;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class CycleCrossoverTest {
+
+    @Test
+    public void testCrossoverExample() {
+        // taken from
+        // http://www.rubicite.com/Tutorials/GeneticAlgorithms/CrossoverOperators/CycleCrossoverOperator.aspx
+        final Integer[] p1 = new Integer[] {8, 4, 7, 3, 6, 2, 5, 1, 9, 0};
+        final Integer[] p2 = new Integer[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+        final DummyListChromosome p1c = new DummyListChromosome(p1);
+        final DummyListChromosome p2c = new DummyListChromosome(p2);
+
+        final CrossoverPolicy<String> cp = new CycleCrossover<Integer, String>();
+        final ChromosomePair<String> pair = cp.crossover(p1c, p2c, 1.0);
+
+        final Integer[] c1 = ((DummyListChromosome) pair.getFirst()).getRepresentation()
+                .toArray(new Integer[p1.length]);
+        final Integer[] c2 = ((DummyListChromosome) pair.getSecond()).getRepresentation()
+                .toArray(new Integer[p2.length]);
+
+        final Integer[] c1e = new Integer[] {8, 1, 2, 3, 4, 5, 6, 7, 9, 0};
+        final Integer[] c2e = new Integer[] {0, 4, 7, 3, 6, 2, 5, 1, 8, 9};
+
+        Assertions.assertArrayEquals(c1e, c1);
+        Assertions.assertArrayEquals(c2e, c2);
+    }
+
+    @Test
+    public void testCrossoverExample2() {
+        // taken from http://www.scribd.com/doc/54206412/32/Cycle-crossover
+        final Integer[] p1 = new Integer[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
+        final Integer[] p2 = new Integer[] {9, 3, 7, 8, 2, 6, 5, 1, 4};
+        final DummyListChromosome p1c = new DummyListChromosome(p1);
+        final DummyListChromosome p2c = new DummyListChromosome(p2);
+
+        final CrossoverPolicy<String> cp = new CycleCrossover<Integer, String>();
+        final ChromosomePair<String> pair = cp.crossover(p1c, p2c, 1.0);
+
+        final Integer[] c1 = ((DummyListChromosome) pair.getFirst()).getRepresentation()
+                .toArray(new Integer[p1.length]);
+        final Integer[] c2 = ((DummyListChromosome) pair.getSecond()).getRepresentation()
+                .toArray(new Integer[p2.length]);
+
+        final Integer[] c1e = new Integer[] {1, 3, 7, 4, 2, 6, 5, 8, 9};
+        final Integer[] c2e = new Integer[] {9, 2, 3, 8, 5, 6, 7, 1, 4};
+
+        Assertions.assertArrayEquals(c1e, c1);
+        Assertions.assertArrayEquals(c2e, c2);
+    }
+
+    @Test
+    public void testCrossover() {
+        final Integer[] p1 = new Integer[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+        final Integer[] p2 = new Integer[] {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
+        final DummyListChromosome p1c = new DummyListChromosome(p1);
+        final DummyListChromosome p2c = new DummyListChromosome(p2);
+
+        final CrossoverPolicy<String> cp = new CycleCrossover<Integer, String>(true);
+
+        for (int i = 0; i < 20; i++) {
+            final ChromosomePair<String> pair = cp.crossover(p1c, p2c, 1.0);
+
+            final Integer[] c1 = ((DummyListChromosome) pair.getFirst()).getRepresentation()
+                    .toArray(new Integer[p1.length]);
+            final Integer[] c2 = ((DummyListChromosome) pair.getSecond()).getRepresentation()
+                    .toArray(new Integer[p2.length]);
+
+            int index = 0;
+            // Determine if it is in the same spot as in the first parent, if
+            // not it comes from the second parent.
+            for (final Integer j : c1) {
+                if (!p1[index].equals(j)) {
+                    Assertions.assertEquals(j, p2[index]);
+                } else {
+                    Assertions.assertEquals(j, p1[index]);
+                }
+                index++;
+            }
+
+            // Same as above only for the second parent.
+            index = 0;
+            for (final Integer k : c2) {
+                if (p2[index] != k) {
+                    Assertions.assertEquals(k, p1[index]);
+                } else {
+                    Assertions.assertEquals(k, p2[index]);
+                }
+                index++;
+            }
+        }
+    }
+
+}
diff --git a/commons-math-ga/src/test/java/org/apache/commons/math4/ga/crossover/NPointCrossoverTest.java b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/crossover/NPointCrossoverTest.java
new file mode 100644
index 0000000..35a55b0
--- /dev/null
+++ b/commons-math-ga/src/test/java/org/apache/commons/math4/ga/crossover/NPointCrossoverTest.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.ga.crossover;
+
+import java.util.List;
+
+import org.apache.commons.math4.ga.chromosome.AbstractChromosome;
+import org.apache.commons.math4.ga.chromosome.ChromosomePair;
+import org.apache.commons.math4.ga.chromosome.IntegralValuedChromosome;
+import org.apache.commons.math4.ga.dummy.DummyListChromosomeDecoder;
+import org.apache.commons.math4.ga.internal.exception.GeneticException;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class NPointCrossoverTest {
+
+    @Test
+    public void testNumberIsTooLargeException() {
+        final Integer[] p1 = new Integer[] {1, 0, 1, 0, 0, 1, 0, 1, 1};
+        final Integer[] p2 = new Integer[] {0, 1, 1, 0, 1, 0, 1, 1, 1};
+
+        final IntegralValuedChromosome<String> p1c = new IntegralValuedChromosome<String>(p1, c -> 0,
+                new DummyListChromosomeDecoder<Integer>("0"), 0, 2);
+        final IntegralValuedChromosome<String> p2c = new IntegralValuedChromosome<String>(p2, c -> 0,
+                new DummyListChromosomeDecoder<Integer>("0"), 0, 2);
+
+        final CrossoverPolicy<String> cp = new NPointCrossover<Integer, String>(15);
+        Assertions.assertThrows(GeneticException.class, () -> {
+            cp.crossover(p1c, p2c, 1.0);
+        });
+    }
+
+    @Test
+    public void testCrossoverInvalidFixedLengthChromosomeFirst() {
+        final Integer[] p1 = new Integer[] {1, 0, 1, 0, 0, 1, 0, 1, 1};
+        final IntegralValuedChromosome<String> p1c = new IntegralValuedChromosome<String>(p1, chromosome -> 0,
+                new DummyListChromosomeDecoder<>("0"), 0, 2);
+        final AbstractChromosome<String> p2c = new AbstractChromosome<String>(chromosome -> 0,
+                new DummyListChromosomeDecoder<>("0")) {
+        };
+
... 1951 lines suppressed ...

[commons-math] 05/09: MATH-1563: Introducing new implementation of GA functionality (WIP).

Posted by er...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

erans pushed a commit to branch feature__MATH-1563__genetic_algorithm
in repository https://gitbox.apache.org/repos/asf/commons-math.git

commit 6e52481f2d720fd9aa88796e3bf7aefb268e5346
Author: avbasak1 <av...@in.ibm.com>
AuthorDate: Sun Jan 2 18:54:37 2022 +0530

    MATH-1563: Introducing new implementation of GA functionality (WIP).
---
 pom.xml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/pom.xml b/pom.xml
index 42c6cb4..fa534d9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -128,6 +128,7 @@
     <!-- 4. Modules that depend on "legacy" codes. -->
     <module>commons-math-examples</module>
 
+    <module>commons-math-ga</module>
   </modules>
 
   <scm>

[commons-math] 06/09: Move GA module declaration to ensure that there are no dependencies on legacy codes.

Posted by er...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

erans pushed a commit to branch feature__MATH-1563__genetic_algorithm
in repository https://gitbox.apache.org/repos/asf/commons-math.git

commit 2af5ba04a68c3d58cb8da952f1e8bf80950a526c
Author: Gilles Sadowski <gi...@gmail.com>
AuthorDate: Sun Jan 2 23:54:11 2022 +0100

    Move GA module declaration to ensure that there are no dependencies on legacy codes.
---
 pom.xml | 1 -
 1 file changed, 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index fa534d9..42c6cb4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -128,7 +128,6 @@
     <!-- 4. Modules that depend on "legacy" codes. -->
     <module>commons-math-examples</module>
 
-    <module>commons-math-ga</module>
   </modules>
 
   <scm>

[commons-math] 08/09: Merge branch 'feature__MATH-1563__genetic_algorithm' of https://gitbox.apache.org/repos/asf/commons-math into feature__MATH-1563__genetic_algorithm

Posted by er...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

erans pushed a commit to branch feature__MATH-1563__genetic_algorithm
in repository https://gitbox.apache.org/repos/asf/commons-math.git

commit 825a18a0486d6c51233d7461c9449375af659154
Merge: 770f4d9 76d6c40
Author: Gilles Sadowski <gi...@gmail.com>
AuthorDate: Wed Jan 19 05:23:13 2022 +0100

    Merge branch 'feature__MATH-1563__genetic_algorithm' of https://gitbox.apache.org/repos/asf/commons-math into feature__MATH-1563__genetic_algorithm


[commons-math] 02/09: Move GA module declaration to ensure that there are no dependencies on legacy codes.

Posted by er...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

erans pushed a commit to branch feature__MATH-1563__genetic_algorithm
in repository https://gitbox.apache.org/repos/asf/commons-math.git

commit a7797aa40f0e6c0d87723670643311ad15561880
Author: Gilles Sadowski <gi...@gmail.com>
AuthorDate: Sun Jan 2 23:54:11 2022 +0100

    Move GA module declaration to ensure that there are no dependencies on legacy codes.
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 14eaeed..42c6cb4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -116,6 +116,7 @@
     <module>commons-math-core</module>
     <module>commons-math-neuralnet</module>
     <module>commons-math-transform</module>
+    <module>commons-math-ga</module>
 
     <!-- 2. Modularized (but not refactored) legacy functionalities. -->
     <module>commons-math-legacy-exception</module>
@@ -127,7 +128,6 @@
     <!-- 4. Modules that depend on "legacy" codes. -->
     <module>commons-math-examples</module>
 
-    <module>commons-math-ga</module>
   </modules>
 
   <scm>

[commons-math] 03/09: MATH-1563: Introducing new implementation of GA functionality (WIP).

Posted by er...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

erans pushed a commit to branch feature__MATH-1563__genetic_algorithm
in repository https://gitbox.apache.org/repos/asf/commons-math.git

commit 67f376b1ecc8966caba11ae79a954c78859d88ef
Author: avbasak1 <av...@in.ibm.com>
AuthorDate: Sun Jan 2 18:54:37 2022 +0530

    MATH-1563: Introducing new implementation of GA functionality (WIP).
---
 pom.xml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/pom.xml b/pom.xml
index 42c6cb4..fa534d9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -128,6 +128,7 @@
     <!-- 4. Modules that depend on "legacy" codes. -->
     <module>commons-math-examples</module>
 
+    <module>commons-math-ga</module>
   </modules>
 
   <scm>

[commons-math] 07/09: Add "LICENCE" and "NOTICE" files.

Posted by er...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

erans pushed a commit to branch feature__MATH-1563__genetic_algorithm
in repository https://gitbox.apache.org/repos/asf/commons-math.git

commit 770f4d9d5b07918c807f7daef91cda4ce194fb0f
Author: Gilles Sadowski <gi...@gmail.com>
AuthorDate: Sat Jan 8 15:56:08 2022 +0100

    Add "LICENCE" and "NOTICE" files.
---
 commons-math-examples/examples-ga/LICENCE          | 201 +++++++++++++++++++++
 commons-math-examples/examples-ga/NOTICE           |   5 +
 .../examples-ga/examples-ga-math-functions/LICENCE | 201 +++++++++++++++++++++
 .../examples-ga/examples-ga-math-functions/NOTICE  |   5 +
 .../examples-ga/examples-ga-tsp/LICENCE            | 201 +++++++++++++++++++++
 .../examples-ga/examples-ga-tsp/NOTICE             |   5 +
 commons-math-ga/LICENCE                            | 201 +++++++++++++++++++++
 commons-math-ga/NOTICE                             |   5 +
 8 files changed, 824 insertions(+)

diff --git a/commons-math-examples/examples-ga/LICENCE b/commons-math-examples/examples-ga/LICENCE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/commons-math-examples/examples-ga/LICENCE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/commons-math-examples/examples-ga/NOTICE b/commons-math-examples/examples-ga/NOTICE
new file mode 100644
index 0000000..28031e8
--- /dev/null
+++ b/commons-math-examples/examples-ga/NOTICE
@@ -0,0 +1,5 @@
+Apache Commons Math
+Copyright 2001-2022 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/LICENCE b/commons-math-examples/examples-ga/examples-ga-math-functions/LICENCE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/LICENCE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/commons-math-examples/examples-ga/examples-ga-math-functions/NOTICE b/commons-math-examples/examples-ga/examples-ga-math-functions/NOTICE
new file mode 100644
index 0000000..28031e8
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-math-functions/NOTICE
@@ -0,0 +1,5 @@
+Apache Commons Math
+Copyright 2001-2022 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/commons-math-examples/examples-ga/examples-ga-tsp/LICENCE b/commons-math-examples/examples-ga/examples-ga-tsp/LICENCE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-tsp/LICENCE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/commons-math-examples/examples-ga/examples-ga-tsp/NOTICE b/commons-math-examples/examples-ga/examples-ga-tsp/NOTICE
new file mode 100644
index 0000000..28031e8
--- /dev/null
+++ b/commons-math-examples/examples-ga/examples-ga-tsp/NOTICE
@@ -0,0 +1,5 @@
+Apache Commons Math
+Copyright 2001-2022 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/commons-math-ga/LICENCE b/commons-math-ga/LICENCE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/commons-math-ga/LICENCE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/commons-math-ga/NOTICE b/commons-math-ga/NOTICE
new file mode 100644
index 0000000..28031e8
--- /dev/null
+++ b/commons-math-ga/NOTICE
@@ -0,0 +1,5 @@
+Apache Commons Math
+Copyright 2001-2022 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).

[commons-math] 09/09: Add dependency on "ga" module.

Posted by er...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

erans pushed a commit to branch feature__MATH-1563__genetic_algorithm
in repository https://gitbox.apache.org/repos/asf/commons-math.git

commit 378a1677886e3c40eb9ecda5eda88bbb55d0b355
Author: Gilles Sadowski <gi...@gmail.com>
AuthorDate: Wed Jan 19 05:46:06 2022 +0100

    Add dependency on "ga" module.
---
 commons-math-examples/pom.xml | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/commons-math-examples/pom.xml b/commons-math-examples/pom.xml
index 2619557..7ed9e7e 100644
--- a/commons-math-examples/pom.xml
+++ b/commons-math-examples/pom.xml
@@ -67,6 +67,12 @@
 
       <dependency>
         <groupId>org.apache.commons</groupId>
+        <artifactId>commons-math4-ga</artifactId>
+        <version>${math.version}</version>
+      </dependency>
+
+      <dependency>
+        <groupId>org.apache.commons</groupId>
         <artifactId>commons-math4-legacy</artifactId>
         <version>${math.version}</version>
       </dependency>
@@ -158,7 +164,7 @@
 
   <modules>
     <module>examples-sofm</module>
-	<module>examples-ga</module>
+    <module>examples-ga</module>
   </modules>
 
 </project>

[commons-math] 04/09: Move GA module declaration to ensure that there are no dependencies on legacy codes.

Posted by er...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

erans pushed a commit to branch feature__MATH-1563__genetic_algorithm
in repository https://gitbox.apache.org/repos/asf/commons-math.git

commit b79fc9ec7ea46c5ba76691e4cfc67b612209798f
Author: Gilles Sadowski <gi...@gmail.com>
AuthorDate: Sun Jan 2 23:54:11 2022 +0100

    Move GA module declaration to ensure that there are no dependencies on legacy codes.
---
 pom.xml | 1 -
 1 file changed, 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index fa534d9..42c6cb4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -128,7 +128,6 @@
     <!-- 4. Modules that depend on "legacy" codes. -->
     <module>commons-math-examples</module>
 
-    <module>commons-math-ga</module>
   </modules>
 
   <scm>