package umontreal.iro.lecuyer.hups;
/* *
* Title:
* Description:
* Copyright: Copyright (c)
* Company:
* @author
* @version 1.0
*/
import umontreal.iro.lecuyer.util.*;
import umontreal.iro.lecuyer.rng.RandomStream;
import cern.colt.list.*;
/**
* This abstract class provides the basic structures for
* storing and manipulating a highly uniform point set
* defined by a set of cycles.
* The s-dimensional points are all the vectors of s successive
* values found in any of the cycles, from any starting point.
* Since this is defined for any positive integer s, the points
* effectively have an infinite number of dimensions.
* The number of points, n, is the sum of lengths of all the cycles.
* The cycles of the point set are simply stored as a list of arrays,
* where each array contains the successive values for a given cycle.
* By default, the values are stored in double.
*
*
* This structure is convenient for implementing recurrence-based point
* sets, where the point set in s dimensions is defined as
* the set of all vectors of s successive values of a periodic recurrence,
* from all its possible initial states.
*
*/
public abstract class CycleBasedPointSet extends PointSet {
protected int numCycles = 0; // Total number of cycles.
// dim = Integer.MAX_VALUE; // Dimension is infinite.
private double[] shift; // Random shift, initially null.
// Entry j is for dimension j.
protected ObjectArrayList cycles = new ObjectArrayList(); // List of cycles.
public double getCoordinate (int i, int j) {
// Find cycle that contains point i, then index in cycle.
int l = 0; // Length of next cycle.
int n = 0; // Total length of cycles added so far.
int k;
for (k = 0; n <= i; k++)
n += l = ((AbstractList) cycles.get (k)).size();
AbstractList curCycle = (AbstractList) cycles.get (k-1);
int coordinate = (i - n + l + j) % curCycle.size();
// double[] curCycleD = ((DoubleArrayList) curCycle).elements();
// return curCycleD[coordinate];
double x = ((DoubleArrayList) curCycle).get (coordinate);
return x;
}
/**
* Adds a random shift to all the points
* of the point set, using stream stream to generate the random numbers,
* for coordinates d1 to d2 - 1. This applies an addition modulo 1
* of a single random point to all the points.
*
* @param stream Stream used to generate random numbers
*
*
*/
public void addRandomShift (int d1, int d2, RandomStream stream) {
if (null == stream)
throw new IllegalArgumentException (
PrintfFormat.NEWLINE +
" Calling addRandomShift with null stream");
if (0 == d2)
d2 = Math.max (dim, 1);
if (shift == null) {
shift = new double[d2];
capacityShift = d2;
} else if (d2 > capacityShift) {
int d3 = Math.max (4, capacityShift);
while (d2 > d3)
d3 *= 2;
double[] temp = new double[d3];
capacityShift = d3;
for (int i = 0; i < d1; i++)
temp[i] = shift[i];
shift = temp;
}
dimShift = d2;
for (int i = d1; i < d2; i++)
shift[i] = stream.nextDouble ();
shiftStream = stream;
}
public void clearRandomShift() {
super.clearRandomShift();
shift = null;
}
/**
* Adds the cycle c to the list of all cycles.
* This method is used by subclass constructors to fill up the list of cycles.
*
*/
protected void addCycle (AbstractList c) {
// Adds the cycle \texttt{c} to the list of all cycles.
// Used by subclass constructors to fill up the list of cycles.
cycles.add (c);
numCycles++;
numPoints += c.size();
}
public int getDimension() {
return Integer.MAX_VALUE;
}
public PointSetIterator iterator(){
return new CycleBasedPointSetIterator();
}
public String toString() {
String s = super.toString();
return s + PrintfFormat.NEWLINE + "Number of cycles: " + numCycles;
}
public String formatPoints() {
StringBuffer sb = new StringBuffer (toString());
for (int c = 0; c < numCycles; c++) {
AbstractList curCycle = (AbstractList)cycles.get (c);
double[] cycle = ((DoubleArrayList)curCycle).elements();
sb.append (PrintfFormat.NEWLINE + "Cycle " + c + ": (");
boolean first = true;
for (int e = 0; e < curCycle.size(); e++) {
if (first)
first = false;
else
sb.append (", ");
sb.append (cycle[e]);
}
sb.append (")");
}
return sb.toString();
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
public class CycleBasedPointSetIterator extends DefaultPointSetIterator {
protected int startPointInCycle = 0; // Index where the current point
// starts in the current cycle.
protected int curCoordInCycle = 0; // Index of the current coordinate
// in the current cycle.
protected int curCycleIndex = 0; // Index of the current cycle.
protected AbstractList curCycle; // The current cycle.
protected double[] curCycleD; // The array for current cycle
public CycleBasedPointSetIterator () {
init();
}
protected void init () {
resetCurCycle(0);
}
public void resetCurCycle (int index) {
curCycleIndex = index;
curCycle = (AbstractList) cycles.get (index);
curCycleD = ((DoubleArrayList) curCycle).elements();
}
public void setCurCoordIndex (int i) {
curCoordIndex = i;
curCoordInCycle = (i + startPointInCycle) % curCycle.size();
}
public void resetCurCoordIndex() {
curCoordIndex = 0;
curCoordInCycle = startPointInCycle;
}
public boolean hasNextCoordinate() {
return true;
}
// We want to avoid generating 0 or 1
public double nextDouble() {
return nextCoordinate() + EpsilonHalf;
}
public double nextCoordinate() {
// First, verify if there are still points....
if (getCurPointIndex() >= getNumPoints ())
outOfBounds();
double x = curCycleD [curCoordInCycle];
if (shift != null) {
if (curCoordIndex >= dimShift) // Extend the shift.
addRandomShift (dimShift, curCoordIndex + 1, shiftStream);
x += shift[curCoordIndex];
if (x >= 1.0)
x -= 1.0;
if (x <= 0.0)
x = EpsilonHalf; // avoid x = 0
}
curCoordIndex++;
curCoordInCycle++;
if (curCoordInCycle >= curCycle.size())
curCoordInCycle = 0;
return x;
}
public void nextCoordinates (double p[], int dim) {
// First, verify if there are still points....
if (getCurPointIndex() >= getNumPoints ())
outOfBounds();
if (curCoordIndex + dim >= dimShift)
addRandomShift (dimShift, curCoordIndex + dim + 1, shiftStream);
int j = curCoordInCycle;
int maxj = curCycle.size();
double x;
for (int i = 0; i < dim; i++) {
x = curCycleD [curCoordInCycle++];
if (curCoordInCycle >= maxj) curCoordInCycle = 0;
if (shift != null) {
x += shift[curCoordIndex + i];
if (x >= 1.0)
x -= 1.0;
if (x <= 0.0)
x = EpsilonHalf; // avoid x = 0
}
p[i] = x;
}
curCoordIndex += dim;
}
public void setCurPointIndex (int i) {
int l = 0;
int n = 0;
int j ;
for (j=0; n <= i; j++)
n += l = ((AbstractList) cycles.get (j)).size();
resetCurCycle (j-1);
startPointInCycle = i - n + l;
curPointIndex = i;
curCoordIndex = 0;
curCoordInCycle = startPointInCycle;
}
public void resetCurPointIndex() {
resetCurCycle (0);
startPointInCycle = 0;
curPointIndex = 0;
curCoordIndex = 0;
curCoordInCycle = 0;
}
public int resetToNextPoint() {
curPointIndex++;
startPointInCycle++;
if (startPointInCycle >= curCycle.size()) {
startPointInCycle = 0;
if (curCycleIndex < (numCycles - 1))
resetCurCycle (curCycleIndex + 1);
}
curCoordIndex = 0;
curCoordInCycle = startPointInCycle;
return curPointIndex;
}
public int nextPoint (double p[], int dim) {
// First, verify if there are still points....
if (getCurPointIndex() >= getNumPoints ())
outOfBounds();
int j = startPointInCycle;
int maxj = curCycle.size() - 1;
for (int i = 0; i < dim; i++) {
p[i] = curCycleD [j];
if (j < maxj) j++; else j = 0;
}
resetToNextPoint();
return curPointIndex;
}
public String formatState() {
return super.formatState() + PrintfFormat.NEWLINE +
"Current cycle: " + curCycleIndex;
}
}
}
Ads help maintain this website.