MATH-1547: Remove "findBest" and "findBestAndSecondBest" methods from "MapUtils".

Use equivalent functionality from class "MapRanking".
diff --git a/src/main/java/org/apache/commons/math4/ml/neuralnet/MapUtils.java b/src/main/java/org/apache/commons/math4/ml/neuralnet/MapUtils.java
index 4b1eb20..40500b6 100644
--- a/src/main/java/org/apache/commons/math4/ml/neuralnet/MapUtils.java
+++ b/src/main/java/org/apache/commons/math4/ml/neuralnet/MapUtils.java
@@ -24,7 +24,6 @@
 import org.apache.commons.math4.exception.NoDataException;
 import org.apache.commons.math4.ml.distance.DistanceMeasure;
 import org.apache.commons.math4.ml.neuralnet.twod.NeuronSquareMesh2D;
-import org.apache.commons.math4.util.Pair;
 
 /**
  * Utilities for network maps.
@@ -38,70 +37,6 @@
     private MapUtils() {}
 
     /**
-     * Finds the neuron that best matches the given features.
-     *
-     * @param features Data.
-     * @param neurons List of neurons to scan. If the list is empty
-     * {@code null} will be returned.
-     * @param distance Distance function. The neuron's features are
-     * passed as the first argument to {@link DistanceMeasure#compute(double[],double[])}.
-     * @return the neuron whose features are closest to the given data.
-     * @throws org.apache.commons.math4.exception.DimensionMismatchException
-     * if the size of the input is not compatible with the neurons features
-     * size.
-     */
-    public static Neuron findBest(double[] features,
-                                  Iterable<Neuron> neurons,
-                                  DistanceMeasure distance) {
-        return new MapRanking(neurons, distance).rank(features, 1).get(0);
-    }
-
-    /**
-     * Finds the two neurons that best match the given features.
-     *
-     * @param features Data.
-     * @param neurons List of neurons to scan. If the list is empty
-     * {@code null} will be returned.
-     * @param distance Distance function. The neuron's features are
-     * passed as the first argument to {@link DistanceMeasure#compute(double[],double[])}.
-     * @return the two neurons whose features are closest to the given data.
-     * @throws org.apache.commons.math4.exception.DimensionMismatchException
-     * if the size of the input is not compatible with the neurons features
-     * size.
-     */
-    public static Pair<Neuron, Neuron> findBestAndSecondBest(double[] features,
-                                                             Iterable<Neuron> neurons,
-                                                             DistanceMeasure distance) {
-        final List<Neuron> list = new MapRanking(neurons, distance).rank(features, 2);
-        return new Pair<>(list.get(0), list.get(1));
-    }
-
-    /**
-     * Creates a list of neurons sorted in increased order of the distance
-     * to the given {@code features}.
-     *
-     * @param features Data.
-     * @param neurons List of neurons to scan. If it is empty, an empty array
-     * will be returned.
-     * @param distance Distance function.
-     * @return the neurons, sorted in increasing order of distance in data
-     * space.
-     * @throws org.apache.commons.math4.exception.DimensionMismatchException
-     * if the size of the input is not compatible with the neurons features
-     * size.
-     *
-     * @see #findBest(double[],Iterable,DistanceMeasure)
-     * @see #findBestAndSecondBest(double[],Iterable,DistanceMeasure)
-     *
-     * @since 3.6
-     */
-    public static Neuron[] sort(double[] features,
-                                Iterable<Neuron> neurons,
-                                DistanceMeasure distance) {
-        return new MapRanking(neurons, distance).rank(features).toArray(new Neuron[0]);
-    }
-
-    /**
      * Computes the <a href="http://en.wikipedia.org/wiki/U-Matrix">
      *  U-matrix</a> of a two-dimensional map.
      *
@@ -150,10 +85,10 @@
                                               NeuronSquareMesh2D map,
                                               DistanceMeasure distance) {
         final HashMap<Neuron, Integer> hit = new HashMap<>();
-        final Network net = map.getNetwork();
+        final MapRanking rank = new MapRanking(map.getNetwork(), distance);
 
         for (double[] f : data) {
-            final Neuron best = findBest(f, net, distance);
+            final Neuron best = rank.rank(f, 1).get(0);
             final Integer count = hit.get(best);
             if (count == null) {
                 hit.put(best, 1);
@@ -196,11 +131,13 @@
     public static double computeQuantizationError(Iterable<double[]> data,
                                                   Iterable<Neuron> neurons,
                                                   DistanceMeasure distance) {
+        final MapRanking rank = new MapRanking(neurons, distance);
+
         double d = 0;
         int count = 0;
         for (double[] f : data) {
             ++count;
-            d += distance.compute(f, findBest(f, neurons, distance).getFeatures());
+            d += distance.compute(f, rank.rank(f, 1).get(0).getFeatures());
         }
 
         if (count == 0) {
@@ -224,12 +161,14 @@
     public static double computeTopographicError(Iterable<double[]> data,
                                                  Network net,
                                                  DistanceMeasure distance) {
+        final MapRanking rank = new MapRanking(net, distance);
+
         int notAdjacentCount = 0;
         int count = 0;
         for (double[] f : data) {
             ++count;
-            final Pair<Neuron, Neuron> p = findBestAndSecondBest(f, net, distance);
-            if (!net.getNeighbours(p.getFirst()).contains(p.getSecond())) {
+            final List<Neuron> p = rank.rank(f, 2);
+            if (!net.getNeighbours(p.get(0)).contains(p.get(1))) {
                 // Increment count if first and second best matching units
                 // are not neighbours.
                 ++notAdjacentCount;
diff --git a/src/main/java/org/apache/commons/math4/ml/neuralnet/sofm/KohonenUpdateAction.java b/src/main/java/org/apache/commons/math4/ml/neuralnet/sofm/KohonenUpdateAction.java
index 691fd90..162e69c 100644
--- a/src/main/java/org/apache/commons/math4/ml/neuralnet/sofm/KohonenUpdateAction.java
+++ b/src/main/java/org/apache/commons/math4/ml/neuralnet/sofm/KohonenUpdateAction.java
@@ -24,7 +24,7 @@
 import org.apache.commons.math4.analysis.function.Gaussian;
 import org.apache.commons.math4.linear.ArrayRealVector;
 import org.apache.commons.math4.ml.distance.DistanceMeasure;
-import org.apache.commons.math4.ml.neuralnet.MapUtils;
+import org.apache.commons.math4.ml.neuralnet.MapRanking;
 import org.apache.commons.math4.ml.neuralnet.Network;
 import org.apache.commons.math4.ml.neuralnet.Neuron;
 import org.apache.commons.math4.ml.neuralnet.UpdateAction;
@@ -194,8 +194,10 @@
     private Neuron findAndUpdateBestNeuron(Network net,
                                            double[] features,
                                            double learningRate) {
+        final MapRanking rank = new MapRanking(net, distance);
+
         while (true) {
-            final Neuron best = MapUtils.findBest(features, net, distance);
+            final Neuron best = rank.rank(features, 1).get(0);
 
             if (attemptNeuronUpdate(best, features, learningRate)) {
                 return best;
diff --git a/src/main/java/org/apache/commons/math4/ml/neuralnet/twod/util/HitHistogram.java b/src/main/java/org/apache/commons/math4/ml/neuralnet/twod/util/HitHistogram.java
index 98d253f..a88fa1d 100644
--- a/src/main/java/org/apache/commons/math4/ml/neuralnet/twod/util/HitHistogram.java
+++ b/src/main/java/org/apache/commons/math4/ml/neuralnet/twod/util/HitHistogram.java
@@ -17,7 +17,7 @@
 
 package org.apache.commons.math4.ml.neuralnet.twod.util;
 
-import org.apache.commons.math4.ml.neuralnet.MapUtils;
+import org.apache.commons.math4.ml.neuralnet.MapRanking;
 import org.apache.commons.math4.ml.neuralnet.Neuron;
 import org.apache.commons.math4.ml.neuralnet.twod.NeuronSquareMesh2D;
 import org.apache.commons.math4.ml.distance.DistanceMeasure;
@@ -54,6 +54,7 @@
         final int nC = map.getNumberOfColumns();
 
         final LocationFinder finder = new LocationFinder(map);
+        final MapRanking rank = new MapRanking(map.getNetwork(), distance);
 
         // Totla number of samples.
         int numSamples = 0;
@@ -61,7 +62,7 @@
         final double[][] hit = new double[nR][nC];
 
         for (double[] sample : data) {
-            final Neuron best = MapUtils.findBest(sample, map, distance);
+            final Neuron best = rank.rank(sample, 1).get(0);
 
             final LocationFinder.Location loc = finder.getLocation(best);
             final int row = loc.getRow();
diff --git a/src/main/java/org/apache/commons/math4/ml/neuralnet/twod/util/QuantizationError.java b/src/main/java/org/apache/commons/math4/ml/neuralnet/twod/util/QuantizationError.java
index 37b1c3d..f2bc9de 100644
--- a/src/main/java/org/apache/commons/math4/ml/neuralnet/twod/util/QuantizationError.java
+++ b/src/main/java/org/apache/commons/math4/ml/neuralnet/twod/util/QuantizationError.java
@@ -17,7 +17,7 @@
 
 package org.apache.commons.math4.ml.neuralnet.twod.util;
 
-import org.apache.commons.math4.ml.neuralnet.MapUtils;
+import org.apache.commons.math4.ml.neuralnet.MapRanking;
 import org.apache.commons.math4.ml.neuralnet.Neuron;
 import org.apache.commons.math4.ml.neuralnet.twod.NeuronSquareMesh2D;
 import org.apache.commons.math4.ml.distance.DistanceMeasure;
@@ -47,6 +47,7 @@
         final int nC = map.getNumberOfColumns();
 
         final LocationFinder finder = new LocationFinder(map);
+        final MapRanking rank = new MapRanking(map.getNetwork(), distance);
 
         // Hit bins.
         final int[][] hit = new int[nR][nC];
@@ -54,7 +55,7 @@
         final double[][] error = new double[nR][nC];
 
         for (double[] sample : data) {
-            final Neuron best = MapUtils.findBest(sample, map, distance);
+            final Neuron best = rank.rank(sample, 1).get(0);
 
             final LocationFinder.Location loc = finder.getLocation(best);
             final int row = loc.getRow();
diff --git a/src/main/java/org/apache/commons/math4/ml/neuralnet/twod/util/SmoothedDataHistogram.java b/src/main/java/org/apache/commons/math4/ml/neuralnet/twod/util/SmoothedDataHistogram.java
index 1327055..caca11f 100644
--- a/src/main/java/org/apache/commons/math4/ml/neuralnet/twod/util/SmoothedDataHistogram.java
+++ b/src/main/java/org/apache/commons/math4/ml/neuralnet/twod/util/SmoothedDataHistogram.java
@@ -17,7 +17,8 @@
 
 package org.apache.commons.math4.ml.neuralnet.twod.util;
 
-import org.apache.commons.math4.ml.neuralnet.MapUtils;
+import java.util.List;
+import org.apache.commons.math4.ml.neuralnet.MapRanking;
 import org.apache.commons.math4.ml.neuralnet.Neuron;
 import org.apache.commons.math4.ml.neuralnet.twod.NeuronSquareMesh2D;
 import org.apache.commons.math4.ml.distance.DistanceMeasure;
@@ -77,16 +78,15 @@
         }
 
         final LocationFinder finder = new LocationFinder(map);
+        final MapRanking rank = new MapRanking(map.getNetwork(), distance);
 
         // Histogram bins.
         final double[][] histo = new double[nR][nC];
 
         for (double[] sample : data) {
-            final Neuron[] sorted = MapUtils.sort(sample,
-                                                  map.getNetwork(),
-                                                  distance);
+            final List<Neuron> sorted = rank.rank(sample);
             for (int i = 0; i < smoothingBins; i++) {
-                final LocationFinder.Location loc = finder.getLocation(sorted[i]);
+                final LocationFinder.Location loc = finder.getLocation(sorted.get(i));
                 final int row = loc.getRow();
                 final int col = loc.getColumn();
                 histo[row][col] += (smoothingBins - i) * membershipNormalization;
diff --git a/src/main/java/org/apache/commons/math4/ml/neuralnet/twod/util/TopographicErrorHistogram.java b/src/main/java/org/apache/commons/math4/ml/neuralnet/twod/util/TopographicErrorHistogram.java
index e3683c1..758e672 100644
--- a/src/main/java/org/apache/commons/math4/ml/neuralnet/twod/util/TopographicErrorHistogram.java
+++ b/src/main/java/org/apache/commons/math4/ml/neuralnet/twod/util/TopographicErrorHistogram.java
@@ -17,12 +17,12 @@
 
 package org.apache.commons.math4.ml.neuralnet.twod.util;
 
-import org.apache.commons.math4.ml.neuralnet.MapUtils;
+import java.util.List;
+import org.apache.commons.math4.ml.neuralnet.MapRanking;
 import org.apache.commons.math4.ml.neuralnet.Neuron;
 import org.apache.commons.math4.ml.neuralnet.Network;
 import org.apache.commons.math4.ml.neuralnet.twod.NeuronSquareMesh2D;
 import org.apache.commons.math4.ml.distance.DistanceMeasure;
-import org.apache.commons.math4.util.Pair;
 
 /**
  * Computes the topographic error histogram.
@@ -55,8 +55,9 @@
         final int nR = map.getNumberOfRows();
         final int nC = map.getNumberOfColumns();
 
-        final Network net = map.getNetwork();
         final LocationFinder finder = new LocationFinder(map);
+        final Network net = map.getNetwork();
+        final MapRanking rank = new MapRanking(net, distance);
 
         // Hit bins.
         final int[][] hit = new int[nR][nC];
@@ -64,15 +65,15 @@
         final double[][] error = new double[nR][nC];
 
         for (double[] sample : data) {
-            final Pair<Neuron, Neuron> p = MapUtils.findBestAndSecondBest(sample, map, distance);
-            final Neuron best = p.getFirst();
+            final List<Neuron> p = rank.rank(sample, 2);
+            final Neuron best = p.get(0);
 
             final LocationFinder.Location loc = finder.getLocation(best);
             final int row = loc.getRow();
             final int col = loc.getColumn();
             hit[row][col] += 1;
 
-            if (!net.getNeighbours(best).contains(p.getSecond())) {
+            if (!net.getNeighbours(best).contains(p.get(1))) {
                 // Increment count if first and second best matching units
                 // are not neighbours.
                 error[row][col] += 1;
diff --git a/src/test/java/org/apache/commons/math4/ml/neuralnet/MapRankingTest.java b/src/test/java/org/apache/commons/math4/ml/neuralnet/MapRankingTest.java
index d835088..7beb2d5 100644
--- a/src/test/java/org/apache/commons/math4/ml/neuralnet/MapRankingTest.java
+++ b/src/test/java/org/apache/commons/math4/ml/neuralnet/MapRankingTest.java
@@ -19,7 +19,7 @@
 
 import java.util.Set;
 import java.util.HashSet;
-
+import java.util.List;
 import org.apache.commons.math4.exception.NotStrictlyPositiveException;
 import org.apache.commons.math4.ml.distance.DistanceMeasure;
 import org.apache.commons.math4.ml.distance.EuclideanDistance;
@@ -105,4 +105,21 @@
         new MapRanking(new NeuronString(3, false, initArray).getNetwork(),
                        new EuclideanDistance()).rank(new double[] { -1 }, 0);
     }
+
+    @Test
+    public void testSort() {
+        final Set<Neuron> list = new HashSet<>();
+
+        for (int i = 0; i < 4; i++) {
+            list.add(new Neuron(i, new double[] { i - 0.5 }));
+        }
+
+        final MapRanking rank = new MapRanking(list, new EuclideanDistance());
+        final List<Neuron> sorted = rank.rank(new double[] { 3.4 });
+
+        final long[] expected = new long[] { 3, 2, 1, 0 };
+        for (int i = 0; i < list.size(); i++) {
+            Assert.assertEquals(expected[i], sorted.get(i).getIdentifier());
+        }
+    }
 }
diff --git a/src/test/java/org/apache/commons/math4/ml/neuralnet/MapUtilsTest.java b/src/test/java/org/apache/commons/math4/ml/neuralnet/MapUtilsTest.java
deleted file mode 100644
index 4404aac..0000000
--- a/src/test/java/org/apache/commons/math4/ml/neuralnet/MapUtilsTest.java
+++ /dev/null
@@ -1,115 +0,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.
- */
-
-package org.apache.commons.math4.ml.neuralnet;
-
-import java.util.Set;
-import java.util.HashSet;
-
-import org.apache.commons.math4.ml.distance.DistanceMeasure;
-import org.apache.commons.math4.ml.distance.EuclideanDistance;
-import org.apache.commons.math4.ml.neuralnet.FeatureInitializer;
-import org.apache.commons.math4.ml.neuralnet.FeatureInitializerFactory;
-import org.apache.commons.math4.ml.neuralnet.MapUtils;
-import org.apache.commons.math4.ml.neuralnet.Network;
-import org.apache.commons.math4.ml.neuralnet.Neuron;
-import org.apache.commons.math4.ml.neuralnet.oned.NeuronString;
-import org.junit.Test;
-import org.junit.Assert;
-
-/**
- * Tests for {@link MapUtils} class.
- */
-public class MapUtilsTest {
-    /*
-     * Test assumes that the network is
-     *
-     *  0-----1-----2
-     */
-    @Test
-    public void testFindClosestNeuron() {
-        final FeatureInitializer init
-            = new OffsetFeatureInitializer(FeatureInitializerFactory.uniform(-0.1, 0.1));
-        final FeatureInitializer[] initArray = { init };
-
-        final Network net = new NeuronString(3, false, initArray).getNetwork();
-        final DistanceMeasure dist = new EuclideanDistance();
-
-        final Set<Neuron> allBest = new HashSet<>();
-        final Set<Neuron> best = new HashSet<>();
-        double[][] features;
-
-        // The following tests ensures that
-        // 1. the same neuron is always selected when the input feature is
-        //    in the range of the initializer,
-        // 2. different network's neuron have been selected by inputs features
-        //    that belong to different ranges.
-
-        best.clear();
-        features = new double[][] {
-            { -1 },
-            { 0.4 },
-        };
-        for (double[] f : features) {
-            best.add(MapUtils.findBest(f, net, dist));
-        }
-        Assert.assertEquals(1, best.size());
-        allBest.addAll(best);
-
-        best.clear();
-        features = new double[][] {
-            { 0.6 },
-            { 1.4 },
-        };
-        for (double[] f : features) {
-            best.add(MapUtils.findBest(f, net, dist));
-        }
-        Assert.assertEquals(1, best.size());
-        allBest.addAll(best);
-
-        best.clear();
-        features = new double[][] {
-            { 1.6 },
-            { 3 },
-        };
-        for (double[] f : features) {
-            best.add(MapUtils.findBest(f, net, dist));
-        }
-        Assert.assertEquals(1, best.size());
-        allBest.addAll(best);
-
-        Assert.assertEquals(3, allBest.size());
-    }
-
-    @Test
-    public void testSort() {
-        final Set<Neuron> list = new HashSet<>();
-
-        for (int i = 0; i < 4; i++) {
-            list.add(new Neuron(i, new double[] { i - 0.5 }));
-        }
-
-        final Neuron[] sorted = MapUtils.sort(new double[] { 3.4 },
-                                              list,
-                                              new EuclideanDistance());
-
-        final long[] expected = new long[] { 3, 2, 1, 0 };
-        for (int i = 0; i < list.size(); i++) {
-            Assert.assertEquals(expected[i], sorted[i].getIdentifier());
-        }
-    }
-}
diff --git a/src/test/java/org/apache/commons/math4/ml/neuralnet/sofm/KohonenUpdateActionTest.java b/src/test/java/org/apache/commons/math4/ml/neuralnet/sofm/KohonenUpdateActionTest.java
index 7a064cf..fbd7fc1 100644
--- a/src/test/java/org/apache/commons/math4/ml/neuralnet/sofm/KohonenUpdateActionTest.java
+++ b/src/test/java/org/apache/commons/math4/ml/neuralnet/sofm/KohonenUpdateActionTest.java
@@ -21,7 +21,7 @@
 import org.apache.commons.math4.ml.distance.EuclideanDistance;
 import org.apache.commons.math4.ml.neuralnet.FeatureInitializer;
 import org.apache.commons.math4.ml.neuralnet.FeatureInitializerFactory;
