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í (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 }