mirror of
https://github.com/meteoinfo/MeteoInfo.git
synced 2025-12-08 20:36:05 +00:00
to version 3.5.11
This commit is contained in:
parent
1013d3cbc2
commit
ef5cae235b
18
.idea/encodings.xml
generated
18
.idea/encodings.xml
generated
@ -3,8 +3,18 @@
|
||||
<component name="Encoding" defaultCharsetForPropertiesFiles="UTF-8">
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-chart/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-chart/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-common/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-common/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-console/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-console/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-data/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-data/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-dataframe/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-dataframe/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-geo/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-geo/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-geometry/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-geometry/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-image/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-image/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-lab/src/main/java" charset="UTF-8" />
|
||||
@ -13,6 +23,14 @@
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-map/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-math/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-math/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-ndarray/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-ndarray/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-projection/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-projection/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-table/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-table/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-ui/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/meteoinfo-ui/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
|
||||
@ -19,11 +19,6 @@
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<!--<repository>
|
||||
<id>central</id>
|
||||
<name>Maven Central</name>
|
||||
<url>https://repo1.maven.org/maven2/</url>
|
||||
</repository>-->
|
||||
<repository>
|
||||
<id>jogamp-remote</id>
|
||||
<name>jogamp mirror</name>
|
||||
@ -34,21 +29,6 @@
|
||||
<name>freehep</name>
|
||||
<url>https://java.freehep.org/maven2/</url>
|
||||
</repository>
|
||||
<!--<repository>
|
||||
<id>boundless</id>
|
||||
<name>boundlessgeo</name>
|
||||
<url>https://repo.boundlessgeo.com/main/</url>
|
||||
</repository>-->
|
||||
<!--<repository>
|
||||
<id>jzy3d-snapshots</id>
|
||||
<name>Jzy3d Snapshots</name>
|
||||
<url>https://maven.jzy3d.org/snapshots/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>jzy3d-releases</id>
|
||||
<name>Jzy3d Releases</name>
|
||||
<url>https://maven.jzy3d.org/releases/</url>
|
||||
</repository>-->
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
@ -92,93 +72,6 @@
|
||||
<artifactId>jogl-all-main</artifactId>
|
||||
<version>${jogl.version}</version>
|
||||
</dependency>
|
||||
<!--<dependency>
|
||||
<groupId>org.jogamp.jogl</groupId>
|
||||
<artifactId>jogl-all</artifactId>
|
||||
<version>${jogl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jogamp.jogl</groupId>
|
||||
<artifactId>jogl-all-natives-linux-aarch64</artifactId>
|
||||
<version>${jogl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jogamp.jogl</groupId>
|
||||
<artifactId>jogl-all-natives-linux-amd64</artifactId>
|
||||
<version>${jogl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jogamp.jogl</groupId>
|
||||
<artifactId>jogl-all-natives-linux-armv6hf</artifactId>
|
||||
<version>${jogl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jogamp.jogl</groupId>
|
||||
<artifactId>jogl-all-natives-linux-i586</artifactId>
|
||||
<version>${jogl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jogamp.jogl</groupId>
|
||||
<artifactId>jogl-all-natives-macosx-universal</artifactId>
|
||||
<version>${jogl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jogamp.jogl</groupId>
|
||||
<artifactId>jogl-all-natives-windows-amd64</artifactId>
|
||||
<version>${jogl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jogamp.jogl</groupId>
|
||||
<artifactId>jogl-all-natives-windows-i586 </artifactId>
|
||||
<version>${jogl.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!– GLUEGEN –>
|
||||
<dependency>
|
||||
<groupId>org.jogamp.gluegen</groupId>
|
||||
<artifactId>gluegen-rt</artifactId>
|
||||
<version>${jogl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jogamp.gluegen</groupId>
|
||||
<artifactId>gluegen-rt-natives-macosx-universal</artifactId>
|
||||
<version>${jogl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jogamp.gluegen</groupId>
|
||||
<artifactId>gluegen-rt-natives-linux-aarch64</artifactId>
|
||||
<version>${jogl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jogamp.gluegen</groupId>
|
||||
<artifactId>gluegen-rt-natives-linux-amd64</artifactId>
|
||||
<version>${jogl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jogamp.gluegen</groupId>
|
||||
<artifactId>gluegen-rt-natives-linux-armv6hf</artifactId>
|
||||
<version>${jogl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jogamp.gluegen</groupId>
|
||||
<artifactId>gluegen-rt-natives-linux-i586</artifactId>
|
||||
<version>${jogl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jogamp.gluegen</groupId>
|
||||
<artifactId>gluegen-rt-natives-macosx-universal</artifactId>
|
||||
<version>${jogl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jogamp.gluegen</groupId>
|
||||
<artifactId>gluegen-rt-natives-windows-amd64</artifactId>
|
||||
<version>${jogl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jogamp.gluegen</groupId>
|
||||
<artifactId>gluegen-rt-natives-windows-i586</artifactId>
|
||||
<version>${jogl.version}</version>
|
||||
</dependency>-->
|
||||
<dependency>
|
||||
<groupId>org.joml</groupId>
|
||||
<artifactId>joml</artifactId>
|
||||
|
||||
@ -87,7 +87,6 @@ float calculateDepth(vec3 pos)
|
||||
vec4 ndc = MVP * vec4(pos, 1.0);
|
||||
ndc.xyz /= ndc.w;
|
||||
float depth = 0.5 * (gl_DepthRange.diff * ndc.z + (gl_DepthRange.near + gl_DepthRange.far));
|
||||
//return depth;
|
||||
return depth + 0.005;
|
||||
return depth;
|
||||
//return ndc.z * 0.5 + 0.5;
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ import java.util.zip.ZipInputStream;
|
||||
public static String getVersion(){
|
||||
String version = GlobalUtil.class.getPackage().getImplementationVersion();
|
||||
if (version == null || version.equals("")) {
|
||||
version = "3.5.11";
|
||||
version = "3.5.12";
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
@ -29,11 +29,6 @@
|
||||
<name>freehep</name>
|
||||
<url>https://java.freehep.org/maven2/</url>
|
||||
</repository>
|
||||
<!--<repository>
|
||||
<id>boundless</id>
|
||||
<name>boundlessgeo</name>
|
||||
<url>https://repo.boundlessgeo.com/main/</url>
|
||||
</repository>-->
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
@ -122,6 +117,11 @@
|
||||
<artifactId>itextpdf</artifactId>
|
||||
<version>5.5.13.3</version>
|
||||
</dependency>
|
||||
<!--<dependency>
|
||||
<groupId>com.github.librepdf</groupId>
|
||||
<artifactId>openpdf</artifactId>
|
||||
<version>1.3.30</version>
|
||||
</dependency>-->
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@ -1,34 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<MeteoInfo File="milconfig.xml" Type="configurefile">
|
||||
<Path OpenPath="D:\Working\MIScript\Jython\mis\common_math\interpolate">
|
||||
<RecentFolder Folder="D:\Working\MIScript\cuace_dust\py\plot"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\plot"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\grib"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\LaSW"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\LaSW\airship"/>
|
||||
<Path OpenPath="D:\Working\MIScript\Jython\mis\dataframe">
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\text"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\model"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\geoshow"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\slice"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math\linalg"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math\interpolate"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\satellite"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\satellite\FY"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\weather"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
|
||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\dataframe"/>
|
||||
</Path>
|
||||
<File>
|
||||
<OpenedFiles>
|
||||
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\plot\air_path_model_1.py"/>
|
||||
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\geoshow\typhoon_map_volume_2.py"/>
|
||||
<OpenedFile File="D:\Working\MIScript\Jython\mis\common_math\interpolate\interp1d_kriging.py"/>
|
||||
<OpenedFile File="D:\Working\MIScript\Jython\mis\common_math\interpolate\griddata_kriging.py"/>
|
||||
<OpenedFile File="D:\Working\MIScript\Jython\mis\dataframe\dataframe_1.py"/>
|
||||
<OpenedFile File="D:\Working\MIScript\Jython\mis\dataframe\reindex_1.py"/>
|
||||
</OpenedFiles>
|
||||
<RecentFiles>
|
||||
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\plot\air_path_model_1.py"/>
|
||||
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\geoshow\typhoon_map_volume_2.py"/>
|
||||
<RecentFile File="D:\Working\MIScript\Jython\mis\common_math\interpolate\interp1d_kriging.py"/>
|
||||
<RecentFile File="D:\Working\MIScript\Jython\mis\common_math\interpolate\griddata_kriging.py"/>
|
||||
<RecentFile File="D:\Working\MIScript\Jython\mis\dataframe\dataframe_1.py"/>
|
||||
<RecentFile File="D:\Working\MIScript\Jython\mis\dataframe\reindex_1.py"/>
|
||||
</RecentFiles>
|
||||
</File>
|
||||
<Font>
|
||||
|
||||
@ -0,0 +1,101 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
|
||||
*
|
||||
* Smile is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Smile is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
package org.meteoinfo.math.distance;
|
||||
|
||||
/**
|
||||
* Chebyshev distance (or Tchebychev distance), or L<sub>∞</sub> metric
|
||||
* is a metric defined on a vector space where the distance between two vectors
|
||||
* is the greatest of their differences along any coordinate dimension.
|
||||
*
|
||||
* @author Haifeng Li
|
||||
*/
|
||||
public class ChebyshevDistance implements Metric<double[]> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public ChebyshevDistance() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Chebyshev Distance";
|
||||
}
|
||||
|
||||
/**
|
||||
* Chebyshev distance between the two arrays of type integer.
|
||||
*/
|
||||
public static double d(int[] x, int[] y) {
|
||||
if (x.length != y.length) {
|
||||
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
|
||||
}
|
||||
|
||||
double dist = 0.0;
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
double d = Math.abs(x[i] - y[i]);
|
||||
if (dist < d)
|
||||
dist = d;
|
||||
}
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chebyshev distance between the two arrays of type float.
|
||||
* NaN will be treated as missing values and will be excluded from the
|
||||
* calculation.
|
||||
*/
|
||||
public static double d(float[] x, float[] y) {
|
||||
if (x.length != y.length)
|
||||
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
|
||||
|
||||
double dist = 0.0;
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
if (!Float.isNaN(x[i]) && !Float.isNaN(y[i])) {
|
||||
double d = Math.abs(x[i] - y[i]);
|
||||
if (dist < d)
|
||||
dist = d;
|
||||
}
|
||||
}
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chebyshev distance between the two arrays of type double.
|
||||
* NaN will be treated as missing values and will be excluded from the
|
||||
* calculation.
|
||||
*/
|
||||
@Override
|
||||
public double d(double[] x, double[] y) {
|
||||
if (x.length != y.length)
|
||||
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
|
||||
|
||||
double dist = 0.0;
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
if (!Double.isNaN(x[i]) && !Double.isNaN(y[i])) {
|
||||
double d = Math.abs(x[i] - y[i]);
|
||||
if (dist < d)
|
||||
dist = d;
|
||||
}
|
||||
}
|
||||
|
||||
return dist;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
|
||||
*
|
||||
* Smile is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Smile is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
package org.meteoinfo.math.distance;
|
||||
|
||||
import org.meteoinfo.math.MathEx;
|
||||
|
||||
import java.util.function.ToDoubleBiFunction;
|
||||
|
||||
/**
|
||||
* Correlation distance is defined as 1 - correlation coefficient.
|
||||
*
|
||||
* @author Haifeng Li
|
||||
*/
|
||||
public class CorrelationDistance implements Distance<double[]> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** A character string indicating what type of correlation is employed. */
|
||||
private String method;
|
||||
/** Correlation lambda. */
|
||||
private ToDoubleBiFunction<double[], double[]> cor;
|
||||
|
||||
/**
|
||||
* Constructor of Pearson correlation distance.
|
||||
*/
|
||||
public CorrelationDistance() {
|
||||
this("pearson");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public CorrelationDistance(String method) {
|
||||
this.method = method.trim().toLowerCase();
|
||||
switch (this.method) {
|
||||
case "pearson":
|
||||
cor = (x, y) -> 1 - MathEx.cor(x, y);
|
||||
break;
|
||||
case "spearman":
|
||||
cor = (x, y) -> 1 - MathEx.spearman(x, y);
|
||||
break;
|
||||
case "kendall":
|
||||
cor = (x, y) -> 1 - MathEx.kendall(x, y);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid correlation: " + method);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("Correlation Distance(%s)", method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pearson correlation distance between the two arrays of type double.
|
||||
*/
|
||||
@Override
|
||||
public double d(double[] x, double[] y) {
|
||||
return cor.applyAsDouble(x, y);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
|
||||
*
|
||||
* Smile is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Smile is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
package org.meteoinfo.math.distance;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.function.ToDoubleBiFunction;
|
||||
import java.util.stream.IntStream;
|
||||
import org.meteoinfo.math.blas.UPLO;
|
||||
import org.meteoinfo.math.matrix.Matrix;
|
||||
|
||||
/**
|
||||
* An interface to calculate a distance measure between two objects. A distance
|
||||
* function maps pairs of points into the nonnegative reals and has to satisfy
|
||||
* <ul>
|
||||
* <li> non-negativity: <code>d(x, y) ≥ 0</code>
|
||||
* <li> isolation: <code>d(x, y) = 0</code> if and only if <code>x = y</code>
|
||||
* <li> symmetry: <code>d(x, y) = d(x, y)</code>
|
||||
* </ul>
|
||||
* Note that a distance function is not required to satisfy triangular inequality
|
||||
* <code>|x - y| + |y - z| ≥ |x - z|</code>, which is necessary for a metric.
|
||||
*
|
||||
* @author Haifeng Li
|
||||
*/
|
||||
public interface Distance<T> extends ToDoubleBiFunction<T,T>, Serializable {
|
||||
/**
|
||||
* Returns the distance measure between two objects.
|
||||
*/
|
||||
double d(T x, T y);
|
||||
|
||||
/**
|
||||
* Returns the distance measure between two objects.
|
||||
* This is simply for Scala convenience.
|
||||
*/
|
||||
default double apply(T x, T y) {
|
||||
return d(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
default double applyAsDouble(T x, T y) {
|
||||
return d(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pairwise distance matrix.
|
||||
*
|
||||
* @param x samples.
|
||||
* @return the pairwise distance matrix.
|
||||
*/
|
||||
default Matrix D(T[] x) {
|
||||
int n = x.length;
|
||||
int N = n * (n - 1) / 2;
|
||||
Matrix D = new Matrix(n, n);
|
||||
IntStream.range(0, N).parallel().forEach(k -> {
|
||||
int j = n - 2 - (int) Math.floor(Math.sqrt(-8*k + 4*n*(n-1)-7)/2.0 - 0.5);
|
||||
int i = k + j + 1 - n*(n-1)/2 + (n-j)*((n-j)-1)/2;
|
||||
D.set(i, j, d(x[i], x[j]));
|
||||
});
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (int j = i + 1; j < n; j++) {
|
||||
D.set(i, j, D.get(j, i));
|
||||
}
|
||||
}
|
||||
|
||||
D.uplo(UPLO.LOWER);
|
||||
return D;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pairwise distance matrix.
|
||||
*
|
||||
* @param x samples.
|
||||
* @param y samples.
|
||||
* @return the pairwise distance matrix.
|
||||
*/
|
||||
default Matrix D(T[] x, T[] y) {
|
||||
int m = x.length;
|
||||
int n = y.length;
|
||||
Matrix D = new Matrix(m, n);
|
||||
IntStream.range(0, m).parallel().forEach(i -> {
|
||||
T xi = x[i];
|
||||
for (int j = 0; j < n; j++) {
|
||||
D.set(i, j, d(xi, y[j]));
|
||||
}
|
||||
});
|
||||
|
||||
return D;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,185 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
|
||||
*
|
||||
* Smile is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Smile is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
package org.meteoinfo.math.distance;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Euclidean distance. For float or double arrays, missing values (i.e. NaN)
|
||||
* are also handled.
|
||||
*
|
||||
* @see SparseEuclideanDistance
|
||||
*
|
||||
* @author Haifeng Li
|
||||
*/
|
||||
public class EuclideanDistance implements Metric<double[]> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* The weights used in weighted distance.
|
||||
*/
|
||||
private double[] weight = null;
|
||||
|
||||
/**
|
||||
* Constructor. Standard (unweighted) Euclidean distance.
|
||||
*/
|
||||
public EuclideanDistance() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor with a given weight vector.
|
||||
*
|
||||
* @param weight the weight vector.
|
||||
*/
|
||||
public EuclideanDistance(double[] weight) {
|
||||
for (int i = 0; i < weight.length; i++) {
|
||||
if (weight[i] < 0) {
|
||||
throw new IllegalArgumentException(String.format("Weight has to be nonnegative: %f", weight[i]));
|
||||
}
|
||||
}
|
||||
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (weight != null) {
|
||||
return String.format("Weighted Euclidean Distance(%s)", Arrays.toString(weight));
|
||||
} else {
|
||||
return "Euclidean Distance";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Euclidean distance between the two arrays of type integer. No missing
|
||||
* value handling in this method.
|
||||
*/
|
||||
public double d(int[] x, int[] y) {
|
||||
if (x.length != y.length)
|
||||
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
|
||||
|
||||
double dist = 0.0;
|
||||
|
||||
if (weight == null) {
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
double d = x[i] - y[i];
|
||||
dist += d * d;
|
||||
}
|
||||
} else {
|
||||
if (x.length != weight.length)
|
||||
throw new IllegalArgumentException(String.format("Input vectors and weight vector have different length: %d, %d", x.length, weight.length));
|
||||
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
double d = x[i] - y[i];
|
||||
dist += weight[i] * d * d;
|
||||
}
|
||||
}
|
||||
|
||||
return Math.sqrt(dist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Euclidean distance between the two arrays of type float.
|
||||
* NaN will be treated as missing values and will be excluded from the
|
||||
* calculation. Let m be the number nonmissing values, and n be the
|
||||
* number of all values. The returned distance is sqrt(n * d / m),
|
||||
* where d is the square of distance between nonmissing values.
|
||||
*/
|
||||
public double d(float[] x, float[] y) {
|
||||
if (x.length != y.length)
|
||||
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
|
||||
|
||||
int n = x.length;
|
||||
int m = 0;
|
||||
double dist = 0.0;
|
||||
|
||||
if (weight == null) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (!Float.isNaN(x[i]) && !Float.isNaN(y[i])) {
|
||||
m++;
|
||||
double d = x[i] - y[i];
|
||||
dist += d * d;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (x.length != weight.length)
|
||||
throw new IllegalArgumentException(String.format("Input vectors and weight vector have different length: %d, %d", x.length, weight.length));
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (!Float.isNaN(x[i]) && !Float.isNaN(y[i])) {
|
||||
m++;
|
||||
double d = x[i] - y[i];
|
||||
dist += weight[i] * d * d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m == 0)
|
||||
dist = Double.NaN;
|
||||
else
|
||||
dist = n * dist / m;
|
||||
|
||||
|
||||
return Math.sqrt(dist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Euclidean distance between the two arrays of type double.
|
||||
* NaN will be treated as missing values and will be excluded from the
|
||||
* calculation. Let m be the number nonmissing values, and n be the
|
||||
* number of all values. The returned distance is sqrt(n * d / m),
|
||||
* where d is the square of distance between nonmissing values.
|
||||
*/
|
||||
@Override
|
||||
public double d(double[] x, double[] y) {
|
||||
if (x.length != y.length)
|
||||
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
|
||||
|
||||
int n = x.length;
|
||||
int m = 0;
|
||||
double dist = 0.0;
|
||||
|
||||
if (weight == null) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (!Double.isNaN(x[i]) && !Double.isNaN(y[i])) {
|
||||
m++;
|
||||
double d = x[i] - y[i];
|
||||
dist += d * d;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (x.length != weight.length)
|
||||
throw new IllegalArgumentException(String.format("Input vectors and weight vector have different length: %d, %d", x.length, weight.length));
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (!Double.isNaN(x[i]) && !Double.isNaN(y[i])) {
|
||||
m++;
|
||||
double d = x[i] - y[i];
|
||||
dist += weight[i] * d * d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m == 0)
|
||||
dist = Double.NaN;
|
||||
else
|
||||
dist = n * dist / m;
|
||||
|
||||
return Math.sqrt(dist);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,152 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
|
||||
*
|
||||
* Smile is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Smile is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
package org.meteoinfo.math.distance;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
/**
|
||||
* In information theory, the Hamming distance between two strings of equal
|
||||
* length is the number of positions for which the corresponding symbols are
|
||||
* different. Put another way, it measures the minimum number of substitutions
|
||||
* required to change one into the other, or the number of errors that
|
||||
* transformed one string into the other. For a fixed length n, the Hamming
|
||||
* distance is a metric on the vector space of the words of that length.
|
||||
*
|
||||
* @author Haifeng Li
|
||||
*/
|
||||
public class HammingDistance implements Distance<BitSet> {
|
||||
|
||||
/** Constructor. */
|
||||
public HammingDistance() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Hamming Distance";
|
||||
}
|
||||
|
||||
@Override
|
||||
public double d(BitSet x, BitSet y) {
|
||||
if (x.size() != y.size()) {
|
||||
throw new IllegalArgumentException(String.format("BitSets have different length: x[%d], y[%d]", x.size(), y.size()));
|
||||
}
|
||||
|
||||
int dist = 0;
|
||||
for (int i = 0; i < x.size(); i++) {
|
||||
if (x.get(i) != y.get(i))
|
||||
dist++;
|
||||
}
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Hamming distance between the two bytes.
|
||||
*/
|
||||
public static int d(byte x, byte y) {
|
||||
return d((int)x, (int)y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Hamming distance between the two shorts.
|
||||
*/
|
||||
public static int d(short x, short y) {
|
||||
return d((int)x, (int)y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Hamming distance between the two integers.
|
||||
*/
|
||||
public static int d(int x, int y) {
|
||||
int dist = 0;
|
||||
int val = x ^ y;
|
||||
|
||||
// Count the number of set bits (Knuth's algorithm)
|
||||
while (val != 0) {
|
||||
++dist;
|
||||
val &= val - 1;
|
||||
}
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Hamming distance between the two long integers.
|
||||
*/
|
||||
public static int d(long x, long y) {
|
||||
int dist = 0;
|
||||
long val = x ^ y;
|
||||
|
||||
// Count the number of set bits (Knuth's algorithm)
|
||||
while (val != 0) {
|
||||
++dist;
|
||||
val &= val - 1;
|
||||
}
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Hamming distance between the two byte arrays.
|
||||
*/
|
||||
public static int d(byte[] x, byte[] y) {
|
||||
if (x.length != y.length)
|
||||
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
|
||||
|
||||
int dist = 0;
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
if (x[i] != y[i])
|
||||
dist++;
|
||||
}
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Hamming distance between the two short arrays.
|
||||
*/
|
||||
public static int d(short[] x, short[] y) {
|
||||
if (x.length != y.length)
|
||||
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
|
||||
|
||||
int dist = 0;
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
if (x[i] != y[i])
|
||||
dist++;
|
||||
}
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Hamming distance between the two integer arrays.
|
||||
*/
|
||||
public static int d(int[] x, int[] y) {
|
||||
if (x.length != y.length)
|
||||
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
|
||||
|
||||
int dist = 0;
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
if (x[i] != y[i])
|
||||
dist++;
|
||||
}
|
||||
|
||||
return dist;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
|
||||
*
|
||||
* Smile is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Smile is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
package org.meteoinfo.math.distance;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* The Jaccard index, also known as the Jaccard similarity coefficient is a
|
||||
* statistic used for comparing the similarity and diversity of sample sets.
|
||||
* <p>
|
||||
* The Jaccard coefficient measures similarity between sample sets, and is
|
||||
* defined as the size of the intersection divided by the size of the union
|
||||
* of the sample sets.
|
||||
* <p>
|
||||
* The Jaccard distance, which measures dissimilarity between sample sets,
|
||||
* is complementary to the Jaccard coefficient and is obtained by subtracting
|
||||
* the Jaccard coefficient from 1, or, equivalently, by dividing the difference
|
||||
* of the sizes of the union and the intersection of two sets by the size of
|
||||
* the union.
|
||||
*
|
||||
* @author Haifeng Li
|
||||
*/
|
||||
public class JaccardDistance<T> implements Distance<T[]> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public JaccardDistance() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Jaccard Distance";
|
||||
}
|
||||
|
||||
@Override
|
||||
public double d(T[] a, T[] b) {
|
||||
Set<T> union = new HashSet<>();
|
||||
Set<T> intersection = new HashSet<>();
|
||||
|
||||
for (int i = 0; i < b.length; i++) {
|
||||
union.add(b[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
intersection.add(a[i]);
|
||||
}
|
||||
|
||||
intersection.retainAll(union);
|
||||
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
union.add(a[i]);
|
||||
}
|
||||
|
||||
return 1.0 - (double) intersection.size() / union.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Jaccard distance between sets.
|
||||
*/
|
||||
public static <T> double d(Set<T> a, Set<T> b) {
|
||||
Set<T> union = new HashSet<>(a);
|
||||
union.addAll(b);
|
||||
|
||||
Set<T> intersection = new HashSet<>(a);
|
||||
intersection.retainAll(b);
|
||||
|
||||
return 1.0 - (double) intersection.size() / union.size();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
|
||||
*
|
||||
* Smile is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Smile is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
package org.meteoinfo.math.distance;
|
||||
|
||||
import org.meteoinfo.math.MathEx;
|
||||
|
||||
/**
|
||||
* The Jensen-Shannon divergence is a popular method of measuring the
|
||||
* similarity between two probability distributions. It is also known
|
||||
* as information radius or total divergence to the average.
|
||||
* <p>
|
||||
* The Jensen-Shannon divergence is a symmetrized and smoothed version of the
|
||||
* Kullback-Leibler divergence . It is defined by
|
||||
* <p>
|
||||
* <pre>
|
||||
* J(P||Q) = (D(P||M) + D(Q||M)) / 2
|
||||
* </pre>
|
||||
* where M = (P+Q)/2 and D(·||·) is KL divergence.
|
||||
* Different from the Kullback-Leibler divergence, it is always a finite value.
|
||||
* <p>
|
||||
* The square root of the Jensen-Shannon divergence is a metric, which is
|
||||
* calculated by this class.
|
||||
*
|
||||
* @author Haifeng Li
|
||||
*/
|
||||
public class JensenShannonDistance implements Metric<double[]> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public JensenShannonDistance() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Jensen-Shannon Distance";
|
||||
}
|
||||
|
||||
@Override
|
||||
public double d(double[] x, double[] y) {
|
||||
if (x.length != y.length) {
|
||||
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
|
||||
}
|
||||
|
||||
return Math.sqrt(MathEx.JensenShannonDivergence(x, y));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,174 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
|
||||
*
|
||||
* Smile is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Smile is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
package org.meteoinfo.math.distance;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Manhattan distance, also known as L<sub>1</sub> distance or L<sub>1</sub>
|
||||
* norm, is the sum of the (absolute) differences of their coordinates. Use
|
||||
* getInstance() to get the standard unweighted Manhattan distance. Or create
|
||||
* an instance with a specified weight vector. For float or double arrays,
|
||||
* missing values (i.e. NaN) are also handled.
|
||||
*
|
||||
* @see SparseManhattanDistance
|
||||
*
|
||||
* @author Haifeng Li
|
||||
*/
|
||||
public class ManhattanDistance implements Metric<double[]> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* The weights used in weighted distance.
|
||||
*/
|
||||
private double[] weight = null;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public ManhattanDistance() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param weight the weight vector.
|
||||
*/
|
||||
public ManhattanDistance(double[] weight) {
|
||||
for (int i = 0; i < weight.length; i++) {
|
||||
if (weight[i] < 0) {
|
||||
throw new IllegalArgumentException(String.format("Weight has to be nonnegative: %f", weight[i]));
|
||||
}
|
||||
}
|
||||
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (weight != null) {
|
||||
return String.format("Weighted Manhattan Distance(%s)", Arrays.toString(weight));
|
||||
} else {
|
||||
return "Manhattan Distance";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manhattan distance between two arrays of type integer.
|
||||
*/
|
||||
public double d(int[] x, int[] y) {
|
||||
if (x.length != y.length)
|
||||
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
|
||||
|
||||
double dist = 0.0;
|
||||
|
||||
if (weight == null) {
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
dist += Math.abs(x[i] - y[i]);
|
||||
}
|
||||
} else {
|
||||
if (x.length != weight.length)
|
||||
throw new IllegalArgumentException(String.format("Input vectors and weight vector have different length: %d, %d", x.length, weight.length));
|
||||
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
dist += weight[i] * Math.abs(x[i] - y[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manhattan distance between two arrays of type float.
|
||||
* NaN will be treated as missing values and will be excluded from the
|
||||
* calculation. Let m be the number non-missing values, and n be the
|
||||
* number of all values. The returned distance is n * d / m,
|
||||
* where d is the distance between non-missing values.
|
||||
*/
|
||||
public double d(float[] x, float[] y) {
|
||||
if (x.length != y.length)
|
||||
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
|
||||
|
||||
int n = x.length;
|
||||
int m = 0;
|
||||
double dist = 0.0;
|
||||
|
||||
if (weight == null) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (!Float.isNaN(x[i]) && !Float.isNaN(y[i])) {
|
||||
m++;
|
||||
dist += Math.abs(x[i] - y[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (x.length != weight.length)
|
||||
throw new IllegalArgumentException(String.format("Input vectors and weight vector have different length: %d, %d", x.length, weight.length));
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (!Float.isNaN(x[i]) && !Float.isNaN(y[i])) {
|
||||
m++;
|
||||
dist += weight[i] * Math.abs(x[i] - y[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dist = n * dist / m;
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manhattan distance between two arrays of type double.
|
||||
* NaN will be treated as missing values and will be excluded from the
|
||||
* calculation. Let m be the number non-missing values, and n be the
|
||||
* number of all values. The returned distance is n * d / m,
|
||||
* where d is the distance between non-missing values.
|
||||
*/
|
||||
@Override
|
||||
public double d(double[] x, double[] y) {
|
||||
if (x.length != y.length)
|
||||
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
|
||||
|
||||
int n = x.length;
|
||||
int m = 0;
|
||||
double dist = 0.0;
|
||||
|
||||
if (weight == null) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (!Double.isNaN(x[i]) && !Double.isNaN(y[i])) {
|
||||
m++;
|
||||
dist += Math.abs(x[i] - y[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (x.length != weight.length)
|
||||
throw new IllegalArgumentException(String.format("Input vectors and weight vector have different length: %d, %d", x.length, weight.length));
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (!Double.isNaN(x[i]) && !Double.isNaN(y[i])) {
|
||||
m++;
|
||||
dist += weight[i] * Math.abs(x[i] - y[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dist = n * dist / m;
|
||||
|
||||
return dist;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
|
||||
*
|
||||
* Smile is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Smile is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
package org.meteoinfo.math.distance;
|
||||
|
||||
/**
|
||||
* A metric function defines a distance between elements of a set. Besides
|
||||
* non-negativity, isolation, and symmetry, it also has to satisfy triangular
|
||||
* inequality.
|
||||
* <ul>
|
||||
* <li> non-negativity: <code>d(x, y) ≥ 0</code>
|
||||
* <li> isolation: <code>d(x, y) = 0</code> if and only if <code>x = y</code>
|
||||
* <li> symmetry: <code>d(x, y) = d(x, y)</code>
|
||||
* <li> triangular inequality: <code>d(x, y) + d(y, z) ≥ d(x, z)</code>.
|
||||
* </ul>
|
||||
*
|
||||
* @author Haifeng Li
|
||||
*/
|
||||
public interface Metric<T> extends Distance<T> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,200 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
|
||||
*
|
||||
* Smile is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Smile is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
package org.meteoinfo.math.distance;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Minkowski distance of order p or L<sub>p</sub>-norm, is a generalization of
|
||||
* Euclidean distance that is actually L<sub>2</sub>-norm. You may also provide
|
||||
* a specified weight vector. For float or double arrays, missing values (i.e. NaN)
|
||||
* are also handled.
|
||||
*
|
||||
* @see SparseMinkowskiDistance
|
||||
*
|
||||
* @author Haifeng Li
|
||||
*/
|
||||
public class MinkowskiDistance implements Metric<double[]> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* The order of Minkowski distance.
|
||||
*/
|
||||
private int p;
|
||||
|
||||
/**
|
||||
* The weights used in weighted distance.
|
||||
*/
|
||||
private double[] weight = null;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public MinkowskiDistance(int p) {
|
||||
if (p <= 0) {
|
||||
throw new IllegalArgumentException(String.format("The order p has to be larger than 0: p = d", p));
|
||||
}
|
||||
|
||||
this.p = p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param weight the weight vector.
|
||||
*/
|
||||
public MinkowskiDistance(int p, double[] weight) {
|
||||
if (p <= 0) {
|
||||
throw new IllegalArgumentException(String.format("The order p has to be larger than 0: p = d", p));
|
||||
}
|
||||
|
||||
for (int i = 0; i < weight.length; i++) {
|
||||
if (weight[i] < 0) {
|
||||
throw new IllegalArgumentException(String.format("Weight has to be nonnegative: %f", weight[i]));
|
||||
}
|
||||
}
|
||||
|
||||
this.p = p;
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (weight != null) {
|
||||
return String.format("Weighted Minkowski Distance(p = %d, weight = %s)", p, Arrays.toString(weight));
|
||||
} else {
|
||||
return String.format("Minkowski Distance(p = %d)", p);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Minkowski distance between the two arrays of type integer.
|
||||
*/
|
||||
public double d(int[] x, int[] y) {
|
||||
if (x.length != y.length) {
|
||||
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
|
||||
}
|
||||
|
||||
double dist = 0.0;
|
||||
|
||||
if (weight == null) {
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
double d = Math.abs(x[i] - y[i]);
|
||||
dist += Math.pow(d, p);
|
||||
}
|
||||
} else {
|
||||
if (x.length != weight.length) {
|
||||
throw new IllegalArgumentException(String.format("Input vectors and weight vector have different length: %d, %d", x.length, weight.length));
|
||||
}
|
||||
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
double d = Math.abs(x[i] - y[i]);
|
||||
dist += weight[i] * Math.pow(d, p);
|
||||
}
|
||||
}
|
||||
|
||||
return Math.pow(dist, 1.0/p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Minkowski distance between the two arrays of type float.
|
||||
* NaN will be treated as missing values and will be excluded from the
|
||||
* calculation. Let m be the number non-missing values, and n be the
|
||||
* number of all values. The returned distance is pow(n * d / m, 1/p),
|
||||
* where d is the p-pow of distance between non-missing values.
|
||||
*/
|
||||
public double d(float[] x, float[] y) {
|
||||
if (x.length != y.length) {
|
||||
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
|
||||
}
|
||||
|
||||
int n = x.length;
|
||||
int m = 0;
|
||||
double dist = 0.0;
|
||||
|
||||
if (weight == null) {
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
if (!Float.isNaN(x[i]) && !Float.isNaN(y[i])) {
|
||||
m++;
|
||||
double d = Math.abs(x[i] - y[i]);
|
||||
dist += Math.pow(d, p);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (x.length != weight.length) {
|
||||
throw new IllegalArgumentException(String.format("Input vectors and weight vector have different length: %d, %d", x.length, weight.length));
|
||||
}
|
||||
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
if (!Float.isNaN(x[i]) && !Float.isNaN(y[i])) {
|
||||
m++;
|
||||
double d = Math.abs(x[i] - y[i]);
|
||||
dist += weight[i] * Math.pow(d, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dist = n * dist / m;
|
||||
|
||||
return Math.pow(dist, 1.0/p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Minkowski distance between the two arrays of type double.
|
||||
* NaN will be treated as missing values and will be excluded from the
|
||||
* calculation. Let m be the number non-missing values, and n be the
|
||||
* number of all values. The returned distance is pow(n * d / m, 1/p),
|
||||
* where d is the p-pow of distance between non-missing values.
|
||||
*/
|
||||
@Override
|
||||
public double d(double[] x, double[] y) {
|
||||
if (x.length != y.length) {
|
||||
throw new IllegalArgumentException(String.format("Arrays have different length: x[%d], y[%d]", x.length, y.length));
|
||||
}
|
||||
|
||||
int n = x.length;
|
||||
int m = 0;
|
||||
double dist = 0.0;
|
||||
|
||||
if (weight == null) {
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
if (!Double.isNaN(x[i]) && !Double.isNaN(y[i])) {
|
||||
m++;
|
||||
double d = Math.abs(x[i] - y[i]);
|
||||
dist += Math.pow(d, p);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (x.length != weight.length) {
|
||||
throw new IllegalArgumentException(String.format("Input vectors and weight vector have different length: %d, %d", x.length, weight.length));
|
||||
}
|
||||
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
if (!Double.isNaN(x[i]) && !Double.isNaN(y[i])) {
|
||||
m++;
|
||||
double d = Math.abs(x[i] - y[i]);
|
||||
dist += weight[i] * Math.pow(d, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dist = n * dist / m;
|
||||
|
||||
return Math.pow(dist, 1.0/p);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,363 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
|
||||
*
|
||||
* Smile is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Smile is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
package org.meteoinfo.math.sort;
|
||||
|
||||
/**
|
||||
* Selection is asking for the k-th smallest element out of n elements.
|
||||
* This class implements the fastest general method for selection based on
|
||||
* partitioning, exactly as done in the Quicksort algorithm.
|
||||
* <p>
|
||||
* The most common use of selection is in the statistical characterization of
|
||||
* a set of data. One often wants to know the median element (quantile p = 1/2)
|
||||
* in an array or the top and bottom quartile elements (quantile p = 1/4, 3/4).
|
||||
*
|
||||
* @author Haifeng Li
|
||||
*/
|
||||
public interface QuickSelect {
|
||||
/**
|
||||
* Given k in [0, n-1], returns an array value from arr such that k array
|
||||
* values are less than or equal to the one returned. The input array will
|
||||
* be rearranged to have this value in location arr[k], with all smaller
|
||||
* elements moved to arr[0, k-1] (in arbitrary order) and all larger elements
|
||||
* in arr[k+1, n-1] (also in arbitrary order).
|
||||
*/
|
||||
static int select(int[] arr, int k) {
|
||||
int n = arr.length;
|
||||
int l = 0;
|
||||
int ir = n - 1;
|
||||
|
||||
int a;
|
||||
int i, j, mid;
|
||||
for (;;) {
|
||||
if (ir <= l + 1) {
|
||||
if (ir == l + 1 && arr[ir] < arr[l]) {
|
||||
Sort.swap(arr, l, ir);
|
||||
}
|
||||
return arr[k];
|
||||
} else {
|
||||
mid = (l + ir) >> 1;
|
||||
Sort.swap(arr, mid, l + 1);
|
||||
if (arr[l] > arr[ir]) {
|
||||
Sort.swap(arr, l, ir);
|
||||
}
|
||||
if (arr[l + 1] > arr[ir]) {
|
||||
Sort.swap(arr, l + 1, ir);
|
||||
}
|
||||
if (arr[l] > arr[l + 1]) {
|
||||
Sort.swap(arr, l, l + 1);
|
||||
}
|
||||
i = l + 1;
|
||||
j = ir;
|
||||
a = arr[l + 1];
|
||||
for (;;) {
|
||||
do {
|
||||
i++;
|
||||
} while (arr[i] < a);
|
||||
do {
|
||||
j--;
|
||||
} while (arr[j] > a);
|
||||
if (j < i) {
|
||||
break;
|
||||
}
|
||||
Sort.swap(arr, i, j);
|
||||
}
|
||||
arr[l + 1] = arr[j];
|
||||
arr[j] = a;
|
||||
if (j >= k) {
|
||||
ir = j - 1;
|
||||
}
|
||||
if (j <= k) {
|
||||
l = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given k in [0, n-1], returns an array value from arr such that k array
|
||||
* values are less than or equal to the one returned. The input array will
|
||||
* be rearranged to have this value in location arr[k], with all smaller
|
||||
* elements moved to arr[0, k-1] (in arbitrary order) and all larger elements
|
||||
* in arr[k+1, n-1] (also in arbitrary order).
|
||||
*/
|
||||
static float select(float[] arr, int k) {
|
||||
int n = arr.length;
|
||||
int l = 0;
|
||||
int ir = n - 1;
|
||||
|
||||
float a;
|
||||
int i, j, mid;
|
||||
for (;;) {
|
||||
if (ir <= l + 1) {
|
||||
if (ir == l + 1 && arr[ir] < arr[l]) {
|
||||
Sort.swap(arr, l, ir);
|
||||
}
|
||||
return arr[k];
|
||||
} else {
|
||||
mid = (l + ir) >> 1;
|
||||
Sort.swap(arr, mid, l + 1);
|
||||
if (arr[l] > arr[ir]) {
|
||||
Sort.swap(arr, l, ir);
|
||||
}
|
||||
if (arr[l + 1] > arr[ir]) {
|
||||
Sort.swap(arr, l + 1, ir);
|
||||
}
|
||||
if (arr[l] > arr[l + 1]) {
|
||||
Sort.swap(arr, l, l + 1);
|
||||
}
|
||||
i = l + 1;
|
||||
j = ir;
|
||||
a = arr[l + 1];
|
||||
for (;;) {
|
||||
do {
|
||||
i++;
|
||||
} while (arr[i] < a);
|
||||
do {
|
||||
j--;
|
||||
} while (arr[j] > a);
|
||||
if (j < i) {
|
||||
break;
|
||||
}
|
||||
Sort.swap(arr, i, j);
|
||||
}
|
||||
arr[l + 1] = arr[j];
|
||||
arr[j] = a;
|
||||
if (j >= k) {
|
||||
ir = j - 1;
|
||||
}
|
||||
if (j <= k) {
|
||||
l = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given k in [0, n-1], returns an array value from arr such that k array
|
||||
* values are less than or equal to the one returned. The input array will
|
||||
* be rearranged to have this value in location arr[k], with all smaller
|
||||
* elements moved to arr[0, k-1] (in arbitrary order) and all larger elements
|
||||
* in arr[k+1, n-1] (also in arbitrary order).
|
||||
*/
|
||||
static double select(double[] arr, int k) {
|
||||
int n = arr.length;
|
||||
int l = 0;
|
||||
int ir = n - 1;
|
||||
|
||||
double a;
|
||||
int i, j, mid;
|
||||
for (;;) {
|
||||
if (ir <= l + 1) {
|
||||
if (ir == l + 1 && arr[ir] < arr[l]) {
|
||||
Sort.swap(arr, l, ir);
|
||||
}
|
||||
return arr[k];
|
||||
} else {
|
||||
mid = (l + ir) >> 1;
|
||||
Sort.swap(arr, mid, l + 1);
|
||||
if (arr[l] > arr[ir]) {
|
||||
Sort.swap(arr, l, ir);
|
||||
}
|
||||
if (arr[l + 1] > arr[ir]) {
|
||||
Sort.swap(arr, l + 1, ir);
|
||||
}
|
||||
if (arr[l] > arr[l + 1]) {
|
||||
Sort.swap(arr, l, l + 1);
|
||||
}
|
||||
i = l + 1;
|
||||
j = ir;
|
||||
a = arr[l + 1];
|
||||
for (;;) {
|
||||
do {
|
||||
i++;
|
||||
} while (arr[i] < a);
|
||||
do {
|
||||
j--;
|
||||
} while (arr[j] > a);
|
||||
if (j < i) {
|
||||
break;
|
||||
}
|
||||
Sort.swap(arr, i, j);
|
||||
}
|
||||
arr[l + 1] = arr[j];
|
||||
arr[j] = a;
|
||||
if (j >= k) {
|
||||
ir = j - 1;
|
||||
}
|
||||
if (j <= k) {
|
||||
l = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given k in [0, n-1], returns an array value from arr such that k array
|
||||
* values are less than or equal to the one returned. The input array will
|
||||
* be rearranged to have this value in location arr[k], with all smaller
|
||||
* elements moved to arr[0, k-1] (in arbitrary order) and all larger elements
|
||||
* in arr[k+1, n-1] (also in arbitrary order).
|
||||
*/
|
||||
static <T extends Comparable<? super T>> T select(T[] arr, int k) {
|
||||
int n = arr.length;
|
||||
int l = 0;
|
||||
int ir = n - 1;
|
||||
|
||||
T a;
|
||||
int i, j, mid;
|
||||
for (;;) {
|
||||
if (ir <= l + 1) {
|
||||
if (ir == l + 1 && arr[ir].compareTo(arr[l]) < 0) {
|
||||
Sort.swap(arr, l, ir);
|
||||
}
|
||||
return arr[k];
|
||||
} else {
|
||||
mid = (l + ir) >> 1;
|
||||
Sort.swap(arr, mid, l + 1);
|
||||
if (arr[l].compareTo(arr[ir]) > 0) {
|
||||
Sort.swap(arr, l, ir);
|
||||
}
|
||||
if (arr[l + 1].compareTo(arr[ir]) > 0) {
|
||||
Sort.swap(arr, l + 1, ir);
|
||||
}
|
||||
if (arr[l].compareTo(arr[l + 1]) > 0) {
|
||||
Sort.swap(arr, l, l + 1);
|
||||
}
|
||||
i = l + 1;
|
||||
j = ir;
|
||||
a = arr[l + 1];
|
||||
for (;;) {
|
||||
do {
|
||||
i++;
|
||||
} while (arr[i].compareTo(a) < 0);
|
||||
do {
|
||||
j--;
|
||||
} while (arr[j].compareTo(a) > 0);
|
||||
if (j < i) {
|
||||
break;
|
||||
}
|
||||
Sort.swap(arr, i, j);
|
||||
}
|
||||
arr[l + 1] = arr[j];
|
||||
arr[j] = a;
|
||||
if (j >= k) {
|
||||
ir = j - 1;
|
||||
}
|
||||
if (j <= k) {
|
||||
l = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the median of an array of type integer.
|
||||
*/
|
||||
static int median(int[] a) {
|
||||
int k = a.length / 2;
|
||||
return select(a, k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the median of an array of type float.
|
||||
*/
|
||||
static float median(float[] a) {
|
||||
int k = a.length / 2;
|
||||
return select(a, k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the median of an array of type double.
|
||||
*/
|
||||
static double median(double[] a) {
|
||||
int k = a.length / 2;
|
||||
return select(a, k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the median of an array of type double.
|
||||
*/
|
||||
static <T extends Comparable<? super T>> T median(T[] a) {
|
||||
int k = a.length / 2;
|
||||
return select(a, k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the first quantile (p = 1/4) of an array of type integer.
|
||||
*/
|
||||
static int q1(int[] a) {
|
||||
int k = a.length / 4;
|
||||
return select(a, k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the first quantile (p = 1/4) of an array of type float.
|
||||
*/
|
||||
static float q1(float[] a) {
|
||||
int k = a.length / 4;
|
||||
return select(a, k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the first quantile (p = 1/4) of an array of type double.
|
||||
*/
|
||||
static double q1(double[] a) {
|
||||
int k = a.length / 4;
|
||||
return select(a, k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the first quantile (p = 1/4) of an array of type double.
|
||||
*/
|
||||
static <T extends Comparable<? super T>> T q1(T[] a) {
|
||||
int k = a.length / 4;
|
||||
return select(a, k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the third quantile (p = 3/4) of an array of type integer.
|
||||
*/
|
||||
static int q3(int[] a) {
|
||||
int k = 3 * a.length / 4;
|
||||
return select(a, k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the third quantile (p = 3/4) of an array of type float.
|
||||
*/
|
||||
static float q3(float[] a) {
|
||||
int k = 3 * a.length / 4;
|
||||
return select(a, k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the third quantile (p = 3/4) of an array of type double.
|
||||
*/
|
||||
static double q3(double[] a) {
|
||||
int k = 3 * a.length / 4;
|
||||
return select(a, k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the third quantile (p = 3/4) of an array of type double.
|
||||
*/
|
||||
static <T extends Comparable<? super T>> T q3(T[] a) {
|
||||
int k = 3 * a.length / 4;
|
||||
return select(a, k);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2010-2020 Haifeng Li. All rights reserved.
|
||||
*
|
||||
* Smile is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Smile is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Smile. If not, see <https://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
package org.meteoinfo.math.util;
|
||||
|
||||
/** A pair of integer. */
|
||||
public class IntPair {
|
||||
public final int i;
|
||||
public final int j;
|
||||
|
||||
/** Constructor. */
|
||||
public IntPair(int i, int j) {
|
||||
this.i = i;
|
||||
this.j = j;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return i * 31 + j;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("(%d, %d)", i, j);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o != null && o instanceof IntPair) {
|
||||
IntPair p = (IntPair) o;
|
||||
return i == p.i && j == p.j;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -23,20 +23,23 @@ public class MatrixTest {
|
||||
|
||||
@Test
|
||||
public void testMv() {
|
||||
matrix = new Matrix(A);
|
||||
double[] d = matrix.mv(b);
|
||||
assertEquals(0.65, d[0], 1E-7);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTv() {
|
||||
matrix = new Matrix(A);
|
||||
double[] d = matrix.tv(b);
|
||||
assertEquals(d[0], 0.65, 1E-7);
|
||||
assertEquals(0.65, d[0], 1E-7);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSVDSolve() {
|
||||
matrix = new Matrix(A);
|
||||
Matrix.SVD svd = matrix.svd(true, true);
|
||||
double[] d = svd.solve(b);
|
||||
assertEquals(d[0], 0.3642384179155737, 1E-7);
|
||||
assertEquals(0.3642384179155737, d[0], 1E-7);
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<commons-math.version>4.0-beta1</commons-math.version>
|
||||
<commons-numbers.version>1.1</commons-numbers.version>
|
||||
<commons-rng.version>1.5</commons-rng.version>
|
||||
</properties>
|
||||
@ -34,15 +35,10 @@
|
||||
<artifactId>meteoinfo-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!--<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-math3</artifactId>
|
||||
<version>3.6.1</version>
|
||||
</dependency>-->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-math4-legacy</artifactId>
|
||||
<version>4.0-beta1</version>
|
||||
<version>${commons-math.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user