-import org.apache.commons.math4.ml.neuralnet.MapUtils;
+import org.apache.commons.math4.ml.neuralnet.MapRanking;
 import org.apache.commons.math4.ml.neuralnet.Network;
 import org.apache.commons.math4.ml.neuralnet.Neuron;
 import org.apache.commons.math4.ml.neuralnet.OffsetFeatureInitializer;
@@ -58,6 +58,7 @@
         final NeighbourhoodSizeFunction neighbourhood
             = NeighbourhoodSizeFunctionFactory.exponentialDecay(3, 1, 100);
         final UpdateAction update = new KohonenUpdateAction(dist, learning, neighbourhood);
+        final MapRanking rank = new MapRanking(net, dist);
 
         // The following test ensures that, after one "update",
         // 1. when the initial learning rate equal to 1, the best matching
@@ -71,7 +72,7 @@
         for (Neuron n : net) {
             distancesBefore[count++] = dist.compute(n.getFeatures(), features);
         }
-        final Neuron bestBefore = MapUtils.findBest(features, net, dist);
+        final Neuron bestBefore = rank.rank(features, 1).get(0);
 
         // Initial distance from the best match is larger than zero.
         Assert.assertTrue(dist.compute(bestBefore.getFeatures(), features) >= 0.2);
@@ -83,7 +84,7 @@
         for (Neuron n : net) {
             distancesAfter[count++] = dist.compute(n.getFeatures(), features);
         }
-        final Neuron bestAfter = MapUtils.findBest(features, net, dist);
+        final Neuron bestAfter = rank.rank(features, 1).get(0);
 
         Assert.assertEquals(bestBefore, bestAfter);
         // Distance is now zero.