ch.akuhn.matrix.Vector Maven / Gradle / Ivy
package ch.akuhn.matrix;
import java.util.Arrays;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* An ordered list of floating point numbers.
*
* @author Adrian Kuhn
*/
public abstract class Vector {
/**
* Add the given value to the value at the given index
*
* @param index
* @param value
* @return the new value
*/
public double add(int index, double value) {
return put(index, get(index) + value);
}
/**
* @return the density
*/
public double density() {
return ((double) used()) / size();
}
/**
* Iterates over all entries. Some vectors omit zero-valued entries.
*
* @return value and index of each entry.
*/
public Iterable entries() {
return new Iterable() {
@Override
public Iterator iterator() {
return new Iterator() {
private int index = 0;
@Override
public boolean hasNext() {
return index < size();
}
@Override
public Entry next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return new Entry(index, get(index++));
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
};
}
/**
* Get the value at the given index
*
* @param index
* @return the value
*/
public abstract double get(int index);
/**
* Compute the L2 norm
*
* @return the L2 norm
*/
public double norm() {
double sum = 0.0;
for (Entry each : entries()) {
sum += (each.value * each.value);
}
return Math.sqrt(sum);
}
/**
* Set the value at an index
*
* @param index
* @param value
* @return the new value
*/
public abstract double put(int index, double value);
/**
* @return the length of the vector
*/
public abstract int size();
/**
* @return the sum of values
*/
public double sum() {
double sum = 0.0;
for (Entry each : entries()) {
sum += each.value;
}
return sum;
}
/**
* Returns number of non-zero-valued entries.
*
* @return a positive integer.
*/
public int used() {
int count = 0;
for (Entry each : entries()) {
if (each.value != 0.0) {
count++;
}
}
return count;
}
/**
* An entry in a sparse vector
*/
public final class Entry {
/**
* The index
*/
public final int index;
/**
* The value
*/
public final double value;
/**
* Construct
*
* @param index
* @param value
*/
public Entry(int index, double value) {
this.index = index;
this.value = value;
}
}
/**
* Construct a Vector from an array of values
*
* @param values
* @return the vector
*/
public static Vector from(double... values) {
return new DenseVector(values.clone());
}
/**
* Copy a range from an array into a vector.
*
* @param values
* @param start
* @param length
* @return the vector
*/
public static Vector copy(double[] values, int start, int length) {
return new DenseVector(Arrays.copyOfRange(values, start, start + length));
}
/**
* Wrap an array in a vector
*
* @param values
* @return the vector
*/
public static Vector wrap(double... values) {
return new DenseVector(values);
}
/**
* Create an empty dense vector
*
* @param size
* @return the vector
*/
public static Vector dense(int size) {
return new DenseVector(size);
}
/**
* Create an empty sparse vector
*
* @param size
* @return the vector
*/
public static Vector sparse(int size) {
return new KuhnSparseVector(size);
}
/**
* Returns the dot/scalar product.
*
* @param x
* @return the dot product
*/
public double dot(Vector x) {
double product = 0.0;
for (Entry each : entries()) {
product += (each.value * x.get(each.index));
}
return product;
}
/**
* y = y + a*this.
*
* @param a
* @param y
*/
public void scaleAndAddTo(double a, Vector y) {
for (Entry each : entries()) {
y.add(each.index, a * each.value);
}
}
/**
* I/O
*
* @param array
* @param start
*/
public void storeOn(double[] array, int start) {
if (start + size() > array.length) {
throw new IllegalArgumentException("start + size() > array.length");
}
Arrays.fill(array, start, start + size(), 0.0);
for (Entry each : entries()) {
array[start + each.index] = each.value;
}
}
@Override
public String toString() {
StringBuilder out = new StringBuilder();
out.append("(");
for (Entry each : entries()) {
out.append(each.value + ", ");
}
out.append(")");
return out.toString();
}
/**
* Multiply by a constant, creating a new vector
*
* @param scalar
* @return the vector
*/
public abstract Vector times(double scalar);
/**
* Multiply by a constant in-place
*
* @param scalar
* @return this
*/
public abstract Vector timesEquals(double scalar);
/**
* Test for equality
*
* @param v
* @param epsilon
* @return true if the same; false otherwise
*/
public abstract boolean equals(Vector v, double epsilon);
/**
* @return an array
*/
public double[] unwrap() {
throw new IllegalStateException("cannot unwrap instance of " + getClass());
}
/**
* mean-center the vector
*/
public void applyCentering() {
double[] values = unwrap();
double mean = Util.sum(values) / values.length;
for (int i = 0; i < values.length; i++) {
values[i] -= mean;
}
}
/**
* @return the mean of the values
*/
public double mean() {
double[] values = unwrap();
return Util.sum(values) / values.length;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy