change inputs random10000_12
[IRC.git] / Robust / src / Benchmarks / Prefetch / KMeans / KMeans.java
1 /* =============================================================================
2  *
3  * kmeans.java
4  *
5  * =============================================================================
6  *
7  * Description:
8  *
9  * Takes as input a file:
10  *   ascii  file: containing 1 data point per line
11  *   binary file: first int is the number of objects
12  *                2nd int is the no. of features of each object
13  *
14  * This example performs a fuzzy c-means clustering on the data. Fuzzy clustering
15  * is performed using min to max clusters and the clustering that gets the best
16  * score according to a compactness and separation criterion are returned.
17  *
18  *
19  * Author:
20  *
21  * Wei-keng Liao
22  * ECE Department Northwestern University
23  * email: wkliao@ece.northwestern.edu
24  *
25  *
26  * Edited by:
27  *
28  * Jay Pisharath
29  * Northwestern University
30  *
31  * Chi Cao Minh
32  * Stanford University
33  *
34  * Port to Java version
35  * Alokika Dash
36  * University of California, Irvine
37  *
38  * =============================================================================
39  *
40  * ------------------------------------------------------------------------
41  * 
42  * For the license of kmeans, please see kmeans/LICENSE.kmeans
43  * 
44  * ------------------------------------------------------------------------
45  * 
46  * Unless otherwise noted, the following license applies to STAMP files:
47  * 
48  * Copyright (c) 2007, Stanford University
49  * All rights reserved.
50  * 
51  * Redistribution and use in source and binary forms, with or without
52  * modification, are permitted provided that the following conditions are
53  * met:
54  * 
55  *     * Redistributions of source code must retain the above copyright
56  *       notice, this list of conditions and the following disclaimer.
57  * 
58  *     * Redistributions in binary form must reproduce the above copyright
59  *       notice, this list of conditions and the following disclaimer in
60  *       the documentation and/or other materials provided with the
61  *       distribution.
62  * 
63  *     * Neither the name of Stanford University nor the names of its
64  *       contributors may be used to endorse or promote products derived
65  *       from this software without specific prior written permission.
66  * 
67  * THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY
68  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
69  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
70  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE
71  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
72  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
73  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
74  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
75  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
76  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
77  * THE POSSIBILITY OF SUCH DAMAGE.
78  *
79  * =============================================================================
80  */
81
82 public class KMeans extends Thread {
83   /**
84    * User input for max clusters
85    **/
86   int max_nclusters;
87
88   /**
89    * User input for min clusters
90    **/
91   int min_nclusters;
92
93   /**
94    * Check for Binary file
95    **/
96   int isBinaryFile;
97
98   /**
99    * Using zscore transformation for cluster center 
100    * deviating from distribution's mean
101    **/
102   int use_zscore_transform;
103
104   /**
105    * Input file name used for clustering
106    **/
107   String filename;
108
109   /**
110    * Total number of threads
111    **/
112   int nthreads;
113
114   /**
115    * threshold until which kmeans cluster continues
116    **/
117   float threshold;
118
119   /**
120    * thread id
121    **/
122   int threadid;
123
124   /**
125    * Global arguments for threads 
126    **/
127   GlobalArgs g_args;
128
129   /**
130    * Output:  Number of best clusters
131    **/
132   int best_nclusters;
133
134   /**
135    * Output: Cluster centers
136    **/
137   float[][] cluster_centres;
138
139   /**
140    *
141    **/
142   float[][] attributes;
143
144   int numObjects;
145
146   int numAttributes;
147
148   public KMeans() {
149     max_nclusters = 13;
150     min_nclusters = 4;
151     isBinaryFile = 0;
152     use_zscore_transform = 1;
153     threshold = (float) 0.001;
154     best_nclusters = 0;
155   }
156
157   /*
158   public KMeans(int threadid, GlobalArgs g_args) {
159     this.threadid = threadid;
160     this.g_args = g_args;
161   }
162   */
163
164   public KMeans(int threadid, GlobalArgs g_args, int nthreads, int use_zscore_transform, 
165       int max_nclusters, int min_nclusters, float threshold,
166       float[][] attributes, int numObjects, int numAttributes) {
167     this.threadid = threadid;
168     this.g_args = g_args;
169     //this.nthreads = nthreads;
170     //this.use_zscore_transform = use_zscore_transform;
171     //this.max_nclusters = max_nclusters;
172     //this.min_nclusters = min_nclusters;
173     //this.threshold = threshold;
174     //this.attributes = attributes;
175     //this.numObjects = numObjects;
176     //this.numAttributes = numAttributes;
177   }
178
179   public void run() {
180     Barrier barr = new Barrier("128.195.136.162");
181     while(true) {
182       Barrier.enterBarrier(barr);
183       atomic {
184         Normal.work(threadid, g_args);
185       }
186       Barrier.enterBarrier(barr);
187     }
188   }
189
190   /* =============================================================================
191    * main
192    * =============================================================================
193    */
194   public static void main(String[] args) {
195     int nthreads;
196     int MAX_LINE_LENGTH = 1000000; /* max input is 400000 one digit input + spaces */
197     int[] mid = new int[8];
198     mid[0] = (128<<24)|(195<<16)|(136<<8)|162; //dc-1.calit2
199     mid[1] = (128<<24)|(195<<16)|(136<<8)|163; //dc-2.calit2
200     mid[2] = (128<<24)|(195<<16)|(136<<8)|164; //dc-3.calit2
201     mid[3] = (128<<24)|(195<<16)|(136<<8)|165; //dc-4.calit2
202     mid[4] = (128<<24)|(195<<16)|(136<<8)|166; //dc-5.calit2
203     mid[5] = (128<<24)|(195<<16)|(136<<8)|167; //dc-6.calit2
204     mid[6] = (128<<24)|(195<<16)|(136<<8)|168; //dc-7.calit2
205     mid[7] = (128<<24)|(195<<16)|(136<<8)|169; //dc-8.calit2
206
207
208     /**
209      * Read options fron the command prompt 
210      **/
211     KMeans kms;
212     kms = new KMeans();
213     KMeans.parseCmdLine(args, kms);
214     nthreads = kms.nthreads;
215     System.out.println("nthreads= " + kms.nthreads);
216
217     /* Initiate Barriers */
218     BarrierServer mybarr;
219
220     atomic {
221       mybarr = global new BarrierServer(nthreads);
222     }
223     mybarr.start(mid[0]);
224
225
226     if (kms.max_nclusters < kms.min_nclusters) {
227       System.out.println("Error: max_clusters must be >= min_clusters\n");
228       System.exit(0);
229     }
230     
231     float[][] buf;
232     float[][] attributes;
233     int numAttributes = 0;
234     int numObjects = 0;
235
236     /*
237      * From the input file, get the numAttributes (columns in txt file) and numObjects (rows in txt file)
238      */
239     if (kms.isBinaryFile == 1) {
240       System.out.println("TODO: Unimplemented Binary file option\n");
241       System.exit(0);
242     }
243
244     FileInputStream inputFile = new FileInputStream(kms.filename);
245     byte b[] = new byte[MAX_LINE_LENGTH];
246     int n;
247     while ((n = inputFile.read(b)) != 0) {
248       for (int i = 0; i < n; i++) {
249         if (b[i] == '\n')
250           numObjects++;
251       }
252     }
253     inputFile.close();
254     inputFile = new FileInputStream(kms.filename);
255     String line = null;
256     if((line = inputFile.readLine()) != null) {
257       int index = 0;
258       boolean prevWhiteSpace = true;
259       while(index < line.length()) {
260         char c = line.charAt(index++);
261         boolean currWhiteSpace = Character.isWhitespace(c);
262         if(prevWhiteSpace && !currWhiteSpace){
263           numAttributes++;
264         }   
265         prevWhiteSpace = currWhiteSpace;
266       }   
267     }   
268     inputFile.close();
269
270     /* Ignore the first attribute: numAttributes = 1; */
271     numAttributes = numAttributes - 1; 
272
273     /* Allocate new shared objects and read attributes of all objects */
274     float[][] tmp_buf;
275     atomic {
276       buf = global new float[numObjects][numAttributes];
277       attributes = global new float[numObjects][numAttributes];
278       tmp_buf = buf;
279     }
280     KMeans.readFromFile(inputFile, kms.filename, tmp_buf, MAX_LINE_LENGTH);
281     System.out.println("Finished Reading from file ......");
282
283     /*
284      * The core of the clustering
285      */
286
287     int len = kms.max_nclusters - kms.min_nclusters + 1;
288
289     int nloops = 1;
290
291     KMeans[] km;
292     GlobalArgs g_args;
293     atomic {
294       km = global new KMeans[nthreads];
295       g_args = global new GlobalArgs();
296       g_args.nthreads = nthreads;
297       for(int x = 0; x < numObjects; x++) {
298         for(int y = 0; y < numAttributes; y++) {
299           attributes[x][y] = buf[x][y];
300         }
301       }
302     }
303
304     atomic {
305       /* Create and Start Threads */
306       for(int i = 1; i<nthreads; i++) {
307         km[i] = global new KMeans(i, g_args, nthreads, kms.use_zscore_transform, 
308             kms.max_nclusters, kms.min_nclusters, kms.threshold, attributes, numObjects, numAttributes);
309       }
310     }
311
312     KMeans tmp;
313
314     boolean waitfordone=true;
315     while(waitfordone) {
316       atomic {
317         if (mybarr.done)
318           waitfordone=false;
319       }
320     }
321
322     for(int i = 1; i<nthreads; i++) {
323       atomic {
324         tmp = km[i];
325       }
326       tmp.start(mid[i]);
327     }
328
329     System.out.println("Finished Starting threads......");
330
331     for (int i = 0; i < nloops; i++) {
332       //
333       // Since zscore transform may perform in cluster() which modifies the
334       // contents of attributes[][], we need to re-store the originals
335       //
336       float[][] tmp_attributes;
337       GlobalArgs tmp_g_args;
338       atomic {
339         for(int x = 0; x < numObjects; x++) {
340           for(int y = 0; y < numAttributes; y++) {
341             attributes[x][y] = buf[x][y];
342           }
343         }
344         tmp_attributes = attributes;
345         tmp_g_args = g_args;
346       }
347
348
349       Cluster.cluster_exec(nthreads,
350           numObjects,
351           numAttributes,
352           tmp_attributes,             // [numObjects][numAttributes] 
353           kms,                    //main class that holds users inputs from command prompt and output arrays that need to be filled
354           tmp_g_args);                // Global arguments common to all threads
355     }
356
357     System.out.println("Printing output......");
358     System.out.println("Best_nclusters= " + kms.best_nclusters);
359
360     /* Output: the coordinates of the cluster centres */
361     
362     /*
363     {
364       for (int i = 0; i < kms.best_nclusters; i++) {
365         System.out.print(i + " ");
366         for (int j = 0; j < numAttributes; j++) {
367           System.out.print(kms.cluster_centres[i][j] + " ");
368         }
369         System.out.println("\n");
370       }
371     }
372     */
373
374     System.out.println("Finished......\n");
375     System.exit(0);
376   }
377
378   public static void parseCmdLine(String args[], KMeans km) {
379     int i = 0;
380     String arg;
381     while (i < args.length && args[i].startsWith("-")) {
382       arg = args[i++];
383       //check options
384       if(arg.equals("-m")) {
385         if(i < args.length) {
386           km.max_nclusters = new Integer(args[i++]).intValue();
387         }
388       } else if(arg.equals("-n")) {
389         if(i < args.length) {
390           km.min_nclusters = new Integer(args[i++]).intValue();
391         }
392       } else if(arg.equals("-t")) {
393         if(i < args.length) {
394           km.threshold = new Integer(args[i++]).intValue();
395         }
396       } else if(arg.equals("-i")) {
397         if(i < args.length) {
398           km.filename = args[i++];
399         }
400       } else if(arg.equals("-b")) {
401         if(i < args.length) {
402           km.isBinaryFile = new Integer(args[i++]).intValue();
403         }
404       } else if(arg.equals("-z")) {
405         if(i < args.length) {
406
407         }
408       } else if(arg.equals("-nthreads")) {
409         if(i < args.length) {
410           km.nthreads = new Integer(args[i++]).intValue();
411         }
412       } else if(arg.equals("-h")) {
413         km.usage();
414       }
415     }
416     if(km.nthreads == 0 || km.filename == null) {
417       km.usage();
418     }
419   }
420
421   /**
422    * The usage routine which describes the program options.
423    **/
424   public void usage() {
425     System.out.println("usage: ./kmeans -m <max_clusters> -n <min_clusters> -t <threshold> -i <filename> -nthreads <threads>\n");
426     System.out.println(                   "  -i filename:     file containing data to be clustered\n");
427     System.out.println(                   "  -b               input file is in binary format\n");
428     System.out.println(                   "  -m max_clusters: maximum number of clusters allowed\n");
429     System.out.println(                   "  -n min_clusters: minimum number of clusters allowed\n");
430     System.out.println(                   "  -z             : don't zscore transform data\n");
431     System.out.println(                   "  -t threshold   : threshold value\n");
432     System.out.println(                   "  -nthreads      : number of threads\n");
433   }
434
435   /**
436    * readFromFile()
437    * Read attributes from the input file into an array
438    **/
439   public static void readFromFile(FileInputStream inputFile, String filename, float[][] buf, int MAX_LINE_LENGTH) {
440     inputFile = new FileInputStream(filename);
441     int j;
442     int i = 0;
443
444     byte b[] = new byte[MAX_LINE_LENGTH];
445     int n;
446     byte oldbytes[]=null;
447
448
449     atomic { //FIXME: temporary fix  Note that this 
450       // transaction will never abort because it is only executed
451       // on master machine and therefore the fileread native call is
452       //allowed as a warning
453       while ((n = inputFile.read(b)) != 0) {
454         j = -1;
455         int x=0;
456
457         if (oldbytes!=null) {
458           //find space
459           for (;x < n; x++) {
460             if (b[x] == ' ')
461               break;
462           }
463           byte newbytes[]= new byte[x+oldbytes.length];
464           for(int ii=0;ii<oldbytes.length;ii++)
465             newbytes[ii]=oldbytes[ii];
466           for(int ii=0;ii<x;ii++)
467             newbytes[ii+oldbytes.length]=b[ii];
468           x++; //skip past space
469           if (j>=0) {
470             buf[i][j]=(float)Double.parseDouble(new String(newbytes, 0, newbytes.length));
471           }
472           j++;
473           oldbytes=null;
474         }
475
476         while (x < n) {
477           int y=x;
478           for(y=x;y<n;y++) {
479             if (b[y]==' ')
480               break;
481             if (b[y]=='\n') {
482               i++;
483               j = -1;
484               x=y;//push end to current character
485             }
486           }
487           if (y==n) {
488             //need to continue for another read
489             oldbytes=new byte[y-x];
490             for(int ii=0;ii<(y-x);ii++)
491               oldbytes[ii]=b[ii+x];
492             break;
493           }
494
495           //otherwise x is beginning of character string, y is end
496           if (j>=0) {
497             buf[i][j]=(float)Double.parseDouble(new String(b,x,y-x));
498           }
499           x=y;//skip to end of number
500           x++;//skip past space
501           j++;
502         }
503       }
504     }
505     inputFile.close();
506   }
507 }
508
509 /* =============================================================================
510  *
511  * End of kmeans.java
512  *
513  * =============================================================================
514  */