public int run (String[] args) throws Exception {
		for(int i = 0; i < args.length; i++){
			System.out.println(i + " : " + args[i]);
		}

		if (args.length < 2) {
			System.err.printf("Usage: %s [generic options] <d> <maxDimensions> <dataSets> <key> <input> <input2?> <output> <prevrun?> \n",
					getClass().getSimpleName()); ToolRunner.printGenericCommandUsage(System.err); 
			return -1;
		}

		int d = Integer.parseInt(args[0]);

		boolean is2D = (Integer.parseInt(args[1]) < 3);
		int iter = d;
		if(!is2D) {
			iter = d*d;
		}

		boolean isPaired = (Integer.parseInt(args[2]) == 2);

		iter = 1;
		for(int i = 0; i < iter; i++) {
			System.out.println("Sub-iteration " + i);

			JobConf conf = getJobInstance(i,isPaired);
			FileSystem fs = FileSystem.get(conf);

			conf.setInt("ff.d", d);
			conf.setInt("ff.subepoch", i);

			int outputIndex = 4;
			if(isPaired) {
				MultipleInputs.addInputPath(conf, new Path(args[4]), KeyValueTextInputFormat.class, FFMapper.class);
				MultipleInputs.addInputPath(conf, new Path(args[5]), KeyValueTextInputFormat.class, FFMapperPaired.class);
				outputIndex = 6;
			} else {
				FileInputFormat.addInputPath(conf, new Path(args[4])); 
				outputIndex = 5;
			}
			//FileOutputFormat.setOutputPath(conf, new Path(args[outputIndex] + "/final/"));
			conf.setStrings("ff.outputPath", args[outputIndex]);
			if(args.length > outputIndex + 1) {
				conf.setStrings("ff.prevPath", args[outputIndex+1]);
			}

			RunningJob job = JobClient.runJob(conf);

			//if(i % d == 0) {
			long loss = job.getCounters().findCounter("FF Loss","Loss").getCounter();
			long count = job.getCounters().findCounter("FF Loss","Points").getCounter();
			long updated = job.getCounters().findCounter("FlexiFaCT","Number Passed").getCounter();

			String key = "-" + args[3];

			BufferedWriter lossResults = new BufferedWriter(new FileWriter("loss" + key + ".txt",true)); ;
			//BufferedWriter lossResults = new BufferedWriter(new FileWriter("loss" + key + ".txt",true)); ;
			if(!isPaired) {
				lossResults.write(i + "\t" + (loss/1000.0) + "\t" + count + "\t" + updated + "\t" + ((loss/1000.0)/count)+ "\t" + Math.sqrt( (loss/1000.0)/count ) + "\n");
			} else {
				long loss0= job.getCounters().findCounter("FF Loss","Loss-data0").getCounter();
				long count0= job.getCounters().findCounter("FF Loss","Points-data0").getCounter();
				long loss1= job.getCounters().findCounter("FF Loss","Loss-data1").getCounter();
				long count1= job.getCounters().findCounter("FF Loss","Points-data1").getCounter();
				lossResults.write(i + "\t" + (loss/1000.0) + "\t" + count + "\t" + ( (loss/1000.0)/count )+ "\t" + Math.sqrt( (loss/1000.0)/count ) + "\t" + updated + "\t" + (loss0/1000.0) + "\t" + count0 + "\t" + (loss1/1000.0) + "\t" + count1 + "\n");
			}
			lossResults.close();
			//}
		}	

		return 0;
	}