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.