View Javadoc

1   package yawn.util;
2   
3   import java.util.Random;
4   import java.util.StringTokenizer;
5   
6   /***
7    * A pattern (or vector or stimuli) of real numbers (double).
8    * 
9    * <p>$Id: Pattern.java,v 1.13 2005/04/20 18:55:18 supermarti Exp $</p>
10   * 
11   * @author Luis Mart&iacute; (luis dot marti at uc3m dot es)
12   * @version $Revision: 1.13 $
13   */
14  public class Pattern {
15      public static final String ELEMENT_SEPARATOR = " ";
16  
17      private double[] elements;
18  
19      /***
20       * Creates a zero elements <code>Pattern</code>.
21       */
22      public Pattern() {
23          elements = new double[0];
24      }
25  
26      /***
27       * Creates a <code>Pattern</code> whose elements are copied from
28       * <code>source</code>.
29       * 
30       * @param source
31       *            the array from which elements are copied
32       */
33      public Pattern(double[] source) {
34          elements = new double[source.length];
35  
36          for (int i = 0; i < source.length; i++) {
37              elements[i] = source[i];
38          }
39      }
40  
41      /***
42       * Creates a <code>Pattern</code> of the desired size initialized to zero.
43       * 
44       * @param size
45       *            the dimension of the new <code>Pattern</code>
46       */
47      public Pattern(int size) {
48          elements = new double[size];
49      }
50  
51      /***
52       * Creates a <code>Pattern</code> whose elements are copied from
53       * <code>source</code>.
54       * 
55       * @param source
56       *            the <code>Pattern</code> to be used as source
57       */
58      public Pattern(Pattern source) {
59          this(source.asDoubleArray());
60      }
61  
62      /***
63       * Element-wise addition.
64       * 
65       * @param operand
66       *            the <code>Pattern</code> to add
67       * @return the result of the operation
68       */
69      public Pattern add(Pattern operand) {
70          checkEqualSize(operand);
71  
72          Pattern res = new Pattern(size());
73  
74          for (int i = 0; i < size(); i++) {
75              res.setComponent(elements[i] + operand.getComponent(i), i);
76          }
77  
78          return res;
79      }
80  
81      /***
82       * Scalar addition.
83       * 
84       * @param operand
85       *            the amount to add
86       * @return the result of the sum
87       */
88      public Pattern add(double operand) {
89          Pattern res = new Pattern(size());
90  
91          for (int i = 0; i < size(); i++) {
92              res.setComponent(elements[i] + operand, i);
93          }
94  
95          return res;
96      }
97  
98      /***
99       * Appends an element to the <code>Pattern</code>. Note that is an
100      * inefficient operation and should be rarely used.
101      * 
102      * @param value
103      *            the value of the element to append
104      */
105     public void appendComponent(double value) {
106         int size = elements == null ? 0 : elements.length;
107         double[] newelements = new double[size + 1];
108 
109         for (int i = 0; (elements != null) && (i < elements.length); i++) {
110             newelements[i] = elements[i];
111         }
112         newelements[newelements.length - 1] = value;
113         elements = newelements;
114     }
115 
116     /***
117      * The elements of this <code>Pattern</code> as a <code>double[]</code>.
118      * 
119      * @return the <code>double[]</code>
120      */
121     public double[] asDoubleArray() {
122         return elements;
123     }
124 
125     /***
126      * Checks if a <code>Pattern</code> has equal size.
127      * 
128      * @param comp
129      *            <code>Pattern</code> to test with
130      * @throws ArrayIndexOutOfBoundsException
131      */
132     protected void checkEqualSize(Pattern comp) {
133         if (comp.size() != size()) {
134             throw new ArrayIndexOutOfBoundsException(
135                     "Doing operations with yawn.util.Pattern instances of different sizes.");
136         }
137     }
138 
139     public Object clone() {
140         return new Pattern(this);
141     }
142 
143     /***
144      * Calculates an Euclidean distance from this <code>Pattern</code>.
145      * 
146      * @param other
147      *            the <code>Pattern</code> to measure the distance with
148      * @return the distance
149      */
150     public double dist(Pattern other) {
151         return this.substract(other).norm2();
152     }
153 
154     public boolean equals(Pattern other) {
155         if (size() != other.size())
156             return false;
157         for (int i = 0; i < size(); i++) {
158             if (elements[i] != other.getComponent(i)) {
159                 return false;
160             }
161         }
162         return true;
163     }
164 
165     /***
166      * Returns the <i>i </i>-nary element of the <code>Pattern</code>.
167      * 
168      * @param i
169      *            the index of the desired element
170      * @return the value of the element
171      */
172     public double getComponent(int i) {
173         return elements[i];
174     }
175 
176     /***
177      * Calculates the inner product of two <code>Pattern</code>s.
178      * 
179      * @param operand
180      *            the <code>Pattern</code> to be used in calculation
181      * @return the inner product
182      */
183     public double innerProduct(Pattern operand) {
184         checkEqualSize(operand);
185         double res = 0;
186         for (int i = 0; i < size(); i++) {
187             res += elements[i] * operand.elements[i];
188         }
189         return res;
190     }
191 
192     /***
193      * Scalar multipication.
194      * 
195      * @param operand
196      *            the amount to multiply
197      * @return the resulting <code>Pattern</code>
198      */
199     public Pattern multiply(double operand) {
200         Pattern res = new Pattern(size());
201 
202         for (int i = 0; i < size(); i++) {
203             res.setComponent(elements[i] * operand, i);
204         }
205 
206         return res;
207     }
208 
209     /***
210      * Calculates a norm1 (sum of absolute values) of the <code>Pattern</code>.
211      * 
212      * @return the norm
213      */
214     public double norm1() {
215         double ret = 0.0;
216         int m = size();
217         for (int j = 0; j < m; j++) {
218             ret += java.lang.Math.abs(getComponent(j));
219         }
220         return ret;
221     }
222 
223     /***
224      * Calculates a norm2 (square root of the sum of the squared values) of the
225      * <code>Pattern</code>.
226      * 
227      * @return the norm
228      */
229     public double norm2() {
230         double ret = 0.0;
231         for (int j = 0; j < size(); j++) {
232             ret += Math.pow(getComponent(j), 2.0);
233         }
234         return Math.sqrt(ret);
235     }
236 
237     /***
238      * Sets all <code>Pattern</code> elements to <code>value</code>.
239      * 
240      * @param value
241      *            the value to set
242      */
243     public void setAllComponents(double value) {
244         for (int i = 0; i < size(); i++) {
245             elements[i] = value;
246         }
247     }
248 
249     /***
250      * Sets element of index <code>i</code> to <code>value</code>.
251      * 
252      * @param value
253      *            the value to set
254      * @param i
255      *            index of the element to set
256      * @throws IndexOutOfBoundsException
257      */
258     public void setComponent(double value, int i) {
259         elements[i] = value;
260     }
261 
262     /***
263      * Sets elements to the ones of <code>orig</code>.
264      * 
265      * @param orig
266      *            the <code>Pattern</code> with the elements to set
267      */
268     public void setComponents(Pattern orig) {
269         checkEqualSize(orig);
270         for (int i = 0; i < size(); i++) {
271             elements[i] = orig.getComponent(i);
272         }
273     }
274 
275     /***
276      * 
277      * @return the elements count of this <code>Pattern</code>
278      */
279     public int size() {
280         return elements.length;
281     }
282 
283     public String toString() {
284         String res = "[";
285         for (int i = 0; i < elements.length; i++) {
286             res = res + String.valueOf(elements[i]) + ELEMENT_SEPARATOR;
287         }
288         return res.trim() + "]";
289     }
290 
291     /***
292      * Parses a String into a <code>Pattern</code>. Elements are separated by
293      * <code>Pattern.ELEMENT_SEPARATOR</code>
294      * 
295      * @param str
296      *            the String to parse
297      * @return the resulting <code>Pattern</code>
298      * @see Pattern#ELEMENT_SEPARATOR
299      */
300     public static Pattern parsePattern(String str) {
301         StringTokenizer st = new StringTokenizer(str, ELEMENT_SEPARATOR);
302 
303         Pattern res = new Pattern(st.countTokens());
304 
305         int i = 0;
306 
307         while (st.hasMoreElements()) {
308             res.setComponent(Double.parseDouble(st.nextToken()), i);
309             i++;
310         }
311 
312         return res;
313     }
314 
315     /***
316      * Randomizes this <code>Pattern</code> with values bounded by
317      * <code>min</code> and <code>max</code>. It does not initializes the
318      * random number generator.
319      * 
320      * @param min
321      *            lower bound
322      * @param max
323      *            higher bound
324      */
325     public void randomize(double min, double max) {
326         Random src = new Random(System.currentTimeMillis() + Runtime.getRuntime().freeMemory());
327         for (int i = 0; i < size(); i++) {
328             elements[i] = src.nextDouble() * (max - min) + min;
329         }
330     }
331 
332     public Pattern substract(Pattern operand) {
333         return add(operand.multiply(-1));
334     }
335 
336 }