I'm writing a neural net which uses a genetic algorithm to adjust the weights. To represent the possible range of "genes" for the GA, I'm passing in a list of bases. Unfortunately, I realized after the fact that there will be a huge possible range of weights for the net, and storing a list of all possible weights would be inefficient (it could potentially get huge).
This sounded like a job for a Range, but apparently Java doesn't have one that implements the List
interface.
I decided to write one as an exercise, and because I will actually need it unless I can find a better way to represent an arbitrary amount of bases of an arbitrary type.
Problems that I'd like help with:
- A lot (most) of the methods from the interface are currently throwing an
UnsupportedOperationException
, either because the operation doesn't make sense (add
ing to the range), or because I couldn't figure out how to properly implement it. Any suggestions on how to implement one of the methods would be appreciated. - Originally, I allowed for deletions by maintaining a
Set
of deleted elements. While iterating, the iterator would just skip over any elements in the set. This worked until I realized thatget
doesn't take it into consideration. I'd like suggestions how howget
could be written to allow for a Set of deleted elements. - Any general comments on how to improve anything.
Range.java:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
public class Range
implements List<Double>,
Iterable<Double> {
private double min;
private double step;
private double max;
public Range(double min, double step, double max) {
this.min = min;
this.step = step;
this.max = max;
}
private void unsupportedOperation(String operationName) {
throw new UnsupportedOperationException(
"Range: Unsupported Operation: " + operationName + "." );
}
//Calculates the number at the given index.
@Override
public Double get(int index) {
double val = min + step * index;
if (val > max) throw new IndexOutOfBoundsException(
"Index (" + index + ") out of range: " + this );
return val;
}
@Override
public boolean add(Double n) {
unsupportedOperation("add");
return false;
}
@Override
public void add(int index, Double n) {
unsupportedOperation("add");
}
@Override
public boolean addAll(Collection<? extends Double> ns) {
unsupportedOperation("addAll");
return false;
}
@Override
public boolean addAll(int index, Collection<? extends Double> ns) {
unsupportedOperation("addAll");
return false;
}
//This and the next method are slightly ambiguous.
@Override
public Double remove(int index) {
unsupportedOperation("remove");
return 0D;
}
@Override
public boolean remove(Object o) {
unsupportedOperation("remove");
return false;
}
@Override
public boolean removeAll(Collection<?> ns) {
unsupportedOperation("removalAll");
return false;
}
@Override
public Double set(int index, Double n) {
unsupportedOperation("set");
return 0D;
}
@Override
public int indexOf(Object o) {
Double n = min;
for (int i = 0; n <= max; n += step, i++) {
if (n.equals(o)) return i;
}
return -1;
}
@Override
public boolean retainAll(Collection<?> ns) {
unsupportedOperation("retainAll");
return false;
}
@Override
public void clear() {
unsupportedOperation("clear");
}
@Override
public boolean contains(Object o) {
for (Double n : this) {
if (n.equals(o)) return true;
}
return false;
}
@Override
public boolean containsAll(Collection<?> ns) {
for (Object n : ns) {
if (!contains(n)) return false;
}
return true;
}
@Override
public int size() {
return (int)Math.ceil( (max - min) / step );
}
@Override
public Object[] toArray() {
List<Double> arr = new ArrayList<Double>();
for (Double n : this) {
arr.add(n);
}
return arr.toArray();
}
@Override
public <T> T[] toArray(T[] arr) {
unsupportedOperation("Generic toArray");
return arr;
}
@Override
@SuppressWarnings("unused")
public boolean isEmpty() {
for (Double n : this) {
return false;
}
return true;
}
@Override
public List<Double> subList(int fromIndex, int toIndex) {
return new Range(get(fromIndex), step, get(toIndex) - 1);
}
@Override
public int lastIndexOf(Object o) {
Double n = min;
for (int i = 0; n <= max; n += step, i++) {
if (n.equals(o)) return i;
}
return -1;
}
@Override
public ListIterator<Double> listIterator() {
unsupportedOperation("listIterator");
return null;
}
@Override
public ListIterator<Double> listIterator(int index) {
unsupportedOperation("listIterator");
return null;
}
@Override
public Iterator<Double> iterator() {
class RangeIterator
implements Iterator<Double> {
double curN = min;
private double nextNonRemoved() {
return curN += step;
}
@Override
public boolean hasNext() {
return curN <= max;
}
@Override
public Double next() {
double last = curN;
if (curN > max) throw new NoSuchElementException(
"Iterator out of range.");
curN = nextNonRemoved();
return last;
}
}
return new RangeIterator();
}
@Override
public String toString() {
return "(" + min + "," + step + "," + max + ")";
}
public static void main(String[] args) {
List<Double> range = new Range(1, 2, 20);
for (double n : range) System.out.print(n + ", ");
System.out.println("\nSize: " + range.size());
//Should be "4".
System.out.println(range.lastIndexOf(9D));
List<Double> sub = range.subList(3, 8);
for (double n : sub) System.out.print(n + ", ");
System.out.println("\nSize: " + sub.size());
}
}
Range
won't have duplicates, it should really beSet
instead of aList
. I'll change that later, but it doesn't affect the question. – Carcigenicate Jul 12 '15 at 17:33Set
doesn't have duplicates, it also doesn't have indexable positions (which you appear to be using). It either contains a value, or it doesn't. – user22048 Jul 12 '15 at 18:29List
interface thenget
is the main use method. – Carcigenicate Jul 12 '15 at 18:30