weka.core.AlgVector Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of weka-stable Show documentation
Show all versions of weka-stable Show documentation
The Waikato Environment for Knowledge Analysis (WEKA), a machine
learning workbench. This is the stable version. Apart from bugfixes, this version
does not receive any other updates.
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/*
* AlgVector.java
* Copyright (C) 2002-2012 University of Waikato, Hamilton, New Zealand
*
*/
package weka.core;
import java.io.Serializable;
import java.util.Random;
/**
* Class for performing operations on an algebraic vector
* of floating-point values.
*
* @author Gabi Schmidberger ([email protected])
* @version $Revision: 8034 $
*/
public class AlgVector
implements Cloneable, Serializable, RevisionHandler {
/** for serialization */
private static final long serialVersionUID = -4023736016850256591L;
/** The values of the matrix */
protected double[] m_Elements;
/**
* Constructs a vector and initializes it with default values.
*
* @param n the number of elements
*/
public AlgVector(int n) {
m_Elements = new double[n];
initialize();
}
/**
* Constructs a vector using a given array.
*
* @param array the values of the matrix
*/
public AlgVector(double[] array) {
m_Elements = new double[array.length];
for (int i = 0; i < array.length; i++) {
m_Elements[i] = array[i];
}
}
/**
* Constructs a vector using a given data format.
* The vector has an element for each numerical attribute.
* The other attributes (nominal, string) are ignored.
* Random is used to initialize the attributes.
*
* @param format the data format to use
* @param random for initializing the attributes
* @throws Exception if something goes wrong
*/
public AlgVector(Instances format, Random random) throws Exception {
int len = format.numAttributes();
for (int i = 0; i < format.numAttributes(); i++) {
if (!format.attribute(i).isNumeric()) len--;
}
if (len > 0) {
m_Elements = new double[len];
initialize(random);
}
}
/**
* Constructs a vector using an instance.
* The vector has an element for each numerical attribute.
* The other attributes (nominal, string) are ignored.
*
* @param instance with numeric attributes, that AlgVector gets build from
* @throws Exception if instance doesn't have access to the data format or
* no numeric attributes in the data
*/
public AlgVector(Instance instance) throws Exception {
int len = instance.numAttributes();
for (int i = 0; i < instance.numAttributes(); i++) {
if (!instance.attribute(i).isNumeric())
len--;
}
if (len > 0) {
m_Elements = new double[len];
int n = 0;
for (int i = 0; i < instance.numAttributes(); i++) {
if (!instance.attribute(i).isNumeric())
continue;
m_Elements[n] = instance.value(i);
n++;
}
}
else {
throw new IllegalArgumentException("No numeric attributes in data!");
}
}
/**
* Creates and returns a clone of this object.
*
* @return a clone of this instance.
* @throws CloneNotSupportedException if an error occurs
*/
public Object clone() throws CloneNotSupportedException {
AlgVector v = (AlgVector)super.clone();
v.m_Elements = new double[numElements()];
for (int i = 0; i < numElements(); i++) {
v.m_Elements[i] = m_Elements[i];
}
return v;
}
/**
* Resets the elements to the default value which is 0.0.
*/
protected void initialize() {
for (int i = 0; i < m_Elements.length; i++) {
m_Elements[i] = 0.0;
}
}
/**
* Initializes the values with random numbers between 0 and 1.
*
* @param random the random number generator to use for initializing
*/
protected void initialize(Random random) {
for (int i = 0; i < m_Elements.length; i++) {
m_Elements[i] = random.nextDouble();
}
}
/**
* Returns the value of a cell in the matrix.
*
* @param index the row's index
* @return the value of the cell of the vector
*/
public final double getElement(int index) {
return m_Elements[index];
}
/**
* Returns the number of elements in the vector.
*
* @return the number of rows
*/
public final int numElements() {
return m_Elements.length;
}
/**
* Sets an element of the matrix to the given value.
*
* @param index the elements index
* @param value the new value
*/
public final void setElement(int index, double value) {
m_Elements[index] = value;
}
/**
* Sets the elements of the vector to values of the given array.
* Performs a deep copy.
*
* @param elements an array of doubles
*/
public final void setElements(double[] elements) {
for (int i = 0; i < elements.length; i++) {
m_Elements[i] = elements[i];
}
}
/**
* Gets the elements of the vector and returns them as double array.
*
* @return an array of doubles
*/
public double[] getElements() {
double [] elements = new double[this.numElements()];
for (int i = 0; i < elements.length; i++) {
elements[i] = m_Elements[i];
}
return elements;
}
/**
* Gets the elements of the vector as an instance.
* !! NON-numeric data is ignored sofar
*
* @param model the dataset structure to fit the data to
* @param random in case of nominal values a random label is taken
* @return an array of doubles
* @throws Exception if length of vector is not number of numerical attributes
*/
public Instance getAsInstance(Instances model, Random random)
throws Exception {
Instance newInst = null;
if (m_Elements != null) {
newInst = new DenseInstance(model.numAttributes());
newInst.setDataset(model);
for (int i = 0, j = 0; i < model.numAttributes(); i++) {
if (model.attribute(i).isNumeric()) {
if (j >= m_Elements.length)
throw new Exception("Datatypes are not compatible.");
newInst.setValue(i, m_Elements[j++]);
}
if (model.attribute(i).isNominal()) {
int newVal = (int)
(random.nextDouble() * (double) (model.attribute(i).numValues()));
if (newVal == (int) model.attribute(i).numValues())
newVal -= 1;
newInst.setValue(i, newVal);
}
}
}
return newInst;
}
/**
* Returns the sum of this vector with another.
*
* @param other the vector to add
* @return a vector containing the sum.
*/
public final AlgVector add(AlgVector other) {
AlgVector b = null;
if (m_Elements != null) {
int n = m_Elements.length;
try {
b = (AlgVector)clone();
} catch (CloneNotSupportedException ex) {
b = new AlgVector(n);
}
for(int i = 0; i < n; i++) {
b.m_Elements[i] = m_Elements[i] + other.m_Elements[i];
}
}
return b;
}
/**
* Returns the difference of this vector minus another.
*
* @param other the vector to subtract
* @return a vector containing the difference vector.
*/
public final AlgVector substract(AlgVector other) {
int n = m_Elements.length;
AlgVector b;
try {
b = (AlgVector)clone();
} catch (CloneNotSupportedException ex) {
b = new AlgVector(n);
}
for(int i = 0; i < n; i++) {
b.m_Elements[i] = m_Elements[i] - other.m_Elements[i];
}
return b;
}
/**
* Returns the inner (or dot) product of two vectors
*
* @param b the multiplication matrix
* @return the double representing the dot product
*/
public final double dotMultiply(AlgVector b) {
double sum = 0.0;
if (m_Elements != null) {
int n = m_Elements.length;
for(int i = 0; i < n; i++) {
sum += m_Elements[i] * b.m_Elements[i];
}
}
return sum;
}
/**
* Computes the scalar product of this vector with a scalar
*
* @param s the scalar
*/
public final void scalarMultiply(double s) {
if (m_Elements != null) {
int n = m_Elements.length;
for(int i = 0; i < n; i++) {
m_Elements[i] = s * m_Elements[i];
}
}
}
/**
* Changes the length of a vector.
*
* @param len the new length of the vector
*/
public void changeLength(double len) {
double factor = this.norm();
factor = len / factor;
scalarMultiply(factor);
}
/**
* Returns the norm of the vector
*
* @return the norm of the vector
*/
public double norm() {
if (m_Elements != null) {
int n = m_Elements.length;
double sum = 0.0;
for(int i = 0; i < n; i++) {
sum += m_Elements[i] * m_Elements[i];
}
return Math.pow(sum, 0.5);
}
else return 0.0;
}
/**
* Norms this vector to length 1.0
*/
public final void normVector() {
double len = this.norm();
this.scalarMultiply(1 / len);
}
/**
* Converts a vector to a string
*
* @return the converted string
*/
public String toString() {
StringBuffer text = new StringBuffer();
for (int i = 0; i < m_Elements.length; i++) {
if (i > 0) text.append(",");
text.append(Utils.doubleToString(m_Elements[i],6));
}
text.append("\n");
return text.toString();
}
/**
* Returns the revision string.
*
* @return the revision
*/
public String getRevision() {
return RevisionUtils.extract("$Revision: 8034 $");
}
/**
* Main method for testing this class, can take an ARFF file as first argument.
*
* @param args commandline options
* @throws Exception if something goes wrong in testing
*/
public static void main(String[] args) throws Exception {
double[] first = {2.3, 1.2, 5.0};
try {
AlgVector test = new AlgVector(first);
System.out.println("test:\n " + test);
} catch (Exception e) {
e.printStackTrace();
}
}
}