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 }