source: trunk/gsdl/packages/kea/kea-3.0/weka/core/Utils.java@ 8815

Last change on this file since 8815 was 8815, checked in by mdewsnip, 19 years ago

Kea 3.0, as downloaded from http://www.nzdl.org/kea but with CSTR_abstracts_test, CSTR_abstracts_train, Chinese_test, and Chinese_train directories removed.

  • Property svn:keywords set to Author Date Id Revision
File size: 38.9 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 * Utils.java
19 * Copyright (C) 1999 Eibe Frank,Len Trigg,Yong Wang
20 *
21 */
22
23package weka.core;
24
25import java.lang.Math;
26import java.util.StringTokenizer;
27import java.util.Properties;
28import java.io.File;
29import java.io.FileInputStream;
30
31/**
32 * Class implementing some simple utility methods.
33 *
34 * @author Eibe Frank ([email protected])
35 * @author Yong Wang ([email protected])
36 * @author Len Trigg ([email protected])
37 * @version $Revision: 8815 $
38 */
39public final class Utils {
40
41 /** The natural logarithm of 2. */
42 public static double log2 = Math.log(2);
43
44 /** The small deviation allowed in double comparisons */
45 public static double SMALL = 1e-6;
46
47
48 /**
49 * Reads properties that inherit from three locations. Properties
50 * are first defined in the system resource location (i.e. in the
51 * CLASSPATH). These default properties must exist. Properties
52 * defined in the users home directory (optional) override default
53 * settings. Properties defined in the current directory (optional)
54 * override all these settings.
55 *
56 * @param resourceName the location of the resource that should be
57 * loaded. e.g.: "weka/core/Utils.props". (The use of hardcoded
58 * forward slashes here is OK - see
59 * jdk1.1/docs/guide/misc/resources.html) This routine will also
60 * look for the file (in this case) "Utils.props" in the users home
61 * directory and the current directory.
62 * @return the Properties
63 * @exception Exception if no default properties are defined, or if
64 * an error occurs reading the properties files.
65 */
66 public static Properties readProperties(String resourceName)
67 throws Exception{
68
69 Properties defaultProps = new Properties();
70 try {
71 // Apparently hardcoded slashes are OK here
72 // jdk1.1/docs/guide/misc/resources.html
73 defaultProps.load(ClassLoader.getSystemResourceAsStream(resourceName));
74 } catch (Exception ex) {
75/* throw new Exception("Problem reading default properties: "
76 + ex.getMessage()); */
77 System.err.println("Warning, unable to load properties file from "
78 +"system resource (Utils.java)");
79 }
80
81 // Hardcoded slash is OK here
82 // eg: see jdk1.1/docs/guide/misc/resources.html
83 int slInd = resourceName.lastIndexOf('/');
84 if (slInd != -1) {
85 resourceName = resourceName.substring(slInd + 1);
86 }
87
88 // Allow a properties file in the home directory to override
89 Properties userProps = new Properties(defaultProps);
90 File propFile = new File(System.getProperties().getProperty("user.home")
91 + File.separatorChar
92 + resourceName);
93 if (propFile.exists()) {
94 try {
95 userProps.load(new FileInputStream(propFile));
96 } catch (Exception ex) {
97 throw new Exception("Problem reading user properties: " + propFile);
98 }
99 }
100
101 // Allow a properties file in the current directory to override
102 Properties localProps = new Properties(userProps);
103 propFile = new File(resourceName);
104 if (propFile.exists()) {
105 try {
106 localProps.load(new FileInputStream(propFile));
107 } catch (Exception ex) {
108 throw new Exception("Problem reading local properties: " + propFile);
109 }
110 }
111
112 return localProps;
113 }
114
115 /**
116 * Returns the correlation coefficient of two double vectors.
117 *
118 * @param y1 double vector 1
119 * @param y2 double vector 2
120 * @param n the length of two double vectors
121 * @return the correlation coefficient
122 */
123 public final static double correlation(double y1[],double y2[],int n) {
124
125 int i;
126 double av1 = 0.0, av2 = 0.0, y11 = 0.0, y22 = 0.0, y12 = 0.0, c;
127
128 if (n <= 1) {
129 return 1.0;
130 }
131 for (i = 0; i < n; i++) {
132 av1 += y1[i];
133 av2 += y2[i];
134 }
135 av1 /= (double) n;
136 av2 /= (double) n;
137 for (i = 0; i < n; i++) {
138 y11 += (y1[i] - av1) * (y1[i] - av1);
139 y22 += (y2[i] - av2) * (y2[i] - av2);
140 y12 += (y1[i] - av1) * (y2[i] - av2);
141 }
142 if (y11 * y22 == 0.0) {
143 c=1.0;
144 } else {
145 c = y12 / Math.sqrt(Math.abs(y11 * y22));
146 }
147
148 return c;
149 }
150
151 /**
152 * Removes all occurrences of a string from another string.
153 *
154 * @param inString the string to remove substrings from.
155 * @param substring the substring to remove.
156 * @return the input string with occurrences of substring removed.
157 */
158 public static String removeSubstring(String inString, String substring) {
159
160 StringBuffer result = new StringBuffer();
161 int oldLoc = 0, loc = 0;
162 while ((loc = inString.indexOf(substring, oldLoc))!= -1) {
163 result.append(inString.substring(oldLoc, loc));
164 oldLoc = loc + substring.length();
165 }
166 result.append(inString.substring(oldLoc));
167 return result.toString();
168 }
169
170 /**
171 * Replaces with a new string, all occurrences of a string from
172 * another string.
173 *
174 * @param inString the string to replace substrings in.
175 * @param substring the substring to replace.
176 * @param replaceString the replacement substring
177 * @return the input string with occurrences of substring replaced.
178 */
179 public static String replaceSubstring(String inString, String subString,
180 String replaceString) {
181
182 StringBuffer result = new StringBuffer();
183 int oldLoc = 0, loc = 0;
184 while ((loc = inString.indexOf(subString, oldLoc))!= -1) {
185 result.append(inString.substring(oldLoc, loc));
186 result.append(replaceString);
187 oldLoc = loc + subString.length();
188 }
189 result.append(inString.substring(oldLoc));
190 return result.toString();
191 }
192
193
194 /**
195 * Pads a string to a specified length, inserting spaces on the left
196 * as required. If the string is too long, characters are removed (from
197 * the right).
198 *
199 * @param inString the input string
200 * @param length the desired length of the output string
201 * @return the output string
202 */
203 public static String padLeft(String inString, int length) {
204
205 return fixStringLength(inString, length, false);
206 }
207
208 /**
209 * Pads a string to a specified length, inserting spaces on the right
210 * as required. If the string is too long, characters are removed (from
211 * the right).
212 *
213 * @param inString the input string
214 * @param length the desired length of the output string
215 * @return the output string
216 */
217 public static String padRight(String inString, int length) {
218
219 return fixStringLength(inString, length, true);
220 }
221
222 /**
223 * Pads a string to a specified length, inserting spaces as
224 * required. If the string is too long, characters are removed (from
225 * the right).
226 *
227 * @param inString the input string
228 * @param length the desired length of the output string
229 * @param right true if inserted spaces should be added to the right
230 * @return the output string
231 */
232 private static String fixStringLength(String inString, int length,
233 boolean right) {
234
235 if (inString.length() < length) {
236 while (inString.length() < length) {
237 inString = (right ? inString.concat(" ") : " ".concat(inString));
238 }
239 } else if (inString.length() > length) {
240 inString = inString.substring(0, length);
241 }
242 return inString;
243 }
244
245 /**
246 * Rounds a double and converts it into String.
247 *
248 * @param value the double value
249 * @param afterDecimalPoint the (maximum) number of digits permitted
250 * after the decimal point
251 * @return the double as a formatted string
252 */
253 public static String doubleToString(double value, int afterDecimalPoint) {
254
255 StringBuffer stringBuffer;
256 double temp;
257 int i,dotPosition;
258 long precisionValue;
259
260 temp = value * Math.pow(10.0, afterDecimalPoint);
261 if (Math.abs(temp) < Long.MAX_VALUE) {
262 precisionValue = (temp > 0) ? (long)(temp + 0.5)
263 : -(long)(Math.abs(temp) + 0.5);
264 if (precisionValue == 0) {
265 stringBuffer = new StringBuffer(String.valueOf(0));
266 } else {
267 stringBuffer = new StringBuffer(String.valueOf(precisionValue));
268 }
269 if (afterDecimalPoint == 0) {
270 return stringBuffer.toString();
271 }
272 dotPosition = stringBuffer.length() - afterDecimalPoint;
273 while (((precisionValue < 0) && (dotPosition < 1)) ||
274 (dotPosition < 0)) {
275 if (precisionValue < 0) {
276 stringBuffer.insert(1, 0);
277 } else {
278 stringBuffer.insert(0, 0);
279 }
280 dotPosition++;
281 }
282 stringBuffer.insert(dotPosition, '.');
283 if ((precisionValue < 0) && (stringBuffer.charAt(1) == '.')) {
284 stringBuffer.insert(1, 0);
285 } else if (stringBuffer.charAt(0) == '.') {
286 stringBuffer.insert(0, 0);
287 }
288 int currentPos = stringBuffer.length() - 1;
289 while ((currentPos > dotPosition) &&
290 (stringBuffer.charAt(currentPos) == '0')) {
291 stringBuffer.setCharAt(currentPos--, ' ');
292 }
293 if (stringBuffer.charAt(currentPos) == '.') {
294 stringBuffer.setCharAt(currentPos, ' ');
295 }
296
297 return stringBuffer.toString().trim();
298 }
299 return new String("" + value);
300 }
301
302 /**
303 * Rounds a double and converts it into a formatted decimal-justified String.
304 * Trailing 0's are replaced with spaces.
305 *
306 * @param value the double value
307 * @param width the width of the string
308 * @param afterDecimalPoint the number of digits after the decimal point
309 * @return the double as a formatted string
310 */
311 public static String doubleToString(double value, int width,
312 int afterDecimalPoint) {
313
314 String tempString = doubleToString(value, afterDecimalPoint);
315 char[] result;
316 int dotPosition;
317
318 if ((afterDecimalPoint >= width)
319 || (tempString.indexOf('E') != -1)) { // Protects sci notation
320 return tempString;
321 }
322
323 // Initialize result
324 result = new char[width];
325 for (int i = 0; i < result.length; i++) {
326 result[i] = ' ';
327 }
328
329 if (afterDecimalPoint > 0) {
330 // Get position of decimal point and insert decimal point
331 dotPosition = tempString.indexOf('.');
332 if (dotPosition == -1) {
333 dotPosition = tempString.length();
334 } else {
335 result[width - afterDecimalPoint - 1] = '.';
336 }
337 } else {
338 dotPosition = tempString.length();
339 }
340
341
342 int offset = width - afterDecimalPoint - dotPosition;
343 if (afterDecimalPoint > 0) {
344 offset--;
345 }
346
347 // Not enough room to decimal align within the supplied width
348 if (offset < 0) {
349 return tempString;
350 }
351
352 // Copy characters before decimal point
353 for (int i = 0; i < dotPosition; i++) {
354 result[offset + i] = tempString.charAt(i);
355 }
356
357 // Copy characters after decimal point
358 for (int i = dotPosition + 1; i < tempString.length(); i++) {
359 result[offset + i] = tempString.charAt(i);
360 }
361
362 return new String(result);
363 }
364
365 /**
366 * Tests if a is equal to b.
367 *
368 * @param a a double
369 * @param b a double
370 */
371 public static boolean eq(double a, double b){
372
373 return (a - b < SMALL) && (b - a < SMALL);
374 }
375
376 /**
377 * Checks if the given array contains any non-empty options.
378 *
379 * @param strings an array of strings
380 * @exception Exception if there are any non-empty options
381 */
382 public static void checkForRemainingOptions(String [] options)
383 throws Exception {
384
385 int illegalOptionsFound = 0;
386 StringBuffer text = new StringBuffer();
387
388 if (options == null) {
389 return;
390 }
391 for (int i = 0; i < options.length; i++) {
392 if (options[i].length() > 0) {
393 illegalOptionsFound++;
394 text.append(options[i] + ' ');
395 }
396 }
397 if (illegalOptionsFound > 0) {
398 throw new Exception("Illegal options: " + text);
399 }
400 }
401
402 /**
403 * Checks if the given array contains the flag "-Char". Stops
404 * searching at the first marker "--". If the flag is found,
405 * it is replaced with the empty string.
406 *
407 * @param flag the character indicating the flag.
408 * @param strings the array of strings containing all the options.
409 * @return true if the flag was found
410 * @exception Exception if an illegal option was found
411 */
412
413 public static boolean getFlag(char flag, String [] options)
414 throws Exception {
415
416 if (options == null) {
417 return false;
418 }
419 for (int i = 0; i < options.length; i++) {
420 if ((options[i].length() > 1) && (options[i].charAt(0) == '-')) {
421 try {
422 Double dummy = Double.valueOf(options[i]);
423 } catch (NumberFormatException e) {
424 if (options[i].length() > 2) {
425 throw new Exception("Illegal option: " + options[i]);
426 }
427 if (options[i].charAt(1) == flag) {
428 options[i] = "";
429 return true;
430 }
431 if (options[i].charAt(1) == '-') {
432 return false;
433 }
434 }
435 }
436 }
437 return false;
438 }
439
440 /**
441 * Gets an option indicated by a flag "-Char" from the given array
442 * of strings. Stops searching at the first marker "--". Replaces
443 * flag and option with empty strings.
444 *
445 * @param flag the character indicating the option.
446 * @param options the array of strings containing all the options.
447 * @return the indicated option or an empty string
448 * @exception Exception if the option indicated by the flag can't be found
449 */
450 public static String getOption(char flag, String [] options)
451 throws Exception {
452
453 String newString;
454
455 if (options == null)
456 return "";
457 for (int i = 0; i < options.length; i++) {
458 if ((options[i].length() > 0) && (options[i].charAt(0) == '-')) {
459
460 // Check if it is a negative number
461 try {
462 Double dummy = Double.valueOf(options[i]);
463 } catch (NumberFormatException e) {
464 if (options[i].length() > 2) {
465 throw new Exception("Illegal option: " + options[i]);
466 }
467 if (options[i].charAt(1) == flag) {
468 if (i + 1 == options.length) {
469 throw new Exception("No value given for -" + flag + " option.");
470 }
471 options[i] = "";
472 newString = new String(options[i + 1]);
473 options[i + 1] = "";
474 return newString;
475 }
476 if (options[i].charAt(1) == '-') {
477 return "";
478 }
479 }
480 }
481 }
482 return "";
483 }
484
485 /**
486 * Quotes a string if it contains special characters.
487 *
488 * The following rules are applied:
489 *
490 * A character is backquoted version of it is one
491 * of <tt>" ' % \ \n \r \t</tt>.
492 *
493 * A string is enclosed within single quotes if a character has been
494 * backquoted using the previous rule above or contains
495 * <tt>{ }</tt> or is exactly equal to the strings
496 * <tt>, ? space or ""</tt> (empty string).
497 *
498 * A quoted question mark distinguishes it from the missing value which
499 * is represented as an unquoted question mark in arff files.
500 *
501 * @param string the string to be quoted
502 * @return the string (possibly quoted)
503 */
504 public static String quote(String string) {
505 boolean quote = false;
506
507 // backquote the following characters
508 if ((string.indexOf('\n') != -1) || (string.indexOf('\r') != -1) ||
509 (string.indexOf('\'') != -1) || (string.indexOf('"') != -1) ||
510 (string.indexOf('\\') != -1) ||
511 (string.indexOf('\t') != -1) || (string.indexOf('%') != -1)) {
512 string = backQuoteChars(string);
513 quote = true;
514 }
515
516 // Enclose the string in 's if the string contains a recently added
517 // backquote or contains one of the following characters.
518 if((quote == true) ||
519 (string.indexOf('{') != -1) || (string.indexOf('}') != -1) ||
520 (string.indexOf(',') != -1) || (string.equals("?")) ||
521 (string.indexOf(' ') != -1) || (string.equals(""))) {
522 string = ("'".concat(string)).concat("'");
523 }
524
525 return string;
526 }
527
528 /**
529 * Converts carriage returns and new lines in a string into \r and \n.
530 * Backquotes the following characters: ` " \ \t and %
531 * @param string the string
532 * @return the converted string
533 */
534 public static String backQuoteChars(String string) {
535
536 int index;
537 StringBuffer newStringBuffer;
538
539 // replace each of the following characters with the backquoted version
540 char charsFind[] = {'\\', '\'', '\t', '"', '%'};
541 String charsReplace[] = {"\\\\", "\\'", "\\t", "\\\"", "\\%"};
542 for(int i = 0; i < charsFind.length; i++) {
543 if (string.indexOf(charsFind[i]) != -1 ) {
544 newStringBuffer = new StringBuffer();
545 while ((index = string.indexOf(charsFind[i])) != -1) {
546 if (index > 0) {
547 newStringBuffer.append(string.substring(0, index));
548 }
549 newStringBuffer.append(charsReplace[i]);
550 if ((index + 1) < string.length()) {
551 string = string.substring(index + 1);
552 } else {
553 string = "";
554 }
555 }
556 newStringBuffer.append(string);
557 string = newStringBuffer.toString();
558 }
559 }
560
561 return Utils.convertNewLines(string);
562 }
563
564 /**
565 * Converts carriage returns and new lines in a string into \r and \n.
566 * @param string the string
567 * @return the converted string
568 */
569 public static String convertNewLines(String string) {
570
571 int index;
572
573 // Replace with \n
574 StringBuffer newStringBuffer = new StringBuffer();
575 while ((index = string.indexOf('\n')) != -1) {
576 if (index > 0) {
577 newStringBuffer.append(string.substring(0, index));
578 }
579 newStringBuffer.append('\\');
580 newStringBuffer.append('n');
581 if ((index + 1) < string.length()) {
582 string = string.substring(index + 1);
583 } else {
584 string = "";
585 }
586 }
587 newStringBuffer.append(string);
588 string = newStringBuffer.toString();
589
590 // Replace with \r
591 newStringBuffer = new StringBuffer();
592 while ((index = string.indexOf('\r')) != -1) {
593 if (index > 0) {
594 newStringBuffer.append(string.substring(0, index));
595 }
596 newStringBuffer.append('\\');
597 newStringBuffer.append('r');
598 if ((index + 1) < string.length()){
599 string = string.substring(index + 1);
600 } else {
601 string = "";
602 }
603 }
604 newStringBuffer.append(string);
605 return newStringBuffer.toString();
606 }
607
608
609 /**
610 * Returns the secondary set of options (if any) contained in
611 * the supplied options array. The secondary set is defined to
612 * be any options after the first "--". These options are removed from
613 * the original options array.
614 *
615 * @param options the input array of options
616 * @return the array of secondary options
617 */
618 public static String [] partitionOptions(String [] options) {
619
620 for (int i = 0; i < options.length; i++) {
621 if (options[i].equals("--")) {
622 options[i++] = "";
623 String [] result = new String [options.length - i];
624 for (int j = i; j < options.length; j++) {
625 result[j - i] = options[j];
626 options[j] = "";
627 }
628 return result;
629 }
630 }
631 return new String [0];
632 }
633
634 /**
635 * Split up a string containing options into an array of strings,
636 * one for each option.
637 *
638 * @param optionString the string containing the options
639 * @return the array of options
640 */
641 public static String [] splitOptions(String optionString) {
642
643 FastVector optionsVec = new FastVector();
644 StringTokenizer st = new StringTokenizer(optionString);
645 while (st.hasMoreTokens())
646 optionsVec.addElement(st.nextToken());
647
648 String [] options = new String[optionsVec.size()];
649 for (int i = 0; i < optionsVec.size(); i++) {
650 options[i] = (String)optionsVec.elementAt(i);
651 }
652 return options;
653 }
654
655 /**
656 * Joins all the options in an option array into a single string,
657 * as might be used on the command line.
658 *
659 * @param optionArray the array of options
660 * @return the string containing all options.
661 */
662 public static String joinOptions(String [] optionArray) {
663
664 String optionString = "";
665 for (int i = 0; i < optionArray.length; i++) {
666 if (optionArray[i].equals("")) {
667 continue;
668 }
669 if (optionArray[i].indexOf(' ') != -1) {
670 optionString += '"' + optionArray[i] + '"';
671 } else {
672 optionString += optionArray[i];
673 }
674 optionString += " ";
675 }
676 return optionString.trim();
677 }
678
679 /**
680 * Creates a new instance of an object given it's class name and
681 * (optional) arguments to pass to it's setOptions method. If the
682 * object implements OptionHandler and the options parameter is
683 * non-null, the object will have it's options set. Example use:<p>
684 *
685 * <code> <pre>
686 * String classifierName = Utils.getOption('W', options);
687 * Classifier c = (Classifier)Utils.forName(Classifier.class,
688 * classifierName,
689 * options);
690 * setClassifier(c);
691 * </pre></code>
692 *
693 * @param classType the class that the instantiated object should
694 * be assignable to -- an exception is thrown if this is not the case
695 * @param className the fully qualified class name of the object
696 * @param options an array of options suitable for passing to setOptions. May
697 * be null. Any options accepted by the object will be removed from the
698 * array.
699 * @return the newly created object, ready for use.
700 * @exception Exception if the class name is invalid, or if the
701 * class is not assignable to the desired class type, or the options
702 * supplied are not acceptable to the object
703 */
704 public static Object forName(Class classType,
705 String className,
706 String [] options) throws Exception {
707
708 Class c = null;
709 try {
710 c = Class.forName(className);
711 } catch (Exception ex) {
712 throw new Exception("Can't find class called: " + className);
713 }
714 if (!classType.isAssignableFrom(c)) {
715 throw new Exception(classType.getName() + " is not assignable from "
716 + className);
717 }
718 Object o = c.newInstance();
719 if ((o instanceof OptionHandler)
720 && (options != null)) {
721 ((OptionHandler)o).setOptions(options);
722 Utils.checkForRemainingOptions(options);
723 }
724 return o;
725 }
726
727 /**
728 * Computes entropy for an array of integers.
729 *
730 * @param counts array of counts
731 * @returns - a log2 a - b log2 b - c log2 c + (a+b+c) log2 (a+b+c)
732 * when given array [a b c]
733 */
734 public static double info(int counts[]) {
735
736 int total = 0; int c;
737 double x = 0;
738 for (int j = 0; j < counts.length; j++) {
739 x -= xlogx(counts[j]);
740 total += counts[j];
741 }
742 return x + xlogx(total);
743 }
744
745 /**
746 * Tests if a is smaller or equal to b.
747 *
748 * @param a a double
749 * @param b a double
750 */
751 public static boolean smOrEq(double a,double b) {
752
753 return (a-b < SMALL);
754 }
755
756 /**
757 * Tests if a is greater or equal to b.
758 *
759 * @param a a double
760 * @param b a double
761 */
762 public static boolean grOrEq(double a,double b) {
763
764 return (b-a < SMALL);
765 }
766
767 /**
768 * Tests if a is smaller than b.
769 *
770 * @param a a double
771 * @param b a double
772 */
773 public static boolean sm(double a,double b) {
774
775 return (b-a > SMALL);
776 }
777
778 /**
779 * Tests if a is smaller than b.
780 *
781 * @param a a double
782 * @param b a double
783 */
784 public static boolean gr(double a,double b) {
785
786 return (a-b > SMALL);
787 }
788
789 /**
790 * Returns the logarithm of a for base 2.
791 *
792 * @param a a double
793 */
794 public static double log2(double a) {
795
796 return Math.log(a) / log2;
797 }
798
799 /**
800 * Returns index of maximum element in a given
801 * array of doubles. First maximum is returned.
802 *
803 * @param doubles the array of doubles
804 * @return the index of the maximum element
805 */
806 public static int maxIndex(double [] doubles) {
807
808 double maximum = 0;
809 int maxIndex = 0;
810
811 for (int i = 0; i < doubles.length; i++) {
812 if ((i == 0) || (doubles[i] > maximum)) {
813 maxIndex = i;
814 maximum = doubles[i];
815 }
816 }
817
818 return maxIndex;
819 }
820
821 /**
822 * Returns index of maximum element in a given
823 * array of integers. First maximum is returned.
824 *
825 * @param ints the array of integers
826 * @return the index of the maximum element
827 */
828 public static int maxIndex(int [] ints) {
829
830 int maximum = 0;
831 int maxIndex = 0;
832
833 for (int i = 0; i < ints.length; i++) {
834 if ((i == 0) || (ints[i] > maximum)) {
835 maxIndex = i;
836 maximum = ints[i];
837 }
838 }
839
840 return maxIndex;
841 }
842
843 /**
844 * Computes the mean for an array of doubles.
845 *
846 * @param vector the array
847 * @return the mean
848 */
849 public static double mean(double[] vector) {
850
851 double sum = 0;
852
853 if (vector.length == 0) {
854 return 0;
855 }
856 for (int i = 0; i < vector.length; i++) {
857 sum += vector[i];
858 }
859 return sum / (double) vector.length;
860 }
861
862 /**
863 * Returns index of minimum element in a given
864 * array of integers. First minimum is returned.
865 *
866 * @param ints the array of integers
867 * @return the index of the minimum element
868 */
869 public static int minIndex(int [] ints) {
870
871 int minimum = 0;
872 int minIndex = 0;
873
874 for (int i = 0; i < ints.length; i++) {
875 if ((i == 0) || (ints[i] < minimum)) {
876 minIndex = i;
877 minimum = ints[i];
878 }
879 }
880
881 return minIndex;
882 }
883
884 /**
885 * Returns index of minimum element in a given
886 * array of doubles. First minimum is returned.
887 *
888 * @param doubles the array of doubles
889 * @return the index of the minimum element
890 */
891 public static int minIndex(double [] doubles) {
892
893 double minimum = 0;
894 int minIndex = 0;
895
896 for (int i = 0; i < doubles.length; i++) {
897 if ((i == 0) || (doubles[i] < minimum)) {
898 minIndex = i;
899 minimum = doubles[i];
900 }
901 }
902
903 return minIndex;
904 }
905
906 /**
907 * Normalizes the doubles in the array by their sum.
908 *
909 * @param doubles the array of double
910 * @exception IllegalArgumentException if sum is Zero or NaN
911 */
912 public static void normalize(double[] doubles) {
913
914 double sum = 0;
915 for (int i = 0; i < doubles.length; i++) {
916 sum += doubles[i];
917 }
918 normalize(doubles, sum);
919 }
920
921 /**
922 * Normalizes the doubles in the array using the given value.
923 *
924 * @param doubles the array of double
925 * @param sum the value by which the doubles are to be normalized
926 * @exception IllegalArgumentException if sum is zero or NaN
927 */
928 public static void normalize(double[] doubles, double sum) {
929
930 if (Double.isNaN(sum)) {
931 throw new IllegalArgumentException("Can't normalize array. Sum is NaN.");
932 }
933 if (sum == 0) {
934 // Maybe this should just be a return.
935 throw new IllegalArgumentException("Can't normalize array. Sum is zero.");
936 }
937 for (int i = 0; i < doubles.length; i++) {
938 doubles[i] /= sum;
939 }
940 }
941
942 /**
943 * Rounds a double to the next nearest integer value. The JDK version
944 * of it doesn't work properly.
945 *
946 * @param value the double value
947 * @return the resulting integer value
948 */
949 public static int round(double value) {
950
951 int roundedValue = value > 0
952 ? (int)(value + 0.5)
953 : -(int)(Math.abs(value) + 0.5);
954
955 return roundedValue;
956 }
957
958 /**
959 * Rounds a double to the given number of decimal places.
960 *
961 * @param value the double value
962 * @param afterDecimalPoint the number of digits after the decimal point
963 * @return the double rounded to the given precision
964 */
965 public static double roundDouble(double value,int afterDecimalPoint) {
966
967 double mask = Math.pow(10.0, (double)afterDecimalPoint);
968
969 return (double)(Math.round(value * mask)) / mask;
970 }
971
972 /**
973 * Sorts a given array of integers in ascending order and returns an
974 * array of integers with the positions of the elements of the original
975 * array in the sorted array. The sort is stable. (Equal elements remain
976 * in their original order.)
977 *
978 * @param array this array is not changed by the method!
979 * @return an array of integers with the positions in the sorted
980 * array.
981 */
982 public static int[] sort(int [] array) {
983
984 int [] index = new int[array.length];
985 int [] newIndex = new int[array.length];
986 int [] helpIndex;
987 int numEqual;
988
989 for (int i = 0; i < index.length; i++) {
990 index[i] = i;
991 }
992 quickSort(array, index, 0, array.length - 1);
993
994 // Make sort stable
995 int i = 0;
996 while (i < index.length) {
997 numEqual = 1;
998 for (int j = i + 1; ((j < index.length)
999 && (array[index[i]] == array[index[j]]));
1000 j++) {
1001 numEqual++;
1002 }
1003 if (numEqual > 1) {
1004 helpIndex = new int[numEqual];
1005 for (int j = 0; j < numEqual; j++) {
1006 helpIndex[j] = i + j;
1007 }
1008 quickSort(index, helpIndex, 0, numEqual - 1);
1009 for (int j = 0; j < numEqual; j++) {
1010 newIndex[i + j] = index[helpIndex[j]];
1011 }
1012 i += numEqual;
1013 } else {
1014 newIndex[i] = index[i];
1015 i++;
1016 }
1017 }
1018 return newIndex;
1019 }
1020
1021 /**
1022 * Sorts a given array of doubles in ascending order and returns an
1023 * array of integers with the positions of the elements of the
1024 * original array in the sorted array. NOTE THESE CHANGES: the sort
1025 * is no longer stable and it doesn't use safe floating-point
1026 * comparisons anymore. Occurrences of Double.NaN are treated as
1027 * Double.MAX_VALUE
1028 *
1029 * @param array this array is not changed by the method!
1030 * @return an array of integers with the positions in the sorted
1031 * array.
1032 */
1033 public static int[] sort(double [] array) {
1034
1035 int [] index = new int[array.length];
1036 array = (double [])array.clone();
1037 for (int i = 0; i < index.length; i++) {
1038 index[i] = i;
1039 if (Double.isNaN(array[i])) {
1040 array[i] = Double.MAX_VALUE;
1041 }
1042 }
1043 quickSort(array, index, 0, array.length - 1);
1044 return index;
1045 }
1046
1047 /**
1048 * Sorts a given array of doubles in ascending order and returns an
1049 * array of integers with the positions of the elements of the original
1050 * array in the sorted array. The sort is stable (Equal elements remain
1051 * in their original order.) Occurrences of Double.NaN are treated as
1052 * Double.MAX_VALUE
1053 *
1054 * @param array this array is not changed by the method!
1055 * @return an array of integers with the positions in the sorted
1056 * array.
1057 */
1058 public static int[] stableSort(double [] array){
1059
1060 int [] index = new int[array.length];
1061 int [] newIndex = new int[array.length];
1062 int [] helpIndex;
1063 int numEqual;
1064
1065 array = (double [])array.clone();
1066 for (int i = 0; i < index.length; i++) {
1067 index[i] = i;
1068 if (Double.isNaN(array[i])) {
1069 array[i] = Double.MAX_VALUE;
1070 }
1071 }
1072 quickSort(array,index,0,array.length-1);
1073
1074 // Make sort stable
1075
1076 int i = 0;
1077 while (i < index.length) {
1078 numEqual = 1;
1079 for (int j = i+1; ((j < index.length) && Utils.eq(array[index[i]],
1080 array[index[j]])); j++)
1081 numEqual++;
1082 if (numEqual > 1) {
1083 helpIndex = new int[numEqual];
1084 for (int j = 0; j < numEqual; j++)
1085 helpIndex[j] = i+j;
1086 quickSort(index, helpIndex, 0, numEqual-1);
1087 for (int j = 0; j < numEqual; j++)
1088 newIndex[i+j] = index[helpIndex[j]];
1089 i += numEqual;
1090 } else {
1091 newIndex[i] = index[i];
1092 i++;
1093 }
1094 }
1095
1096 return newIndex;
1097 }
1098
1099 /**
1100 * Computes the variance for an array of doubles.
1101 *
1102 * @param vector the array
1103 * @return the variance
1104 */
1105 public static double variance(double[] vector) {
1106
1107 double sum = 0, sumSquared = 0;
1108
1109 if (vector.length <= 1) {
1110 return 0;
1111 }
1112 for (int i = 0; i < vector.length; i++) {
1113 sum += vector[i];
1114 sumSquared += (vector[i] * vector[i]);
1115 }
1116 return (sumSquared - (sum * sum / (double) vector.length)) /
1117 (double) (vector.length - 1);
1118 }
1119
1120 /**
1121 * Computes the sum of the elements of an array of doubles.
1122 *
1123 * @param doubles the array of double
1124 * @returns the sum of the elements
1125 */
1126 public static double sum(double[] doubles) {
1127
1128 double sum = 0;
1129
1130 for (int i = 0; i < doubles.length; i++) {
1131 sum += doubles[i];
1132 }
1133 return sum;
1134 }
1135
1136 /**
1137 * Computes the sum of the elements of an array of integers.
1138 *
1139 * @param ints the array of integers
1140 * @returns the sum of the elements
1141 */
1142 public static int sum(int[] ints) {
1143
1144 int sum = 0;
1145
1146 for (int i = 0; i < ints.length; i++) {
1147 sum += ints[i];
1148 }
1149 return sum;
1150 }
1151
1152 /**
1153 * Returns c*log2(c) for a given integer value c.
1154 *
1155 * @param c an integer value
1156 * @returns c*log2(c) (but is careful to return 0 if c is 0)
1157 */
1158 public static double xlogx(int c) {
1159
1160 if (c == 0) {
1161 return 0.0;
1162 }
1163 return c * Utils.log2((double) c);
1164 }
1165
1166 /**
1167 * Implements quicksort for an array of indices.
1168 *
1169 * @param array the array of integers to be sorted
1170 * @param index the index which should contain the positions in the
1171 * sorted array
1172 * @param lo0 the first index of the subset to be sorted
1173 * @param hi0 the last index of the subset to be sorted
1174 */
1175 private static void quickSort(int [] array, int [] index,
1176 int lo0, int hi0) {
1177
1178 int lo = lo0;
1179 int hi = hi0;
1180 int mid;
1181 int help;
1182
1183 if (hi0 > lo0) {
1184
1185 // Arbitrarily establishing partition element as the midpoint of
1186 // the array.
1187 mid = array[index[(lo0 + hi0) / 2]];
1188
1189 // loop through the array until indices cross
1190 while (lo <= hi) {
1191
1192 // find the first element that is greater than or equal to
1193 // the partition element starting from the left Index.
1194 while ((array[index[lo]] < mid) && (lo < hi0)) {
1195 ++lo;
1196 }
1197
1198 // find an element that is smaller than or equal to
1199 // the partition element starting from the right Index.
1200 while ((array[index[hi]] > mid) && (hi > lo0)) {
1201 --hi;
1202 }
1203
1204 // if the indexes have not crossed, swap
1205 if (lo <= hi) {
1206 help = index[lo];
1207 index[lo] = index[hi];
1208 index[hi] = help;
1209 ++lo;
1210 --hi;
1211 }
1212 }
1213
1214 // If the right index has not reached the left side of array
1215 // must now sort the left partition.
1216 if (lo0 < hi) {
1217 quickSort(array, index, lo0, hi);
1218 }
1219
1220 // If the left index has not reached the right side of array
1221 // must now sort the right partition.
1222 if (lo < hi0) {
1223 quickSort(array, index, lo, hi0);
1224 }
1225 }
1226 }
1227
1228 /**
1229 * Implements unsafe quicksort for an array of indices.
1230 *
1231 * @param array the array of doubles to be sorted
1232 * @param index the index which should contain the positions in the
1233 * sorted array
1234 * @param lo0 the first index of the subset to be sorted
1235 * @param hi0 the last index of the subset to be sorted
1236 */
1237 private static void quickSort(double [] array, int [] index, int lo0, int hi0) {
1238
1239 int lo = lo0;
1240 int hi = hi0;
1241 double mid;
1242 int help;
1243
1244 if (hi0 > lo0) {
1245
1246 // Arbitrarily establishing partition element as the midpoint of
1247 // the array.
1248 mid = array[index[(lo0 + hi0) / 2]];
1249
1250 // loop through the array until indices cross
1251 while (lo <= hi) {
1252
1253 // find the first element that is greater than or equal to
1254 // the partition element starting from the left Index.
1255 while ((array[index[lo]] < mid) && (lo < hi0)) {
1256 ++lo;
1257 }
1258
1259 // find an element that is smaller than or equal to
1260 // the partition element starting from the right Index.
1261 while ((array[index[hi]] > mid) && (hi > lo0)) {
1262 --hi;
1263 }
1264
1265 // if the indexes have not crossed, swap
1266 if (lo <= hi) {
1267 help = index[lo];
1268 index[lo] = index[hi];
1269 index[hi] = help;
1270 ++lo;
1271 --hi;
1272 }
1273 }
1274
1275 // If the right index has not reached the left side of array
1276 // must now sort the left partition.
1277 if (lo0 < hi) {
1278 quickSort(array, index, lo0, hi);
1279 }
1280
1281 // If the left index has not reached the right side of array
1282 // must now sort the right partition.
1283 if (lo < hi0) {
1284 quickSort(array, index, lo, hi0);
1285 }
1286 }
1287 }
1288
1289 /**
1290 * Main method for testing this class.
1291 *
1292 * @param ops some dummy options
1293 */
1294 public static void main(String[] ops) {
1295
1296 double[] doubles = {4.5, 6.7, Double.NaN, 3.4, 4.8, 1.2, 3.4};
1297 int[] ints = {12, 6, 2, 18, 16, 6, 7, 5};
1298
1299 try {
1300
1301 // Option handling
1302 System.out.println("First option split up:");
1303 if (ops.length > 0) {
1304 String[] firstOptionSplitUp = Utils.splitOptions(ops[0]);
1305 for (int i = 0; i < firstOptionSplitUp.length; i ++) {
1306 System.out.println(firstOptionSplitUp[i]);
1307 }
1308 }
1309 System.out.println("Partitioned options: ");
1310 String[] partitionedOptions = Utils.partitionOptions(ops);
1311 for (int i = 0; i < partitionedOptions.length; i++) {
1312 System.out.println(partitionedOptions[i]);
1313 }
1314 System.out.println("Get flag -f: " + Utils.getFlag('f', ops));
1315 System.out.println("Get option -o: " + Utils.getOption('o', ops));
1316 System.out.println("Checking for remaining options... ");
1317 Utils.checkForRemainingOptions(ops);
1318
1319 // Statistics
1320 System.out.println("Original array (doubles): ");
1321 for (int i = 0; i < doubles.length; i++) {
1322 System.out.print(doubles[i] + " ");
1323 }
1324 System.out.println();
1325 System.out.println("Original array (ints): ");
1326 for (int i = 0; i < ints.length; i++) {
1327 System.out.print(ints[i] + " ");
1328 }
1329 System.out.println();
1330 System.out.println("Correlation: " + Utils.correlation(doubles, doubles,
1331 doubles.length));
1332 System.out.println("Mean: " + Utils.mean(doubles));
1333 System.out.println("Variance: " + Utils.variance(doubles));
1334 System.out.println("Sum (doubles): " + Utils.sum(doubles));
1335 System.out.println("Sum (ints): " + Utils.sum(ints));
1336 System.out.println("Max index (doubles): " + Utils.maxIndex(doubles));
1337 System.out.println("Max index (ints): " + Utils.maxIndex(ints));
1338 System.out.println("Min index (doubles): " + Utils.minIndex(doubles));
1339 System.out.println("Min index (ints): " + Utils.minIndex(ints));
1340
1341 // Sorting and normalizing
1342 System.out.println("Sorted array (doubles): ");
1343 int[] sorted = Utils.sort(doubles);
1344 for (int i = 0; i < doubles.length; i++) {
1345 System.out.print(doubles[sorted[i]] + " ");
1346 }
1347 System.out.println();
1348 System.out.println("Normalized array (doubles): ");
1349 Utils.normalize(doubles);
1350 for (int i = 0; i < doubles.length; i++) {
1351 System.out.print(doubles[i] + " ");
1352 }
1353 System.out.println();
1354 System.out.println("Normalized again (doubles): ");
1355 Utils.normalize(doubles, Utils.sum(doubles));
1356 for (int i = 0; i < doubles.length; i++) {
1357 System.out.print(doubles[i] + " ");
1358 }
1359 System.out.println();
1360
1361 // Pretty-printing
1362 System.out.println("-4.58: " + Utils.doubleToString(-4.57826535, 2));
1363 System.out.println("-6.78: " + Utils.doubleToString(-6.78214234, 6,2));
1364
1365 // Comparisons
1366 System.out.println("5.70001 == 5.7 ? " + Utils.eq(5.70001, 5.7));
1367 System.out.println("5.70001 > 5.7 ? " + Utils.gr(5.70001, 5.7));
1368 System.out.println("5.70001 >= 5.7 ? " + Utils.grOrEq(5.70001, 5.7));
1369 System.out.println("5.7 < 5.70001 ? " + Utils.sm(5.7, 5.70001));
1370 System.out.println("5.7 <= 5.70001 ? " + Utils.smOrEq(5.7, 5.70001));
1371
1372 // Math
1373 System.out.println("Info (ints): " + Utils.info(ints));
1374 System.out.println("log2(4.6): " + Utils.log2(4.6));
1375 System.out.println("5 * log(5): " + Utils.xlogx(5));
1376 System.out.println("5.5 rounded: " + Utils.round(5.5));
1377 System.out.println("5.55555 rounded to 2 decimal places: " +
1378 Utils.roundDouble(5.55555, 2));
1379 } catch (Exception e) {
1380 e.printStackTrace();
1381 }
1382 }
1383}
1384
Note: See TracBrowser for help on using the repository browser.