source: src/main/java/weka/classifiers/misc/monotone/Coordinates.java @ 7

Last change on this file since 7 was 4, checked in by gnappo, 14 years ago

Import di weka.

File size: 7.4 KB
Line 
1/*
2 *    This program is free software; you can redistribute it and/or modify
3 *    it under the terms of the GNU General Public License as published by
4 *    the Free Software Foundation; either version 2 of the License, or
5 *    (at your option) any later version.
6 *
7 *    This program is distributed in the hope that it will be useful,
8 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 *    GNU General Public License for more details.
11 *
12 *    You should have received a copy of the GNU General Public License
13 *    along with this program; if not, write to the Free Software
14 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16
17/*
18 *    Coordinates.java
19 *    Copyright (C) 2004 Stijn Lievens
20 *
21 */
22
23package weka.classifiers.misc.monotone;
24
25import weka.core.Instance;
26import weka.core.RevisionHandler;
27import weka.core.RevisionUtils;
28
29import java.io.Serializable;
30
31/**
32 * This is a simple implementation of the data space.  The <code>
33 * Coordinates </code> holds the internal weka value of an instance,
34 * but <i> with the class removed </i>.  The class is immutable,
35 * and works best when all attibutes are nominal (ordinal), although
36 * it will not give an error when working with numeric attributes.
37 * In the latter case, performance will degrade because of the way
38 * in which the hashcode is calculated.
39 *
40 * <p>
41 * This implementation is part of the master's thesis: "Studie
42 * en implementatie van instantie-gebaseerde algoritmen voor gesuperviseerd
43 * rangschikken", Stijn Lievens, Ghent University, 2004.
44 * </p>
45 *
46 * @author Stijn Lievens (stijn.lievens@ugent.be)
47 * @version $Revision: 5922 $
48 */
49public class Coordinates
50  implements Serializable, RevisionHandler {
51
52  /** for serialization */
53  private static final long serialVersionUID = 2319016195345994738L;
54
55  /**
56   * The internal weka values of the attributes of the instance, minus
57   * the class attribute.
58   */
59  private int[] m_coord;
60
61  /**
62   * The hashcode of this object.  Calculated during construction.
63   */
64  private int m_hashCode;
65
66  /**
67   * Create the <code> Coordinates </code> for the given instance.
68   *
69   * @param instance the <code> Instance </code> on which the <code>
70   * Coordinates </code> will be based
71   */
72  public Coordinates(Instance instance) {
73
74    double[] values = instance.toDoubleArray();
75    int classIndex = instance.classIndex();
76    if (classIndex == -1) {
77      m_coord = new int[values.length];
78    } else {
79      m_coord = new int[values.length - 1];
80    }
81
82    m_hashCode = 0;
83    int factor=1;
84    for (int i = 0,j = 0;i < values.length; i++) { 
85      if (i != classIndex) {
86        m_coord[j] = (int) values[i];
87        if (i > 0 && i - 1 != classIndex) {
88          factor *= instance.attribute(i-1).numValues();
89        } else if (i - 1 == classIndex && classIndex != -1 
90            && classIndex != 0) {
91          factor *= instance.attribute(i - 2).numValues();
92        }
93        m_hashCode += (m_coord[j])*factor;
94        j++;   
95      }
96    }
97  }
98
99  /**
100   * Get the value of the attribute with index <code> index, </code>
101   * ignoring the class attribute.  Indices are counted starting from
102   * 0. 
103   *
104   * @param index the index of the requested attribute
105   * @return the value of this attribute, in internal floating point format.
106   */
107  public double getValue(int index) {
108    return m_coord[index];
109  }
110
111  /**
112   * Get the values of the coordinates.
113   *
114   * @param values array serving as output, and the first
115   * <code> dimension() </code> values are filled in.
116   */
117  public void getValues(double[] values) {
118    // XXX this is a rather strange method, maybe it should be changed
119    // into one that returns (using System.arraycopy) the requested values
120    for (int i = 0; i < m_coord.length; i++) {
121      values[i] = m_coord[i];
122    }
123  }
124
125  /**
126   * Indicates if the object <code> o </code> equals <code> this. </code>
127   *
128   * @param o the reference object with which to compare
129   * @return <code> true </code> if <code> o </code> equals <code>
130   * this, </code> <code> false </code> otherwise
131   */
132  public boolean equals(Object o) {
133    if (! (o instanceof Coordinates) ) {
134      return false;
135    }
136
137    Coordinates cc = (Coordinates) o;
138    // if the length or hashCodes differ, the objects are certainly not equal
139    if (m_coord.length != cc.m_coord.length || m_hashCode != cc.m_hashCode) {
140      return false;
141    }
142
143    for (int i = 0; i < m_coord.length; i++) {
144      if (m_coord[i] != cc.m_coord[i]) {
145        return false;
146      }
147    }
148    return true;
149  }
150
151  /**
152   * Checks if <code> this </code> is strictly smaller than <code> cc. </code>
153   * This means that for all indices i it holds that
154   * <code> this.getValue(i) &lt;= cc.getValue(i) </code> and that there is
155   * at least one index i such that
156   * <code> this.getValue(i) &ne; cc.getValue(i) </code>
157   *
158   * @param cc the <code> Coordinates </code> that <code> this </code> is
159   * compared to
160   * @return <code> true </code> if <code> this </code> is strictly
161   * smaller than <code> cc, </code> <code> false </code> otherwise
162   * @throws IllegalArgumentException if the dimensions of both objects differ
163   */
164  public boolean strictlySmaller(Coordinates cc) throws IllegalArgumentException {
165    if (cc.m_coord.length != m_coord.length) { 
166      throw new IllegalArgumentException
167      ("Coordinates are not from the same space");
168    }
169
170    // Skip all equal values
171    int i = 0;
172    while(i < m_coord.length && cc.m_coord[i] == m_coord[i]) { 
173      i++;
174    }
175
176    if (i == m_coord.length) {
177      return false; // equality !
178    }
179
180    for (; i < m_coord.length; i++) {
181      if (m_coord[i] > cc.m_coord[i]) { 
182        return false;
183      }
184    }
185    return true;
186  }
187
188  /**
189   * Checks if <code> this </code> is smaller or equal than <code> cc. </code>
190   * This means that for all indices i it holds that
191   * <code> this.getValue(i) &lt;= cc.getValue(i). </code>
192   *
193   * @param cc the <code> Coordinates </code> that <code> this </code> is
194   * compared to
195   * @return <code> true </code> if <code> this </code> is
196   * smaller or equal than <code> cc, </code> <code> false </code> otherwise
197   * @throws IllegalArgumentException if the dimensions of both objects differ
198   */
199  public boolean smallerOrEqual(Coordinates cc) throws IllegalArgumentException {
200    if (cc.m_coord.length != m_coord.length) { 
201      throw new IllegalArgumentException
202      ("Coordinates are not from the same space");
203    }
204    for (int i = 0; i < m_coord.length; i++) {
205      if (m_coord[i] > cc.m_coord[i]) { 
206        return false;
207      }
208    }
209    return true;
210  }
211
212  /**
213   * Gets the hash code value for this object.
214   *
215   * @return the requested hash code
216   */
217  public int hashCode() {
218    return m_hashCode;
219  }
220
221  /**
222   * Gets the dimension of the data space, this is the number of attributes,
223   * exluding the class attribute.
224   *
225   * @return the dimension of the data space this object resides in
226   */
227  public int dimension() {
228    return m_coord.length;
229  }
230
231  /**
232   * Get a string representation of this object.
233   *
234   * @return the requested string representation
235   */
236  public String toString() {
237    String s = "(";
238    for (int i = 0; i < m_coord.length - 1; i++) {
239      s += m_coord[i] + ",";
240    }
241    return s + m_coord[m_coord.length - 1] + ")";
242  }
243 
244  /**
245   * Returns the revision string.
246   *
247   * @return            the revision
248   */
249  public String getRevision() {
250    return RevisionUtils.extract("$Revision: 5922 $");
251  }
252}
Note: See TracBrowser for help on using the repository browser.