All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.commons.math.linear.SparseFieldVector Maven / Gradle / Ivy

/*
 * 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.math.linear;

import java.io.Serializable;
import java.lang.reflect.Array;

import org.apache.commons.math.Field;
import org.apache.commons.math.FieldElement;
import org.apache.commons.math.MathRuntimeException;
import org.apache.commons.math.exception.util.LocalizedFormats;
import org.apache.commons.math.util.OpenIntToFieldHashMap;

/**
 * This class implements the {@link FieldVector} interface with a {@link OpenIntToFieldHashMap} backing store.
 * @param  the type of the field elements
 * @version $Revision: 983921 $ $Date: 2010-08-10 12:46:06 +0200 (mar. 10 août 2010) $
 * @since 2.0
 */
public class SparseFieldVector> implements FieldVector, Serializable {

    /**
     *  Serial version id
     */
    private static final long serialVersionUID = 7841233292190413362L;
    /** Field to which the elements belong. */
    private final Field field;
    /** Entries of the vector. */
    private final OpenIntToFieldHashMap entries;
    /** Dimension of the vector. */
    private final int virtualSize;

    /**
     * Build a 0-length vector.
     * 

Zero-length vectors may be used to initialize construction of vectors * by data gathering. We start with zero-length and use either the {@link * #SparseFieldVector(SparseFieldVector, int)} constructor * or one of the append method ({@link #append(FieldElement)}, * {@link #append(FieldElement[])}, {@link #append(FieldVector)}, * {@link #append(SparseFieldVector)}) to gather data into this vector.

* @param field field to which the elements belong */ public SparseFieldVector(Field field) { this(field, 0); } /** * Construct a (dimension)-length vector of zeros. * @param field field to which the elements belong * @param dimension Size of the vector */ public SparseFieldVector(Field field, int dimension) { this.field = field; virtualSize = dimension; entries = new OpenIntToFieldHashMap(field); } /** * Build a resized vector, for use with append. * @param v The original vector * @param resize The amount to resize it */ protected SparseFieldVector(SparseFieldVector v, int resize) { field = v.field; virtualSize = v.getDimension() + resize; entries = new OpenIntToFieldHashMap(v.entries); } /** * Build a vector with known the sparseness (for advanced use only). * @param field field to which the elements belong * @param dimension The size of the vector * @param expectedSize The expected number of non-zero entries */ public SparseFieldVector(Field field, int dimension, int expectedSize) { this.field = field; virtualSize = dimension; entries = new OpenIntToFieldHashMap(field,expectedSize); } /** * Create from a Field array. * Only non-zero entries will be stored * @param field field to which the elements belong * @param values The set of values to create from */ public SparseFieldVector(Field field, T[] values) { this.field = field; virtualSize = values.length; entries = new OpenIntToFieldHashMap(field); for (int key = 0; key < values.length; key++) { T value = values[key]; entries.put(key, value); } } /** * Copy constructor. * @param v The instance to copy from */ public SparseFieldVector(SparseFieldVector v) { field = v.field; virtualSize = v.getDimension(); entries = new OpenIntToFieldHashMap(v.getEntries()); } /** * Get the entries of this instance. * @return entries of this instance */ private OpenIntToFieldHashMap getEntries() { return entries; } /** * Optimized method to add sparse vectors. * @param v vector to add * @return The sum of this and v * @throws IllegalArgumentException If the dimensions don't match */ public FieldVector add(SparseFieldVector v) throws IllegalArgumentException { checkVectorDimensions(v.getDimension()); SparseFieldVector res = (SparseFieldVector)copy(); OpenIntToFieldHashMap.Iterator iter = v.getEntries().iterator(); while (iter.hasNext()) { iter.advance(); int key = iter.key(); T value = iter.value(); if (entries.containsKey(key)) { res.setEntry(key, entries.get(key).add(value)); } else { res.setEntry(key, value); } } return res; } /** {@inheritDoc} */ public FieldVector add(T[] v) throws IllegalArgumentException { checkVectorDimensions(v.length); SparseFieldVector res = new SparseFieldVector(field,getDimension()); for (int i = 0; i < v.length; i++) { res.setEntry(i, v[i].add(getEntry(i))); } return res; } /** * Construct a vector by appending a vector to this vector. * @param v vector to append to this one. * @return a new vector */ public FieldVector append(SparseFieldVector v) { SparseFieldVector res = new SparseFieldVector(this, v.getDimension()); OpenIntToFieldHashMap.Iterator iter = v.entries.iterator(); while (iter.hasNext()) { iter.advance(); res.setEntry(iter.key() + virtualSize, iter.value()); } return res; } /** {@inheritDoc} */ public FieldVector append(FieldVector v) { if (v instanceof SparseFieldVector) { return append((SparseFieldVector) v); } else { return append(v.toArray()); } } /** {@inheritDoc} */ public FieldVector append(T d) { FieldVector res = new SparseFieldVector(this, 1); res.setEntry(virtualSize, d); return res; } /** {@inheritDoc} */ public FieldVector append(T[] a) { FieldVector res = new SparseFieldVector(this, a.length); for (int i = 0; i < a.length; i++) { res.setEntry(i + virtualSize, a[i]); } return res; } /** {@inheritDoc} */ public FieldVector copy() { return new SparseFieldVector(this); } /** {@inheritDoc} */ public T dotProduct(FieldVector v) throws IllegalArgumentException { checkVectorDimensions(v.getDimension()); T res = field.getZero(); OpenIntToFieldHashMap.Iterator iter = entries.iterator(); while (iter.hasNext()) { iter.advance(); res = res.add(v.getEntry(iter.key()).multiply(iter.value())); } return res; } /** {@inheritDoc} */ public T dotProduct(T[] v) throws IllegalArgumentException { checkVectorDimensions(v.length); T res = field.getZero(); OpenIntToFieldHashMap.Iterator iter = entries.iterator(); while (iter.hasNext()) { int idx = iter.key(); T value = field.getZero(); if (idx < v.length) { value = v[idx]; } res = res.add(value.multiply(iter.value())); } return res; } /** {@inheritDoc} */ public FieldVector ebeDivide(FieldVector v) throws IllegalArgumentException { checkVectorDimensions(v.getDimension()); SparseFieldVector res = new SparseFieldVector(this); OpenIntToFieldHashMap.Iterator iter = res.entries.iterator(); while (iter.hasNext()) { iter.advance(); res.setEntry(iter.key(), iter.value().divide(v.getEntry(iter.key()))); } return res; } /** {@inheritDoc} */ public FieldVector ebeDivide(T[] v) throws IllegalArgumentException { checkVectorDimensions(v.length); SparseFieldVector res = new SparseFieldVector(this); OpenIntToFieldHashMap.Iterator iter = res.entries.iterator(); while (iter.hasNext()) { iter.advance(); res.setEntry(iter.key(), iter.value().divide(v[iter.key()])); } return res; } /** {@inheritDoc} */ public FieldVector ebeMultiply(FieldVector v)throws IllegalArgumentException { checkVectorDimensions(v.getDimension()); SparseFieldVector res = new SparseFieldVector(this); OpenIntToFieldHashMap.Iterator iter = res.entries.iterator(); while (iter.hasNext()) { iter.advance(); res.setEntry(iter.key(), iter.value().multiply(v.getEntry(iter.key()))); } return res; } /** {@inheritDoc} */ public FieldVector ebeMultiply(T[] v) throws IllegalArgumentException { checkVectorDimensions(v.length); SparseFieldVector res = new SparseFieldVector(this); OpenIntToFieldHashMap.Iterator iter = res.entries.iterator(); while (iter.hasNext()) { iter.advance(); res.setEntry(iter.key(), iter.value().multiply(v[iter.key()])); } return res; } /** {@inheritDoc} */ public T[] getData() { T[] res = buildArray(virtualSize); OpenIntToFieldHashMap.Iterator iter = entries.iterator(); while (iter.hasNext()) { iter.advance(); res[iter.key()] = iter.value(); } return res; } /** {@inheritDoc} */ public int getDimension() { return virtualSize; } /** {@inheritDoc} */ public T getEntry(int index) throws MatrixIndexException { checkIndex(index); return entries.get(index); } /** {@inheritDoc} */ public Field getField() { return field; } /** {@inheritDoc} */ public FieldVector getSubVector(int index, int n) throws MatrixIndexException { checkIndex(index); checkIndex(index + n - 1); SparseFieldVector res = new SparseFieldVector(field,n); int end = index + n; OpenIntToFieldHashMap.Iterator iter = entries.iterator(); while (iter.hasNext()) { iter.advance(); int key = iter.key(); if (key >= index && key < end) { res.setEntry(key - index, iter.value()); } } return res; } /** {@inheritDoc} */ public FieldVector mapAdd(T d) { return copy().mapAddToSelf(d); } /** {@inheritDoc} */ public FieldVector mapAddToSelf(T d) { for (int i = 0; i < virtualSize; i++) { setEntry(i, getEntry(i).add(d)); } return this; } /** {@inheritDoc} */ public FieldVector mapDivide(T d) { return copy().mapDivideToSelf(d); } /** {@inheritDoc} */ public FieldVector mapDivideToSelf(T d) { OpenIntToFieldHashMap.Iterator iter = entries.iterator(); while (iter.hasNext()) { iter.advance(); entries.put(iter.key(), iter.value().divide(d)); } return this; } /** {@inheritDoc} */ public FieldVector mapInv() { return copy().mapInvToSelf(); } /** {@inheritDoc} */ public FieldVector mapInvToSelf() { for (int i = 0; i < virtualSize; i++) { setEntry(i, field.getOne().divide(getEntry(i))); } return this; } /** {@inheritDoc} */ public FieldVector mapMultiply(T d) { return copy().mapMultiplyToSelf(d); } /** {@inheritDoc} */ public FieldVector mapMultiplyToSelf(T d) { OpenIntToFieldHashMap.Iterator iter = entries.iterator(); while (iter.hasNext()) { iter.advance(); entries.put(iter.key(), iter.value().multiply(d)); } return this; } /** {@inheritDoc} */ public FieldVector mapSubtract(T d) { return copy().mapSubtractToSelf(d); } /** {@inheritDoc} */ public FieldVector mapSubtractToSelf(T d) { return mapAddToSelf(field.getZero().subtract(d)); } /** * Optimized method to compute outer product when both vectors are sparse. * @param v vector with which outer product should be computed * @return the square matrix outer product between instance and v * @throws IllegalArgumentException if v is not the same size as {@code this} */ public FieldMatrix outerProduct(SparseFieldVector v) throws IllegalArgumentException { checkVectorDimensions(v.getDimension()); SparseFieldMatrix res = new SparseFieldMatrix(field, virtualSize, virtualSize); OpenIntToFieldHashMap.Iterator iter = entries.iterator(); while (iter.hasNext()) { iter.advance(); OpenIntToFieldHashMap.Iterator iter2 = v.entries.iterator(); while (iter2.hasNext()) { iter2.advance(); res.setEntry(iter.key(), iter2.key(), iter.value().multiply(iter2.value())); } } return res; } /** {@inheritDoc} */ public FieldMatrix outerProduct(T[] v) throws IllegalArgumentException { checkVectorDimensions(v.length); FieldMatrix res = new SparseFieldMatrix(field, virtualSize, virtualSize); OpenIntToFieldHashMap.Iterator iter = entries.iterator(); while (iter.hasNext()) { iter.advance(); int row = iter.key(); FieldElementvalue = iter.value(); for (int col = 0; col < virtualSize; col++) { res.setEntry(row, col, value.multiply(v[col])); } } return res; } /** {@inheritDoc} */ public FieldMatrix outerProduct(FieldVector v) throws IllegalArgumentException { if(v instanceof SparseFieldVector) return outerProduct((SparseFieldVector)v); else return outerProduct(v.toArray()); } /** {@inheritDoc} */ public FieldVector projection(FieldVector v) throws IllegalArgumentException { checkVectorDimensions(v.getDimension()); return v.mapMultiply(dotProduct(v).divide(v.dotProduct(v))); } /** {@inheritDoc} */ public FieldVector projection(T[] v) throws IllegalArgumentException { checkVectorDimensions(v.length); return projection(new SparseFieldVector(field,v)); } /** {@inheritDoc} */ public void set(T value) { for (int i = 0; i < virtualSize; i++) { setEntry(i, value); } } /** {@inheritDoc} */ public void setEntry(int index, T value) throws MatrixIndexException { checkIndex(index); entries.put(index, value); } /** {@inheritDoc} */ public void setSubVector(int index, FieldVector v) throws MatrixIndexException { checkIndex(index); checkIndex(index + v.getDimension() - 1); setSubVector(index, v.getData()); } /** {@inheritDoc} */ public void setSubVector(int index, T[] v) throws MatrixIndexException { checkIndex(index); checkIndex(index + v.length - 1); for (int i = 0; i < v.length; i++) { setEntry(i + index, v[i]); } } /** * Optimized method to subtract SparseRealVectors. * @param v The vector to subtract from this * @return The difference of this and v * @throws IllegalArgumentException If the dimensions don't match */ public SparseFieldVector subtract(SparseFieldVector v) throws IllegalArgumentException{ checkVectorDimensions(v.getDimension()); SparseFieldVector res = (SparseFieldVector)copy(); OpenIntToFieldHashMap.Iterator iter = v.getEntries().iterator(); while (iter.hasNext()) { iter.advance(); int key = iter.key(); if (entries.containsKey(key)) { res.setEntry(key, entries.get(key).subtract(iter.value())); } else { res.setEntry(key, field.getZero().subtract(iter.value())); } } return res; } /** {@inheritDoc} */ public FieldVector subtract(FieldVector v) throws IllegalArgumentException { if(v instanceof SparseFieldVector) return subtract((SparseFieldVector)v); else return subtract(v.toArray()); } /** {@inheritDoc} */ public FieldVector subtract(T[] v) throws IllegalArgumentException { checkVectorDimensions(v.length); SparseFieldVector res = new SparseFieldVector(this); for (int i = 0; i < v.length; i++) { if (entries.containsKey(i)) { res.setEntry(i, entries.get(i).subtract(v[i])); } else { res.setEntry(i, field.getZero().subtract(v[i])); } } return res; } /** {@inheritDoc} */ public T[] toArray() { return getData(); } /** * Check if an index is valid. * * @param index * index to check * @exception MatrixIndexException * if index is not valid */ private void checkIndex(final int index) throws MatrixIndexException { if (index < 0 || index >= getDimension()) { throw new MatrixIndexException(LocalizedFormats.INDEX_OUT_OF_RANGE, index, 0, getDimension() - 1); } } /** * Check if instance dimension is equal to some expected value. * * @param n * expected dimension. * @exception IllegalArgumentException * if the dimension is inconsistent with vector size */ protected void checkVectorDimensions(int n) throws IllegalArgumentException { if (getDimension() != n) { throw MathRuntimeException.createIllegalArgumentException( LocalizedFormats.VECTOR_LENGTH_MISMATCH, getDimension(), n); } } /** {@inheritDoc} */ public FieldVector add(FieldVector v) throws IllegalArgumentException { if (v instanceof SparseFieldVector) { return add((SparseFieldVector)v); } else { return add(v.toArray()); } } /** Build an array of elements. * @param length size of the array to build * @return a new array */ @SuppressWarnings("unchecked") // field is type T private T[] buildArray(final int length) { return (T[]) Array.newInstance(field.getZero().getClass(), length); } /** {@inheritDoc} */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((field == null) ? 0 : field.hashCode()); result = prime * result + virtualSize; OpenIntToFieldHashMap.Iterator iter = entries.iterator(); while (iter.hasNext()) { iter.advance(); int temp = iter.value().hashCode(); result = prime * result + temp; } return result; } /** {@inheritDoc} */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof SparseFieldVector)) { return false; } @SuppressWarnings("unchecked") // OK, because "else if" check below ensures that // other must be the same type as this SparseFieldVector other = (SparseFieldVector) obj; if (field == null) { if (other.field != null) { return false; } } else if (!field.equals(other.field)) { return false; } if (virtualSize != other.virtualSize) { return false; } OpenIntToFieldHashMap.Iterator iter = entries.iterator(); while (iter.hasNext()) { iter.advance(); T test = other.getEntry(iter.key()); if (!test.equals(iter.value())) { return false; } } iter = other.getEntries().iterator(); while (iter.hasNext()) { iter.advance(); T test = iter.value(); if (!test.equals(getEntry(iter.key()))) { return false; } } return true; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy