userguide: add samples for various RandomVectorGenerator implementations (e.g. low discrepancy vs. uniform).
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1485347 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
f4b634bff3
commit
ab6b3c02c3
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* 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.math3.userguide;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import org.apache.commons.math3.geometry.euclidean.twod.Vector2D;
|
||||
import org.apache.commons.math3.random.HaltonSequenceGenerator;
|
||||
import org.apache.commons.math3.random.JDKRandomGenerator;
|
||||
import org.apache.commons.math3.random.MersenneTwister;
|
||||
import org.apache.commons.math3.random.RandomGenerator;
|
||||
import org.apache.commons.math3.random.RandomVectorGenerator;
|
||||
import org.apache.commons.math3.random.SobolSequenceGenerator;
|
||||
import org.apache.commons.math3.random.UncorrelatedRandomVectorGenerator;
|
||||
import org.apache.commons.math3.random.UniformRandomGenerator;
|
||||
import org.apache.commons.math3.util.FastMath;
|
||||
import org.apache.commons.math3.util.Pair;
|
||||
|
||||
/**
|
||||
* Plots 2D samples drawn from various pseudo / quasi-random generators.
|
||||
*/
|
||||
public class RandomVectorGeneratorExamples {
|
||||
|
||||
public static List<Vector2D> makeCircle(int samples, final RandomVectorGenerator generator) {
|
||||
List<Vector2D> points = new ArrayList<Vector2D>();
|
||||
for (double i = 0; i < samples; i++) {
|
||||
double[] vector = generator.nextVector();
|
||||
Vector2D point = new Vector2D(vector);
|
||||
points.add(point);
|
||||
}
|
||||
|
||||
// normalize points first
|
||||
points = normalize(points);
|
||||
|
||||
// now test if the sample is within the unit circle
|
||||
List<Vector2D> circlePoints = new ArrayList<Vector2D>();
|
||||
for (Vector2D p : points) {
|
||||
double criteria = FastMath.pow(p.getX(), 2) + FastMath.pow(p.getY(), 2);
|
||||
if (criteria < 1.0) {
|
||||
circlePoints.add(p);
|
||||
}
|
||||
}
|
||||
|
||||
return circlePoints;
|
||||
}
|
||||
|
||||
public static List<Vector2D> makeRandom(int samples, RandomVectorGenerator generator) {
|
||||
List<Vector2D> points = new ArrayList<Vector2D>();
|
||||
for (double i = 0; i < samples; i++) {
|
||||
double[] vector = generator.nextVector();
|
||||
Vector2D point = new Vector2D(vector);
|
||||
points.add(point);
|
||||
}
|
||||
|
||||
return normalize(points);
|
||||
}
|
||||
|
||||
public static List<Vector2D> normalize(final List<Vector2D> input) {
|
||||
// find the mininum and maximum x value in the dataset
|
||||
double minX = Double.MAX_VALUE;
|
||||
double maxX = Double.MIN_VALUE;
|
||||
for (Vector2D p : input) {
|
||||
minX = FastMath.min(minX, p.getX());
|
||||
maxX = FastMath.max(maxX, p.getX());
|
||||
}
|
||||
|
||||
double minY, maxY;
|
||||
|
||||
// use the minimum to detect if we either have input values in the range [0, 1] or [-sqrt(3), sqrt(3)]
|
||||
if (FastMath.abs(minX) < 0.1) {
|
||||
minX = minY = 0.0;
|
||||
maxX = maxY = 1.0;
|
||||
} else {
|
||||
minX = minY = -FastMath.sqrt(3);
|
||||
maxX = maxY = FastMath.sqrt(3);
|
||||
}
|
||||
|
||||
double rangeX = maxX - minX;
|
||||
double rangeY = maxY - minY;
|
||||
List<Vector2D> points = new ArrayList<Vector2D>();
|
||||
for (Vector2D p : input) {
|
||||
double[] arr = p.toArray();
|
||||
// normalize to the range [-1, 1]
|
||||
arr[0] = (arr[0] - minX) / rangeX * 2 - 1;
|
||||
arr[1] = (arr[1] - minY) / rangeY * 2 - 1;
|
||||
points.add(new Vector2D(arr));
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
public static class Display extends JFrame {
|
||||
|
||||
private static final long serialVersionUID = -8846964550416589808L;
|
||||
|
||||
public Display() {
|
||||
setTitle("Pseudo/Quasi-random examples");
|
||||
setSize(800, 800);
|
||||
setLocationRelativeTo(null);
|
||||
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
|
||||
setLayout(new GridBagLayout());
|
||||
|
||||
int[] datasets = new int[] { 256, 1000, 2500, 1000 };
|
||||
List<Pair<String, RandomVectorGenerator>> generators = new ArrayList<Pair<String, RandomVectorGenerator>>();
|
||||
|
||||
generators.add(new Pair<String, RandomVectorGenerator>("Uncorrelated\nUniform(JDK)",
|
||||
new UncorrelatedRandomVectorGenerator(2, new UniformRandomGenerator(new JDKRandomGenerator()))));
|
||||
generators.add(new Pair<String, RandomVectorGenerator>("Independent\nRandom(MT)", new RandomVectorGenerator() {
|
||||
|
||||
RandomGenerator[] rngs = new RandomGenerator[] {
|
||||
new MersenneTwister(0),
|
||||
new MersenneTwister(1)
|
||||
};
|
||||
|
||||
public double[] nextVector() {
|
||||
final double[] vector = new double[2];
|
||||
vector[0] = rngs[0].nextDouble();
|
||||
vector[1] = rngs[1].nextDouble();
|
||||
return vector;
|
||||
}
|
||||
|
||||
}));
|
||||
generators.add(new Pair<String, RandomVectorGenerator>("HaltonSequence", new HaltonSequenceGenerator(2)));
|
||||
generators.add(new Pair<String, RandomVectorGenerator>("SobolSequence", new SobolSequenceGenerator(2)));
|
||||
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.fill = GridBagConstraints.VERTICAL;
|
||||
c.gridx = 1;
|
||||
c.gridy = 0;
|
||||
c.insets = new Insets(2, 2, 2, 2);
|
||||
|
||||
for (Pair<String, RandomVectorGenerator> pair : generators) {
|
||||
JTextArea text = new JTextArea(pair.getFirst());
|
||||
text.setEditable(false);
|
||||
text.setOpaque(false);
|
||||
add(text, c);
|
||||
c.gridx++;
|
||||
}
|
||||
int saveY = ++c.gridy;
|
||||
|
||||
c.gridx = 0;
|
||||
for (int type = 0; type < 4; type++) {
|
||||
JLabel text = new JLabel("n=" + String.valueOf(datasets[type]));
|
||||
text.setOpaque(false);
|
||||
add(text, c);
|
||||
c.gridy++;
|
||||
}
|
||||
|
||||
c.gridy = saveY;
|
||||
for (int type = 0; type < 4; type++) {
|
||||
c.gridx = 1;
|
||||
|
||||
for (Pair<String, RandomVectorGenerator> pair : generators) {
|
||||
List<Vector2D> points = null;
|
||||
int samples = datasets[type];
|
||||
switch (type) {
|
||||
case 0:
|
||||
points = makeRandom(samples, pair.getValue());
|
||||
break;
|
||||
case 1:
|
||||
points = makeRandom(samples, pair.getValue());
|
||||
break;
|
||||
case 2:
|
||||
points = makeRandom(samples, pair.getValue());
|
||||
break;
|
||||
case 3:
|
||||
points = makeCircle(samples, pair.getValue());
|
||||
break;
|
||||
}
|
||||
add(new Plot(points), c);
|
||||
c.gridx++;
|
||||
}
|
||||
|
||||
c.gridy++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Plot extends JComponent {
|
||||
|
||||
private static final long serialVersionUID = 4546352048750419587L;
|
||||
|
||||
private static double PAD = 10;
|
||||
|
||||
private List<Vector2D> points;
|
||||
|
||||
public Plot(final List<Vector2D> points) {
|
||||
this.points = points;
|
||||
}
|
||||
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
Graphics2D g2 = (Graphics2D)g;
|
||||
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
|
||||
RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
|
||||
int w = getWidth();
|
||||
int h = getHeight();
|
||||
|
||||
g2.clearRect(0, 0, w, h);
|
||||
|
||||
g2.setPaint(Color.black);
|
||||
g2.drawRect(0, 0, w - 1, h - 1);
|
||||
|
||||
for (Vector2D point : points) {
|
||||
Vector2D p = transform(point, w, h);
|
||||
double[] arr = p.toArray();
|
||||
g2.draw(new Rectangle2D.Double(arr[0] - 1, arr[1] - 1, 2, 2));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return new Dimension(140, 140);
|
||||
}
|
||||
|
||||
private Vector2D transform(Vector2D point, int width, int height) {
|
||||
double[] arr = point.toArray();
|
||||
return new Vector2D(new double[] { PAD + (arr[0] + 1) / 2.0 * (width - 2 * PAD),
|
||||
height - PAD - (arr[1] + 1) / 2.0 * (height - 2 * PAD) });
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
Display d = new Display();
|
||||
d.setVisible(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue