
edu.jas.util.CartesianProductLong Maven / Gradle / Ivy
The newest version!
/*
* $Id: CartesianProductLong.java 4065 2012-07-27 15:17:38Z kredel $
*/
package edu.jas.util;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
/**
* Cartesian product for Long with iterator. Similar to CartesianProduct but
* returns only tuples of given total degree.
* @author Heinz Kredel
*/
public class CartesianProductLong implements Iterable> {
/**
* data structure.
*/
public final List comps;
public final long upperBound;
/**
* CartesianProduct constructor.
* @param comps components of the Cartesian product.
* @param ub an upper bound for the total degree of the elements.
*/
public CartesianProductLong(List comps, long ub) {
if (comps == null) {
throw new IllegalArgumentException("null components not allowed");
}
this.comps = comps;
this.upperBound = ub;
}
/**
* Get an iterator over subsets.
* @return an iterator.
*/
public Iterator> iterator() {
return new CartesianProductLongIterator(comps, upperBound);
}
}
/**
* Cartesian product iterator for Longs. Similar to CartesianProductIterator but
* returns only tuples of given total degree.
* @author Heinz Kredel
*/
class CartesianProductLongIterator implements Iterator> {
/**
* data structure.
*/
final List comps;
final List compit;
List current;
boolean empty;
public final long upperBound;
/**
* CartesianProduct iterator constructor.
* @param comps components of the Cartesian product.
* @param un an upper bound for the total degree of the elements.
*/
public CartesianProductLongIterator(List comps, long ub) {
if (comps == null) {
throw new IllegalArgumentException("null comps not allowed");
}
this.comps = comps;
this.upperBound = ub;
current = new ArrayList(comps.size());
compit = new ArrayList(comps.size());
empty = false;
for (LongIterable ci : comps) {
LongIterator it = (LongIterator) ci.iterator();
if (it.getUpperBound() < this.upperBound) {
throw new IllegalArgumentException("each iterator (" + it.getUpperBound()
+ ") must be able to reach total upper bound " + upperBound);
}
if (!it.hasNext()) {
empty = true;
current.clear();
return;
}
current.add(it.next());
compit.add(it);
}
// start with last component equal to upper bound
LongIterator it = compit.get(compit.size() - 1);
long d = -1L;
while (it.hasNext()) {
d = it.next();
if (d >= upperBound) {
break;
}
}
if (d >= 0L) {
current.set(current.size() - 1, d);
}
if (totalDegree(current) != upperBound) {
empty = true;
current.clear();
}
//System.out.println("current = " + current);
}
/**
* Test for availability of a next tuple.
* @return true if the iteration has more tuples, else false.
*/
public synchronized boolean hasNext() {
return !empty;
}
/**
* Get next tuple.
* @return next tuple.
*/
public synchronized List next() {
if (empty) {
throw new NoSuchElementException("invalid call of next()");
}
List res = new ArrayList(current);
//int waist = 0;
while (true) {
// search iterator which hasNext
int i = compit.size() - 1;
for (; i >= 0; i--) {
LongIterator iter = compit.get(i);
if (iter.hasNext()) {
break;
}
}
if (i < 0) {
empty = true;
//System.out.println("inner waist = " + waist);
return res;
}
long pd = 0L;
for (int j = 0; j < i; j++) {
pd += current.get(j);
}
if (pd >= upperBound) {
if (current.get(0) == upperBound) {
empty = true;
//System.out.println("inner waist = " + waist);
return res;
}
pd = upperBound;
}
long rd = upperBound - pd;
// update iterators
for (int j = i + 1; j < compit.size(); j++) {
LongIterator iter = (LongIterator) comps.get(j).iterator();
iter.setUpperBound(rd);
compit.set(j, iter);
}
// update current
for (int j = i; j < compit.size(); j++) {
LongIterator iter = compit.get(j);
Long el = iter.next();
current.set(j, el);
}
long td = totalDegree(current);
if (td == upperBound) {
//System.out.println("inner waist = " + waist);
return res;
}
//System.out.println("current = " + current + ", td = " + td);
if (td > upperBound) {
//waist++;
continue;
}
// adjust last component to total degree
LongIterator it = compit.get(compit.size() - 1);
long d = -1L;
while (td < upperBound && it.hasNext()) {
td++;
d = it.next();
}
//System.out.println("d = " + d);
if (d >= 0L) {
current.set(current.size() - 1, d);
}
if (td == upperBound) {
//System.out.println("inner waist = " + waist);
return res;
}
//waist++;
// continue search
}
//return res;
}
/**
* Total degree of a tuple.
* @param e list of Longs.
* @return sum of all elements in e.
*/
public long totalDegree(List e) {
long d = 0L;
for (Long i : e) {
d += i;
}
return d;
}
/**
* Remove a tuple if allowed.
*/
public void remove() {
throw new UnsupportedOperationException("cannnot remove tuples");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy