SAMOA-80: Update instances to be used from MOA
Fix #83
diff --git a/samoa-instances/src/main/java/org/apache/samoa/instances/ArffLoader.java b/samoa-instances/src/main/java/org/apache/samoa/instances/ArffLoader.java
index dd82eda..51f5893 100644
--- a/samoa-instances/src/main/java/org/apache/samoa/instances/ArffLoader.java
+++ b/samoa-instances/src/main/java/org/apache/samoa/instances/ArffLoader.java
@@ -29,6 +29,9 @@
import java.util.logging.Level;
import java.util.logging.Logger;
+/**
+ * The Class ArffLoader. Loads an Arff file with sparse or dense format.
+ */
public class ArffLoader implements Loader {
/**
@@ -42,12 +45,14 @@
* The stream tokenizer.
*/
protected transient StreamTokenizer streamTokenizer;
+ protected Range range;
+ protected List<Attribute> auxAttributes;
/**
* Instantiates a new arff loader.
*
- * @param reader the reader
- * @param size the size
+ * @param reader the reader
+ * @param size the size
* @param classAttribute the class attribute
*/
public ArffLoader(Reader reader, int size, int classAttribute) {
@@ -61,8 +66,6 @@
}
}
- protected Range range;
-
/**
* Instantiates a new arff loader.
*
@@ -169,7 +172,7 @@
while (numAttribute == 0 && streamTokenizer.ttype != StreamTokenizer.TT_EOF) {
//For each line
while (streamTokenizer.ttype != StreamTokenizer.TT_EOL
- && streamTokenizer.ttype != StreamTokenizer.TT_EOF) {
+ && streamTokenizer.ttype != StreamTokenizer.TT_EOF) {
//For each item
if (streamTokenizer.ttype == StreamTokenizer.TT_NUMBER) {
//System.out.println(streamTokenizer.nval + "Num ");
@@ -177,7 +180,7 @@
++numAttribute;
} else if (streamTokenizer.sval != null && (streamTokenizer.ttype == StreamTokenizer.TT_WORD
- || streamTokenizer.ttype == 34 || streamTokenizer.ttype == 39)) {
+ || streamTokenizer.ttype == 34 || streamTokenizer.ttype == 39)) {
//System.out.println(streamTokenizer.sval + "Str");
boolean isNumeric = this.auxAttributes.get(numAttribute).isNumeric();
double value;
@@ -189,7 +192,7 @@
value = this.auxAttributes.get(numAttribute).indexOfValue(streamTokenizer.sval);
}
- instance.setValue(numAttribute,value);//this.setValue(instance, numAttribute, value, isNumeric);
+ instance.setValue(numAttribute, value);//this.setValue(instance, numAttribute, value, isNumeric);
++numAttribute;
}
streamTokenizer.nextToken();
@@ -242,7 +245,7 @@
streamTokenizer.nextToken(); // Remove the '{' char
//For each line
while (streamTokenizer.ttype != StreamTokenizer.TT_EOL
- && streamTokenizer.ttype != StreamTokenizer.TT_EOF) {
+ && streamTokenizer.ttype != StreamTokenizer.TT_EOF) {
while (streamTokenizer.ttype != '}') {
//For each item
//streamTokenizer.nextToken();
@@ -262,7 +265,7 @@
//numAttribute++;
} else if (streamTokenizer.sval != null && (streamTokenizer.ttype == StreamTokenizer.TT_WORD
- || streamTokenizer.ttype == 34 || streamTokenizer.ttype == 39)) {
+ || streamTokenizer.ttype == 34 || streamTokenizer.ttype == 39)) {
//System.out.print(streamTokenizer.sval + "-");
if (this.auxAttributes.get(numAttribute).isNumeric()) {
this.setSparseValue(instance, indexValues, attributeValues, numAttribute, Double.valueOf(streamTokenizer.sval).doubleValue(), true);
@@ -309,6 +312,9 @@
//System.out.println(numAttribute+":"+valueAttribute+","+this.instanceInformation.classIndex()+","+value);
}
+ //protected List<Attribute> inputAttributes;
+ // protected List<Attribute> outputAttributes;
+
/**
* Reads an instance sparse and returns a dense one.
*
@@ -324,7 +330,7 @@
streamTokenizer.nextToken(); // Remove the '{' char
//For each line
while (streamTokenizer.ttype != StreamTokenizer.TT_EOL
- && streamTokenizer.ttype != StreamTokenizer.TT_EOF) {
+ && streamTokenizer.ttype != StreamTokenizer.TT_EOF) {
while (streamTokenizer.ttype != '}') {
//For each item
//streamTokenizer.nextToken();
@@ -339,7 +345,7 @@
//numAttribute++;
} else if (streamTokenizer.sval != null && (streamTokenizer.ttype == StreamTokenizer.TT_WORD
- || streamTokenizer.ttype == 34)) {
+ || streamTokenizer.ttype == 34)) {
//System.out.print(streamTokenizer.sval + "/"+this.auxAttributes.get(numAttribute).indexOfValue(streamTokenizer.sval)+" ");
if (this.auxAttributes.get(numAttribute).isNumeric()) {
instance.setValue(numAttribute, Double.valueOf(streamTokenizer.sval).doubleValue());//this.setValue(instance, numAttribute, Double.valueOf(streamTokenizer.sval).doubleValue(), true);
@@ -362,11 +368,6 @@
return instance;
}
- //protected List<Attribute> inputAttributes;
- // protected List<Attribute> outputAttributes;
-
- protected List<Attribute> auxAttributes;
-
private InstanceInformation getHeader() {
//commented JD
//this.range.setUpper(10000); //TO DO: Create a new range object with isInRange that does not need the upper limit
diff --git a/samoa-instances/src/main/java/org/apache/samoa/instances/Attribute.java b/samoa-instances/src/main/java/org/apache/samoa/instances/Attribute.java
index 4f49b43..ff9a529 100644
--- a/samoa-instances/src/main/java/org/apache/samoa/instances/Attribute.java
+++ b/samoa-instances/src/main/java/org/apache/samoa/instances/Attribute.java
@@ -24,6 +24,9 @@
import java.text.SimpleDateFormat;
import java.util.*;
+/**
+ * Class that keeps all information needed to describe a feature or attribute.
+ */
public class Attribute implements Serializable {
/** The keyword used to denote the start of an arff attribute declaration */
@@ -68,8 +71,8 @@
*/
protected boolean isDate;
- /**
- * Date format specification for date attributes
+ /**
+ * Date format specification for date attributes
*/
protected SimpleDateFormat m_DateFormat;
@@ -122,7 +125,7 @@
* @param dateFormat the format of the date used
*/
public Attribute(String attributeName, String dateFormat) {
- this.name = attributeName;
+ this.name = attributeName;
this.valuesStringAttribute = null;
this.isDate = true;
diff --git a/samoa-instances/src/main/java/org/apache/samoa/instances/AttributesInformation.java b/samoa-instances/src/main/java/org/apache/samoa/instances/AttributesInformation.java
index 214a716..a3b2c52 100644
--- a/samoa-instances/src/main/java/org/apache/samoa/instances/AttributesInformation.java
+++ b/samoa-instances/src/main/java/org/apache/samoa/instances/AttributesInformation.java
@@ -24,13 +24,19 @@
import java.util.ArrayList;
import java.util.List;
+/**
+ * Class for storing the information of the attributes.
+ * It stores only information about discrete attributes and suppose that
+ * the default attribute is numeric.
+ */
public class AttributesInformation implements Serializable {
/**
* The attribute information.
*/
- protected List<Attribute> attributes;
- protected List<Integer> indexValues;
+ protected Attribute[] attributes;
+
+ protected int[] indexValues;
/**
* The number of attributes.
*/
@@ -42,22 +48,32 @@
protected Attribute defaultNumericAttribute;
public AttributesInformation(AttributesInformation chunk) {
- this.attributes = chunk.attributes;
- this.indexValues = chunk.indexValues;
+ this.attributes = chunk.attributes.clone();
+ this.indexValues = chunk.indexValues.clone();
this.numberAttributes = chunk.numberAttributes;
}
- public AttributesInformation(List<Attribute> v, List<Integer> i, int numberAttributes) {
+ public AttributesInformation(Attribute[] v, int[] i, int numberAttributes) {
this.attributes = v;
this.indexValues = i;
this.numberAttributes = numberAttributes;
}
- public AttributesInformation(List<Attribute> v, int numberAttributes) {
+ public AttributesInformation(Attribute[] v, int numberAttributes) {
this.attributes = v;
- this.indexValues = new ArrayList<Integer>(numberAttributes);
+ this.indexValues = new int[numberAttributes];
for (int i = 0; i < numberAttributes; i++) {
- this.indexValues.add(i);
+ this.indexValues[i] = i;
+ }
+ this.numberAttributes = numberAttributes;
+ }
+
+ public AttributesInformation(List<Attribute> v, int numberAttributes) {
+ this.attributes = new Attribute[numberAttributes];
+ this.indexValues = new int[numberAttributes];
+ for (int i = 0; i < numberAttributes; i++) {
+ this.indexValues[i] = i;
+ this.attributes[i] = v.get(i);
}
this.numberAttributes = numberAttributes;
}
@@ -85,22 +101,26 @@
//if there is not attribute information, it is numeric
return defaultNumericAttribute();
}
- return attributes.get(location);
+ return attributes[location];
}
- public void add(Attribute attribute, int value) {
- this.attributes.add(attribute);
- this.indexValues.add(value);
- }
+ /*public void add(Attribute attribute, int value) {
+ this.attributes.add(attribute);
+ this.indexValues.add(value);
+ }*/
/**
* Sets the attribute information.
*
* @param v the new attribute information
*/
- public void setAttributes(List<Attribute> v) {
+ public void setAttributes(Attribute[] v) {
this.attributes = v;
- this.numberAttributes=v.size();
+ this.numberAttributes = v.length;
+ this.indexValues = new int[numberAttributes];
+ for (int i = 0; i < numberAttributes; i++) {
+ this.indexValues[i] = i;
+ }
}
/**
@@ -112,24 +132,24 @@
public int locateIndex(int index) {
int min = 0;
- int max = this.indexValues.size() - 1;
+ int max = this.indexValues.length - 1;
if (max == -1) {
return -1;
}
// Binary search
- while ((this.indexValues.get(min) <= index) && (this.indexValues.get(max) >= index)) {
+ while ((this.indexValues[min] <= index) && (this.indexValues[max] >= index)) {
int current = (max + min) / 2;
- if (this.indexValues.get(current) > index) {
+ if (this.indexValues[current] > index) {
max = current - 1;
- } else if (this.indexValues.get(current) < index) {
+ } else if (this.indexValues[current] < index) {
min = current + 1;
} else {
return current;
}
}
- if (this.indexValues.get(max) < index) {
+ if (this.indexValues[max] < index) {
return max;
} else {
return min - 1;
@@ -143,47 +163,77 @@
return this.defaultNumericAttribute;
}
- public void setAttributes(List<Attribute> v, List<Integer> indexValues) {
+ public void setAttributes(Attribute[] v, int[] indexValues) {
this.attributes = v;
- this.numberAttributes=v.size();
- this.indexValues=indexValues;
+ this.numberAttributes = v.length;
+ this.indexValues = indexValues;
}
-
- public void deleteAttributeAt(Integer position) {
- if ((position < 0) || (position >= attributes.size())) {
- throw new IllegalArgumentException("Index out of range");
- }
- ArrayList<Attribute> newList = new ArrayList<Attribute>(attributes.size() - 1);
- for (int i = 0 ; i < position; i++) {
- Attribute att = attributes.get(i);
- newList.add(att);
- }
- for (int i = position + 1; i < attributes.size(); i++) {
- Attribute newAtt = (Attribute) attributes.get(i);
- newList.add(newAtt);
- }
- attributes = newList;
+ public void deleteAttributeAt(int position) {
+
+ int index = locateIndex(position);
+
+ this.numberAttributes--;
+ if ((index >= 0) && (indexValues[index] == position)) {
+ int[] tempIndices = new int[indexValues.length - 1];
+ Attribute[] tempValues = new Attribute[attributes.length - 1];
+ System.arraycopy(indexValues, 0, tempIndices, 0, index);
+ System.arraycopy(attributes, 0, tempValues, 0, index);
+ for (int i = index; i < indexValues.length - 1; i++) {
+ tempIndices[i] = indexValues[i + 1] - 1;
+ tempValues[i] = attributes[i + 1];
+ }
+ indexValues = tempIndices;
+ attributes = tempValues;
+ } else {
+ int[] tempIndices = new int[indexValues.length];
+ Attribute[] tempValues = new Attribute[attributes.length];
+ System.arraycopy(indexValues, 0, tempIndices, 0, index + 1);
+ System.arraycopy(attributes, 0, tempValues, 0, index + 1);
+ for (int i = index + 1; i < indexValues.length; i++) {
+ tempIndices[i] = indexValues[i] - 1;
+ tempValues[i] = attributes[i];
+ }
+ indexValues = tempIndices;
+ attributes = tempValues;
}
+ }
- public void insertAttributeAt(Attribute att, int position) {
-
- if ((position < 0) || (position > attributes.size())) {
- throw new IllegalArgumentException("Index out of range");
- }
-
- ArrayList<Attribute> newList = new ArrayList<Attribute>(attributes.size() + 1);
- for (int i = 0 ; i < position; i++) {
- Attribute oldAtt = attributes.get(i);
- newList.add(oldAtt);
- }
- newList.add(att);
- for (int i = position; i < attributes.size(); i++) {
- Attribute newAtt = (Attribute) attributes.get(i);
- newList.add(newAtt);
- }
- attributes = newList;
-
+ public void insertAttributeAt(Attribute attribute, int position) {
+ if ((position < 0) || (position > this.numberAttributes)) {
+ throw new IllegalArgumentException("Can't insert attribute: index out "
+ + "of range");
}
+ int index = locateIndex(position);
+
+ this.numberAttributes++;
+ if ((index >= 0) && (indexValues[index] == position)) {
+ int[] tempIndices = new int[indexValues.length + 1];
+ Attribute[] tempValues = new Attribute[attributes.length + 1];
+ System.arraycopy(indexValues, 0, tempIndices, 0, index);
+ System.arraycopy(attributes, 0, tempValues, 0, index);
+ tempIndices[index] = position;
+ tempValues[index] = attribute;
+ for (int i = index; i < indexValues.length; i++) {
+ tempIndices[i + 1] = indexValues[i] + 1;
+ tempValues[i + 1] = attributes[i];
+ }
+ indexValues = tempIndices;
+ attributes = tempValues;
+ } else {
+ int[] tempIndices = new int[indexValues.length + 1];
+ Attribute[] tempValues = new Attribute[attributes.length + 1];
+ System.arraycopy(indexValues, 0, tempIndices, 0, index + 1);
+ System.arraycopy(attributes, 0, tempValues, 0, index + 1);
+ tempIndices[index + 1] = position;
+ tempValues[index + 1] = attribute;
+ for (int i = index + 1; i < indexValues.length; i++) {
+ tempIndices[i + 1] = indexValues[i] + 1;
+ tempValues[i + 1] = attributes[i];
+ }
+ indexValues = tempIndices;
+ attributes = tempValues;
+ }
+ }
}
diff --git a/samoa-instances/src/main/java/org/apache/samoa/instances/DenseInstance.java b/samoa-instances/src/main/java/org/apache/samoa/instances/DenseInstance.java
index d8a789b..30652f3 100644
--- a/samoa-instances/src/main/java/org/apache/samoa/instances/DenseInstance.java
+++ b/samoa-instances/src/main/java/org/apache/samoa/instances/DenseInstance.java
@@ -20,6 +20,9 @@
* #L%
*/
+ /**
+ * Class that stores an instance that uses a dense representation.
+ */
public class DenseInstance extends InstanceImpl {
/**
diff --git a/samoa-instances/src/main/java/org/apache/samoa/instances/FilteredSparseInstance.java b/samoa-instances/src/main/java/org/apache/samoa/instances/FilteredSparseInstance.java
new file mode 100644
index 0000000..a762b79
--- /dev/null
+++ b/samoa-instances/src/main/java/org/apache/samoa/instances/FilteredSparseInstance.java
@@ -0,0 +1,80 @@
+package org.apache.samoa.instances;
+
+/*
+ * #%L
+ * SAMOA
+ * %%
+ * Copyright (C) 2014 - 2015 Apache Software Foundation
+ * %%
+ * Licensed 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.
+ * #L%
+ */
+
+/**
+ * The Class FilteredSparseInstance.
+ * <p>
+ * This class is an extension to the original SparseInstance.
+ * It has been created to be used with feature selection
+ * algorithms for data streams.
+ * In contrast to SparseInstance objects, missing values are
+ * represented as NaNs instead of 0s (zeros).
+ * This allows learners to skip features with missing values.
+ *
+ * @author Jean Paul Barddal
+ */
+public class FilteredSparseInstance extends SparseInstance {
+
+ /**
+ * Instantiates a new sparse instance.
+ *
+ * @param d the d
+ * @param res the res
+ */
+ public FilteredSparseInstance(double d, double[] res) {
+ super(d, res);
+ }
+
+
+ /**
+ * Instantiates a new sparse instance.
+ *
+ * @param inst the inst
+ */
+ public FilteredSparseInstance(InstanceImpl inst) {
+ super(inst);
+ }
+
+ /**
+ * Instantiates a new sparse instance.
+ *
+ * @param numberAttributes the number attributes
+ */
+ public FilteredSparseInstance(double numberAttributes) {
+ super(numberAttributes);
+ }
+
+ /**
+ * Instantiates a new sparse instance.
+ *
+ * @param weight the weight
+ * @param attributeValues the attribute values
+ * @param indexValues the index values
+ * @param numberAttributes the number attributes
+ */
+ public FilteredSparseInstance(double weight, double[] attributeValues, int[] indexValues, int numberAttributes) {
+ super(numberAttributes);
+ this.weight = weight;
+ this.instanceData = new FilteredSparseInstanceData(attributeValues, indexValues, numberAttributes);
+ }
+
+}
diff --git a/samoa-instances/src/main/java/org/apache/samoa/instances/FilteredSparseInstanceData.java b/samoa-instances/src/main/java/org/apache/samoa/instances/FilteredSparseInstanceData.java
new file mode 100644
index 0000000..d1d4848
--- /dev/null
+++ b/samoa-instances/src/main/java/org/apache/samoa/instances/FilteredSparseInstanceData.java
@@ -0,0 +1,68 @@
+package org.apache.samoa.instances;
+
+/*
+ * #%L
+ * SAMOA
+ * %%
+ * Copyright (C) 2014 - 2015 Apache Software Foundation
+ * %%
+ * Licensed 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.
+ * #L%
+ */
+
+/**
+ * The Class FilteredSparseInstanceData.
+ * <p>
+ * This class is an extension to the original SparseInstanceData.
+ * It has been created to be used with feature selection
+ * algorithms for data streams.
+ * In contrast to SparseInstanceData objects, missing values are
+ * represented as NaNs instead of 0s (zeros).
+ * This allows learners to skip features with missing values.
+ *
+ * @author Jean Paul Barddal
+ */
+public class FilteredSparseInstanceData extends SparseInstanceData {
+
+
+ /**
+ * Instantiates a new sparse instance data.
+ *
+ * @param attributeValues the attribute values
+ * @param indexValues the index values
+ * @param numberAttributes the number attributes
+ */
+ public FilteredSparseInstanceData(double[] attributeValues, int[] indexValues, int numberAttributes) {
+ super(attributeValues, indexValues, numberAttributes);
+ }
+
+
+ /**
+ * Value of the attribute in the indexAttribute position.
+ * If this value is absent, a NaN value (marker of missing value)
+ * is returned, otherwise this method returns the actual value.
+ *
+ * @param indexAttribute the index attribute
+ * @return the double
+ */
+ @Override
+ public double value(int indexAttribute) {
+ int location = locateIndex(indexAttribute);
+ if ((location >= 0) && (indexValues[location] == indexAttribute)) {
+ return attributeValues[location];
+ } else {
+ // returns a NaN value which represents missing values instead of a 0 (zero)
+ return Double.NaN;
+ }
+ }
+}
diff --git a/samoa-instances/src/main/java/org/apache/samoa/instances/Instance.java b/samoa-instances/src/main/java/org/apache/samoa/instances/Instance.java
index da4dcdd..48a3a60 100644
--- a/samoa-instances/src/main/java/org/apache/samoa/instances/Instance.java
+++ b/samoa-instances/src/main/java/org/apache/samoa/instances/Instance.java
@@ -22,6 +22,9 @@
import java.io.Serializable;
+/**
+ * The Interface Instance.
+ */
public interface Instance extends Serializable {
/**
@@ -47,6 +50,14 @@
public Attribute attribute(int instAttIndex);
/**
+ * Index of an Attribute.
+ *
+ * @param attribute, the attribute to be found.
+ * @return the index of an attribute
+ */
+ public int indexOfAttribute(Attribute attribute);
+
+ /**
* Delete attribute at.
*
* @param i the index
@@ -70,8 +81,8 @@
/**
* Adds the sparse values.
*
- * @param indexValues the index values
- * @param attributeValues the attribute values
+ * @param indexValues the index values
+ * @param attributeValues the attribute values
* @param numberAttributes the number attributes
*/
public void addSparseValues(int[] indexValues, double[] attributeValues, int numberAttributes);
@@ -100,20 +111,45 @@
public double value(int instAttIndex);
/**
+ * Gets the value of an attribute, given the attribute.
+ *
+ * @param attribute the attribute
+ * @return the double
+ */
+ public double value(Attribute attribute);
+
+ /**
* Sets an attribute as missing
*
- * @param instAttIndex, the attribute's index
+ * @param instAttIndex, the attribute's index
*/
- public void setMissing(int instAttIndex);
+ public void setMissing(int instAttIndex);
+
+
+ /**
+ * Sets an attribute as missing
+ *
+ * @param attribute, the Attribute
+ */
+ public void setMissing(Attribute attribute);
/**
* Sets the value of an attribute.
*
* @param instAttIndex the index
- * @param value the value
+ * @param value the value
*/
public void setValue(int instAttIndex, double value);
+
+ /**
+ * Sets the value of an attribute.
+ *
+ * @param attribute, the Attribute
+ * @param value the value
+ */
+ public void setValue(Attribute attribute, double value);
+
/**
* Checks if an attribute is missing.
*
@@ -123,6 +159,14 @@
public boolean isMissing(int instAttIndex);
/**
+ * Checks if an attribute is missing.
+ *
+ * @param attribute, the Attribute
+ * @return true, if is missing
+ */
+ public boolean isMissing(Attribute attribute);
+
+ /**
* Gets the index of the attribute given the index of the array in a sparse
* representation.
*
@@ -250,7 +294,7 @@
/**
* Sets the value of an output attribute.
*
- * @param indexClass the output attribute index
+ * @param indexClass the output attribute index
* @param valueAttribute the value of the attribute
*/
public void setClassValue(int indexClass, double valueAttribute);
@@ -287,45 +331,4 @@
*/
public double valueOutputAttribute(int attributeIndex);
- /**
- * Index of an Attribute.
- *
- * @param attribute, the attribute to be found.
- * @return the index of an attribute
- */
- public int indexOfAttribute(Attribute attribute);
-
- /**
- * Gets the value of an attribute, given the attribute.
- *
- * @param attribute the attribute
- * @return the double
- */
- public double value(Attribute attribute);
-
- /**
- * Sets an attribute as missing
- *
- * @param attribute, the Attribute
- */
- public void setMissing(Attribute attribute);
-
- /**
- * Sets the value of an attribute.
- *
- * @param attribute, the Attribute
- * @param value the value
- */
- public void setValue(Attribute attribute, double value);
-
- /**
- * Checks if an attribute is missing.
- *
- * @param attribute, the Attribute
- * @return true, if is missing
- */
- public boolean isMissing(Attribute attribute);
-
-
-
}
diff --git a/samoa-instances/src/main/java/org/apache/samoa/instances/InstanceData.java b/samoa-instances/src/main/java/org/apache/samoa/instances/InstanceData.java
index a5a5658..8eabdd2 100644
--- a/samoa-instances/src/main/java/org/apache/samoa/instances/InstanceData.java
+++ b/samoa-instances/src/main/java/org/apache/samoa/instances/InstanceData.java
@@ -22,6 +22,9 @@
import java.io.Serializable;
+/**
+ * The Interface InstanceData.
+ */
public interface InstanceData extends Serializable {
/**
diff --git a/samoa-instances/src/main/java/org/apache/samoa/instances/InstanceImpl.java b/samoa-instances/src/main/java/org/apache/samoa/instances/InstanceImpl.java
index e81c8a5..6a728cf 100644
--- a/samoa-instances/src/main/java/org/apache/samoa/instances/InstanceImpl.java
+++ b/samoa-instances/src/main/java/org/apache/samoa/instances/InstanceImpl.java
@@ -22,6 +22,9 @@
import java.text.SimpleDateFormat;
+/**
+ * Implementation of Instance.
+ */
public class InstanceImpl implements MultiLabelInstance {
/**
@@ -52,6 +55,7 @@
}
//Dense
+
/**
* Instantiates a new instance.
*
@@ -66,6 +70,7 @@
}
//Sparse
+
/**
* Instantiates a new instance.
*
@@ -247,6 +252,19 @@
}
/**
+ * Value.
+ *
+ * @param attribute
+ * the attribute
+ * @return the double
+ */
+ @Override
+ public double value(Attribute attribute) {
+ int index = this.instanceHeader.indexOf(attribute);
+ return value(index);
+ }
+
+ /**
* String value.
*
* @param i
@@ -299,7 +317,6 @@
@Override
public int classIndex() {
int classIndex = instanceHeader.classIndex();
- //return classIndex != Integer.MAX_VALUE ? classIndex : 0;
// return ? classIndex : 0;
if (classIndex == Integer.MAX_VALUE)
if (this.instanceHeader.instanceInformation.range != null)
@@ -379,7 +396,11 @@
*/
@Override
public void setDataset(Instances dataset) {
- this.instanceHeader = new InstancesHeader(dataset);
+ if (dataset instanceof InstancesHeader) {
+ this.instanceHeader = (InstancesHeader) dataset;
+ } else {
+ this.instanceHeader = new InstancesHeader(dataset);
+ }
}
/**
@@ -478,19 +499,6 @@
this.setValue(instAttIndex, Double.NaN);
}
- /**
- * Value.
- *
- * @param attribute
- * the attribute
- * @return the double
- */
- @Override
- public double value(Attribute attribute) {
- int index = this.instanceHeader.indexOf(attribute);
- return value(index);
- }
-
@Override
public void setMissing(Attribute attribute) {
int index = this.instanceHeader.indexOf(attribute);
diff --git a/samoa-instances/src/main/java/org/apache/samoa/instances/InstanceInformation.java b/samoa-instances/src/main/java/org/apache/samoa/instances/InstanceInformation.java
index 9d39791..32d686e 100644
--- a/samoa-instances/src/main/java/org/apache/samoa/instances/InstanceInformation.java
+++ b/samoa-instances/src/main/java/org/apache/samoa/instances/InstanceInformation.java
@@ -23,6 +23,9 @@
import java.io.Serializable;
import java.util.List;
+/**
+ * The Class InstanceInformation.
+ */
public class InstanceInformation implements Serializable {
/**
@@ -42,14 +45,6 @@
*/
protected Range range;
- public Attribute inputAttribute(int w) {
- return this.attributesInformation.attribute(inputAttributeIndex(w));
- }
-
- public Attribute outputAttribute(int w) {
- return this.attributesInformation.attribute(outputAttributeIndex(w));
- }
-
/**
* Instantiates a new instance information.
*
@@ -60,6 +55,18 @@
this.relationName = chunk.relationName;
this.attributesInformation = chunk.attributesInformation;
this.classIndex = chunk.classIndex;
+ this.range = chunk.range;
+ }
+
+ /**
+ * Instantiates a new instance information.
+ *
+ * @param st the st
+ * @param input the input
+ */
+ public InstanceInformation(String st, Attribute[] input) {
+ this.relationName = st;
+ this.attributesInformation = new AttributesInformation(input, input.length);
}
/**
@@ -83,78 +90,62 @@
this.attributesInformation = null;
}
- //Information Instances
- /* (non-Javadoc)
- * @see com.yahoo.labs.samoa.instances.InstanceInformationInterface#setRelationName(java.lang.String)
- */
- public void setRelationName(String string) {
- this.relationName = string;
+ public Attribute inputAttribute(int w) {
+ return this.attributesInformation.attribute(inputAttributeIndex(w));
}
- /* (non-Javadoc)
- * @see com.yahoo.labs.samoa.instances.InstanceInformationInterface#getRelationName()
- */
+ public Attribute outputAttribute(int w) {
+ return this.attributesInformation.attribute(outputAttributeIndex(w));
+ }
+
+
public String getRelationName() {
return this.relationName;
}
- /* (non-Javadoc)
- * @see com.yahoo.labs.samoa.instances.InstanceInformationInterface#classIndex()
- */
+ public void setRelationName(String string) {
+ this.relationName = string;
+ }
+
public int classIndex() {
return this.classIndex;
}
- /* (non-Javadoc)
- * @see com.yahoo.labs.samoa.instances.InstanceInformationInterface#setClassIndex(int)
- */
public void setClassIndex(int classIndex) {
this.classIndex = classIndex;
}
- /* (non-Javadoc)
- * @see com.yahoo.labs.samoa.instances.InstanceInformationInterface#classAttribute()
- */
public Attribute classAttribute() {
return this.attribute(this.classIndex());
}
- /* (non-Javadoc)
- * @see com.yahoo.labs.samoa.instances.InstanceInformationInterface#numAttributes()
- */
public int numAttributes() {
return this.attributesInformation.numberAttributes;
}
- /* (non-Javadoc)
- * @see com.yahoo.labs.samoa.instances.InstanceInformationInterface#attribute(int)
- */
public Attribute attribute(int w) {
return this.attributesInformation.attribute(w);
}
- /* (non-Javadoc)
- * @see com.yahoo.labs.samoa.instances.InstanceInformationInterface#numClasses()
- */
public int numClasses() {
return this.attributesInformation.attribute(classIndex()).numValues();
}
- /* (non-Javadoc)
- * @see com.yahoo.labs.samoa.instances.InstanceInformationInterface#deleteAttributeAt(java.lang.Integer)
- */
- public void deleteAttributeAt(Integer integer) {
+ public void deleteAttributeAt(int integer) {
this.attributesInformation.deleteAttributeAt(integer);
+ if (this.classIndex > integer) {
+ this.classIndex--;
+ }
}
- /* (non-Javadoc)
- * @see com.yahoo.labs.samoa.instances.InstanceInformationInterface#insertAttributeAt(com.yahoo.labs.samoa.instances.Attribute, int)
- */
public void insertAttributeAt(Attribute attribute, int i) {
this.attributesInformation.insertAttributeAt(attribute, i);
+ if (this.classIndex >= i) {
+ this.classIndex++;
+ }
}
- public void setAttributes(List<Attribute> v) {
+ public void setAttributes(Attribute[] v) {
if (this.attributesInformation == null)
this.attributesInformation = new AttributesInformation();
this.attributesInformation.setAttributes(v);
@@ -209,7 +200,7 @@
this.range = range;
}
- public void setAttributes(List<Attribute> v, List<Integer> indexValues) {
+ public void setAttributes(Attribute[] v, int[] indexValues) {
if (this.attributesInformation == null)
this.attributesInformation = new AttributesInformation();
this.attributesInformation.setAttributes(v, indexValues);
diff --git a/samoa-instances/src/main/java/org/apache/samoa/instances/Instances.java b/samoa-instances/src/main/java/org/apache/samoa/instances/Instances.java
index 04fde39..1ee3876 100644
--- a/samoa-instances/src/main/java/org/apache/samoa/instances/Instances.java
+++ b/samoa-instances/src/main/java/org/apache/samoa/instances/Instances.java
@@ -30,6 +30,9 @@
import java.util.List;
import java.util.Random;
+/**
+ * Class Instances that stores a set of instances and their structure.
+ */
public class Instances implements Serializable {
/**
@@ -65,6 +68,16 @@
transient protected Loader loader;
+/**
+ * Indices of relevant features.
+ */
+ protected int[] indicesRelevants;
+
+ /**
+ * Indices of irrelevant features.
+ */
+ protected int[] indicesIrrelevants;
+
/**
* Instantiates a new instances.
*
@@ -73,6 +86,11 @@
public Instances(Instances chunk) {
this(chunk, chunk.numInstances());
chunk.copyInstances(0, this, chunk.numInstances());
+ this.computeAttributesIndices();
+ if(chunk.indicesRelevants != null) {
+ this.indicesRelevants = chunk.indicesRelevants.clone();
+ this.indicesIrrelevants = chunk.indicesIrrelevants.clone();
+ }
}
/**
@@ -92,6 +110,7 @@
this.loader = new ArffLoader(reader, 0, classAttribute);
this.instanceInformation = loader.getStructure();
this.instances = new ArrayList<Instance>();
+ this.computeAttributesIndices();
}
/**
@@ -101,9 +120,10 @@
* @param range
*/
public Instances(Reader reader, Range range) {
- this.loader = new ArffLoader(reader, 0, classAttribute);//new MultiTargetArffLoader(reader, range);
+ this.loader = new MultiTargetArffLoader(reader, range); //new ArffLoader(reader, 0, classAttribute);
this.instanceInformation = loader.getStructure();
this.instances = new ArrayList<Instance>();
+ this.computeAttributesIndices();
}
public Instances(InputStream inputStream, int classAttribute, String encodingFormat) {
@@ -130,6 +150,24 @@
capacity = 0;
}
this.instances = new ArrayList<Instance>(capacity);
+ this.computeAttributesIndices();
+ if(chunk.indicesRelevants != null) {
+ this.indicesRelevants = chunk.indicesRelevants.clone();
+ this.indicesIrrelevants = chunk.indicesIrrelevants.clone();
+ }
+ }
+
+ /**
+ * Instantiates a new instances.
+ *
+ * @param st the st
+ * @param v the v
+ * @param capacity the capacity
+ */
+ public Instances(String st, Attribute[] v, int capacity) {
+ this.instanceInformation = new InstanceInformation(st, v);
+ this.instances = new ArrayList<Instance>(capacity);
+ this.computeAttributesIndices();
}
/**
@@ -140,8 +178,13 @@
* @param capacity the capacity
*/
public Instances(String st, List<Attribute> v, int capacity) {
- this.instanceInformation = new InstanceInformation(st, v);
+ Attribute[] attributes = new Attribute[v.size()];
+ for (int i = 0; i < v.size(); i++) {
+ attributes[i]= v.get(i);
+ }
+ this.instanceInformation = new InstanceInformation(st, attributes);
this.instances = new ArrayList<Instance>(capacity);
+ this.computeAttributesIndices();
}
/**
@@ -160,6 +203,7 @@
+ "of range");
}
chunk.copyInstances(first, this, toCopy);
+ this.computeAttributesIndices();
}
/**
@@ -170,6 +214,7 @@
*/
public Instances(StringReader st, int capacity) {
this.instances = new ArrayList<Instance>(capacity);
+ this.computeAttributesIndices();
}
//Information Instances
@@ -253,21 +298,32 @@
*/
public void deleteAttributeAt(Integer integer) {
this.instanceInformation.deleteAttributeAt(integer);
+ for (int i = 0; i < numInstances(); i++) {
+ instance(i).setDataset(null);
+ instance(i).deleteAttributeAt(integer);
+ instance(i).setDataset(this);
+ }
}
/**
- * Insert attribute at.
- *
- * @param attribute the attribute
- * @param i the i
- */
- public void insertAttributeAt(Attribute attribute, int i) {
- if (this.instanceInformation == null) {
- this.instanceInformation = new InstanceInformation();
- }
- this.instanceInformation.insertAttributeAt(attribute, i);
+ * Insert attribute at.
+ *
+ * @param attribute the attribute
+ * @param position the position
+ */
+ public void insertAttributeAt(Attribute attribute, int position) {
+ if (this.instanceInformation == null) {
+ this.instanceInformation = new InstanceInformation();
+ }
+ this.instanceInformation.insertAttributeAt(attribute, position);
+ for (int i = 0; i < numInstances(); i++) {
+ instance(i).setDataset(null);
+ instance(i).insertAttributeAt(i);
+ instance(i).setDataset(this);
+ }
}
+
//List of Instances
/**
* Instance.
@@ -525,20 +581,31 @@
}
- public void setAttributes(List<Attribute> v) {
+ public void setAttributes(Attribute[] v) {
if (this.instanceInformation == null) {
- this.instanceInformation = new InstanceInformation();
+ this.instanceInformation = new InstanceInformation();
}
this.instanceInformation.setAttributes(v);
- }
+}
- public void setAttributes(List<Attribute> v, List<Integer> indexValues) {
+public void setAttributes(Attribute[] v, int[] indexValues) {
if (this.instanceInformation == null) {
this.instanceInformation = new InstanceInformation();
}
this.instanceInformation.setAttributes(v, indexValues);
}
+ public void setAttributes(List<Attribute> v, List<Integer> indexValues) {
+ int[] ret = new int[indexValues.size()];
+ for(int i = 0;i < ret.length;i++)
+ ret[i] = indexValues.get(i);
+ Attribute[] attributes = new Attribute[v.size()];
+ for (int i = 0; i < v.size(); i++) {
+ attributes[i]= v.get(i);
+ }
+ setAttributes(attributes, ret);
+ }
+
/**
* Returns the dataset as a string in ARFF format. Strings are quoted if
* they contain whitespace characters, or if they are a question mark.
@@ -626,4 +693,48 @@
hsAttributesIndices.put(this.attribute(i).name(), i);
}
}
+
+ /**
+ * Returns the indices of the relevant features indicesRelevants.
+ * @return indicesRelevants
+ */
+ public int[] getIndicesRelevants() {
+ return indicesRelevants;
+ }
+
+ /**
+ * Returns the indices of the irrelevant features indicesIrrelevants.
+ * @return indicesIrrelevants
+ */
+ public int[] getIndicesIrrelevants() {
+ return indicesIrrelevants;
+ }
+
+ /**
+ * Sets the indices of relevant features.
+ * This method also sets the irrelevant ones since
+ * it is the set complement.
+ *
+ * @param indicesRelevants
+ */
+ public void setIndicesRelevants(int[] indicesRelevants) {
+ this.indicesRelevants = indicesRelevants;
+ // -1 to skip the class attribute
+ int numIrrelevantFeatures = this.numAttributes() - this.indicesRelevants.length - 1;
+ this.indicesIrrelevants = new int[numIrrelevantFeatures];
+
+ // Infers and sets the set of irrelevant features
+ int index = 0;
+ int indexRel = 0;
+ for(int i = 0; i < numAttributes(); i++){
+ if(i != classIndex()) {
+ while (indexRel < indicesRelevants.length - 1 &&
+ i > indicesRelevants[indexRel]) indexRel++;
+ if (indicesRelevants[indexRel] != i){
+ indicesIrrelevants[index] = i;
+ index++;
+ }
+ }
+ }
+ }
}
diff --git a/samoa-instances/src/main/java/org/apache/samoa/instances/InstancesHeader.java b/samoa-instances/src/main/java/org/apache/samoa/instances/InstancesHeader.java
index c32cf88..a58566f 100644
--- a/samoa-instances/src/main/java/org/apache/samoa/instances/InstancesHeader.java
+++ b/samoa-instances/src/main/java/org/apache/samoa/instances/InstancesHeader.java
@@ -20,6 +20,10 @@
* #L%
*/
+ /**
+ * Class for storing the header or context of a data stream. It allows to know
+ * the number of attributes and classes.
+ */
public class InstancesHeader extends Instances {
private static final long serialVersionUID = 1L;
diff --git a/samoa-instances/src/main/java/org/apache/samoa/instances/MultiLabelInstance.java b/samoa-instances/src/main/java/org/apache/samoa/instances/MultiLabelInstance.java
index 9567c90..9cfcb96 100644
--- a/samoa-instances/src/main/java/org/apache/samoa/instances/MultiLabelInstance.java
+++ b/samoa-instances/src/main/java/org/apache/samoa/instances/MultiLabelInstance.java
@@ -20,6 +20,9 @@
* #L%
*/
+/**
+ * The Interface MultiLabelInstance.
+ */
public interface MultiLabelInstance extends Instance {
}
diff --git a/samoa-instances/src/main/java/org/apache/samoa/instances/MultiLabelPrediction.java b/samoa-instances/src/main/java/org/apache/samoa/instances/MultiLabelPrediction.java
index 0b51c56..5b82294 100644
--- a/samoa-instances/src/main/java/org/apache/samoa/instances/MultiLabelPrediction.java
+++ b/samoa-instances/src/main/java/org/apache/samoa/instances/MultiLabelPrediction.java
@@ -21,47 +21,40 @@
*/
import java.io.Serializable;
-import java.util.ArrayList;
public class MultiLabelPrediction implements Prediction, Serializable {
- protected ArrayList< ArrayList<Double> > prediction;
+ protected DoubleVector[] prediction;
public MultiLabelPrediction() {
this(0);
}
public MultiLabelPrediction(int numOutputAttributes) {
- prediction = new ArrayList< ArrayList<Double> >();
- for (int i=0; i<numOutputAttributes;i++)
- prediction.add(new ArrayList<Double>());
+ prediction = new DoubleVector[numOutputAttributes];
+ for (int i = 0; i < numOutputAttributes; i++)
+ prediction[i] = new DoubleVector();
}
@Override
public int numOutputAttributes() {
- return prediction.size();
+ return prediction.length;
}
@Override
public int numClasses(int outputAttributeIndex) {
int ret = 0;
- if (prediction.size() > outputAttributeIndex) {
- ret = prediction.get(outputAttributeIndex).size();
+ if (prediction.length > outputAttributeIndex) {
+ ret = prediction[outputAttributeIndex].numValues();
}
return ret;
}
@Override
public double[] getVotes(int outputAttributeIndex) {
- int s = prediction.get(outputAttributeIndex).size();
double ret[] = null;
- if (prediction.size() > outputAttributeIndex) {
- ArrayList<Double> aux = prediction.get(outputAttributeIndex);
- ret = new double[s];
- for (int i =0;i < s;i++) {
- ret[i] = aux.get(i).doubleValue();
- }
+ if (prediction.length > outputAttributeIndex) {
+ ret = prediction[outputAttributeIndex].getArrayCopy();
}
-
return ret;
}
@@ -71,54 +64,38 @@
}
@Override
+ public void setVotes(double[] votes) {
+ setVotes(0, votes);
+ }
+
+ @Override
public double getVote(int outputAttributeIndex, int classIndex) {
double ret = 0.0;
- if (prediction.size() > outputAttributeIndex) {
- ret = (classIndex >= 0 && classIndex < prediction.get(outputAttributeIndex).size()) ?
- prediction.get(outputAttributeIndex).get(classIndex) : 0;
+ if (prediction.length > outputAttributeIndex) {
+ ret = prediction[outputAttributeIndex].getValue(classIndex);
}
return ret;
}
@Override
public void setVotes(int outputAttributeIndex, double[] votes) {
- for(int i=0; i<votes.length; i++) {
- if (i >= prediction.get(outputAttributeIndex).size()) {
- prediction.get(outputAttributeIndex).ensureCapacity(i+1);
- while (prediction.get(outputAttributeIndex).size() < i+1) {
- prediction.get(outputAttributeIndex).add(0.0);
- }
- }
-
- prediction.get(outputAttributeIndex).set(i,votes[i]);
- }
- }
-
- @Override
- public void setVotes(double[] votes) {
- setVotes(0, votes);
+ for (int i = 0; i < votes.length; i++)
+ prediction[outputAttributeIndex].setValue(i, votes[i]);
}
@Override
public void setVote(int outputAttributeIndex, int classIndex, double vote) {
- if (outputAttributeIndex >= prediction.get(outputAttributeIndex).size()) {
- prediction.get(outputAttributeIndex).ensureCapacity(classIndex+1);
- while (prediction.get(outputAttributeIndex).size() < classIndex+1) {
- prediction.get(outputAttributeIndex).add(0.0);
- }
- }
+ prediction[outputAttributeIndex].setValue(classIndex, vote);
- prediction.get(outputAttributeIndex).set(classIndex, vote);
}
@Override
- public String toString(){
- StringBuffer sb= new StringBuffer();
- for (int i=0; i<prediction.size(); i++){
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < prediction.length; i++) {
sb.append("Out " + i + ": ");
- for (int c=0; c<prediction.get(i).size(); c++)
- {
- sb.append(((int)(prediction.get(i).get(c)*1000)/1000.0)+ " ");
+ for (int c = 0; c < prediction[i].numValues(); c++) {
+ sb.append(((int) (prediction[i].getValue(c) * 1000) / 1000.0) + " ");
}
}
return sb.toString();
@@ -126,14 +103,82 @@
@Override
public boolean hasVotesForAttribute(int outputAttributeIndex) {
- if(prediction.size()<(outputAttributeIndex+1))
+ if (prediction.length < (outputAttributeIndex + 1))
return false;
- return (prediction.get(outputAttributeIndex).size()==0) ? false : true;
+ return (prediction[outputAttributeIndex].numValues() == 0) ? false : true;
}
@Override
public int size() {
- return prediction.size();
+ return prediction.length;
}
-}
\ No newline at end of file
+ protected class DoubleVector implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ protected double[] array;
+
+ public DoubleVector() {
+ this.array = new double[0];
+ }
+
+ public DoubleVector(double[] toCopy) {
+ this.array = new double[toCopy.length];
+ System.arraycopy(toCopy, 0, this.array, 0, toCopy.length);
+ }
+
+ public int numValues() {
+ return this.array.length;
+ }
+
+ public void setValue(int i, double v) {
+ if (i >= this.array.length) {
+ setArrayLength(i + 1);
+ }
+ this.array[i] = v;
+ }
+
+ public void addToValue(int i, double v) {
+ if (i >= this.array.length) {
+ setArrayLength(i + 1);
+ }
+ this.array[i] += v;
+ }
+
+ // returns 0.0 for values outside of range
+ public double getValue(int i) {
+ return ((i >= 0) && (i < this.array.length)) ? this.array[i] : 0.0;
+ }
+
+
+ public int maxIndex() {
+ int max = -1;
+ for (int i = 0; i < this.array.length; i++) {
+ if ((max < 0) || (this.array[i] > this.array[max])) {
+ max = i;
+ }
+ }
+ return max;
+ }
+
+ public double[] getArrayCopy() {
+ double[] aCopy = new double[this.array.length];
+ System.arraycopy(this.array, 0, aCopy, 0, this.array.length);
+ return aCopy;
+ }
+
+ protected void setArrayLength(int l) {
+ double[] newArray = new double[l];
+ int numToCopy = this.array.length;
+ if (numToCopy > l) {
+ numToCopy = l;
+ }
+ System.arraycopy(this.array, 0, newArray, 0, numToCopy);
+ this.array = newArray;
+ }
+
+
+ }
+
+}
diff --git a/samoa-instances/src/main/java/org/apache/samoa/instances/SparseInstanceData.java b/samoa-instances/src/main/java/org/apache/samoa/instances/SparseInstanceData.java
index 940271a..338643d 100644
--- a/samoa-instances/src/main/java/org/apache/samoa/instances/SparseInstanceData.java
+++ b/samoa-instances/src/main/java/org/apache/samoa/instances/SparseInstanceData.java
@@ -23,6 +23,19 @@
public class SparseInstanceData implements InstanceData {
/**
+ * The attribute values.
+ */
+ protected double[] attributeValues;
+ /**
+ * The index values.
+ */
+ protected int[] indexValues;
+ /**
+ * The number of attributes.
+ */
+ protected int numberAttributes;
+
+ /**
* Instantiates a new sparse instance data.
*
* @param attributeValues
@@ -50,11 +63,6 @@
}
/**
- * The attribute values.
- */
- protected double[] attributeValues;
-
- /**
* Gets the attribute values.
*
* @return the attribute values
@@ -112,16 +120,6 @@
}
/**
- * The index values.
- */
- protected int[] indexValues;
-
- /**
- * The number of attributes.
- */
- protected int numberAttributes;
-
- /**
* Gets the number of attributes.
*
* @return the int
@@ -313,7 +311,7 @@
public void insertAttributeAt(int position) {
if ((position < 0) || (position > numAttributes())) {
throw new IllegalArgumentException("Can't insert attribute: index out "
- + "of range");
+ + "of range");
}
int index = locateIndex(position);