[Home]Voidious/WaveReader

Robo Home | Voidious | Changes | Preferences | AllPages

The analysis portion of my recent Segmentation Research. This program uses data recorded with WaveRecorder to try and find optimal Segmentation slices for a GuessFactorTargeting bot.

Much of the code is very stringy, but the core methods are pretty clean and efficient. A lot of it is just kind of a sandbox to try this stuff. I may get to cleaning it up later once I'm more familiar with what I want to be doing with it.

--

package voidious.test;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

/** 
 * WaveReader.java
 * 
 * Some GuessFactorTargeting analysis by Voidious.
 *
 * This code is open source, released under the RoboWiki Public Code License:
 * http://robowiki.net/cgi-bin/robowiki?RWPCL
 */

public class WaveReader {
//	public static double _ln2 = Math.log(2);
	public HashMap<String, ArrayList> waveSets;
	public static String baseDir = 
		"/your/data/dir/";

	public WaveReader() {
		waveSets = new HashMap<String, ArrayList>();
	}
	
	public static void main(String[] args) {
		boolean useRatio = false;
		if (args.length > 0) {
			useRatio = true;
		}
		
		WaveReader wr = new WaveReader();
		
		String[] files = {"cig900.w2.txt", "dm900.w2.txt", "sparrow900.w2.txt",
			"fm900.w2.txt", "rmb900.w2.txt", "aspid900.w2.txt",
			"dt900.w2.txt", "fhqw900.w2.txt", "funky900.w2.txt", "taow900.w2.txt",
			"tron900.w2.txt", "grb900.w2.txt"};

		wr.clearData();
		for (int x = 0; x < files.length; x++) {
			String thisFile = files[x];
			System.out.print("Loading file: " + thisFile + "... ");
			
//			wr.loadData(thisFile);
			wr.loadDataFiringOnly(thisFile);

			System.out.println("Done!");
		}

/*
		for (int y = 1; y <= 4; y++) {
			System.out.println("----\nLateralVelocity, " + y + " segments.");
			ThresholdData td;
			if (useRatio) {
				td = wr.findBestLatVelSlicesTwoRatioAll(y, 0.2f, 37, 0, 8);
			} else {
				td = wr.findBestLatVelSlicesTwoAll(y, 0.2f, 37, 0, 8);					
			}
			
			System.out.print("Slices: " + round(td.slices[0], 1));
			for (int z = 1; z < td.slices.length; z++) {
				System.out.print(" / " + round(td.slices[z], 1));		
			}
			System.out.println();
			System.out.println("Entropy: " + td.origEntropy + " / " + td.entropy);			
			if (useRatio) {
				System.out.println("Gain Ratio: " + td.gainRatio);			
			}
		}

		for (int y = 1; y <= 4; y++) {
			System.out.println("----\nDistance, " + y + " segments.");
			ThresholdData td;
			if (useRatio) {
				td = wr.findBestDistanceSlicesTwoRatioAll(y, 25, 37, 0, 1000);
			} else {
				td = wr.findBestDistanceSlicesTwoAll(y, 25, 37, 0, 1000);					
			}
			
			System.out.print("Slices: " + round(td.slices[0], 0));
			for (int z = 1; z < td.slices.length; z++) {
				System.out.print(" / " + round(td.slices[z], 0));		
			}
			System.out.println();
			System.out.println("Entropy: " + td.origEntropy + " / " + td.entropy);			
			if (useRatio) {
				System.out.println("Gain Ratio: " + td.gainRatio);			
			}
		}

		for (int y = 1; y <= 4; y++) {
			System.out.println("----\nWall Distance, " + y + " segments.");
			ThresholdData td;
			if (useRatio) {
				td = wr.findBestWallDistanceSlicesTwoRatioAll(y, 0.025f, 37, 0, 1);
			} else {
				td = wr.findBestWallDistanceSlicesTwoAll(y, 0.025f, 37, 0, 1);
			}
			
			System.out.print("Slices: " + round(td.slices[0], 3));
			for (int z = 1; z < td.slices.length; z++) {
				System.out.print(" / " + round(td.slices[z], 3));		
			}
			System.out.println();
			System.out.println("Entropy: " + td.origEntropy + " / " + td.entropy);			
			if (useRatio) {
				System.out.println("Gain Ratio: " + td.gainRatio);			
			}
		}

		for (int y = 1; y <= 4; y++) {
			System.out.println("----\nVChangeTime, " + y + " segments.");
			ThresholdData td;
			if (useRatio) {
				td = wr.findBestVChangeTimeSlicesTwoRatioAll(y, 0.025f, 37, 0, 1.2f);
			} else {
				td = wr.findBestVChangeTimeSlicesTwoAll(y, 0.025f, 37, 0, 1.2f);
			}
			
			System.out.print("Slices: " + round(td.slices[0], 3));
			for (int z = 1; z < td.slices.length; z++) {
				System.out.print(" / " + round(td.slices[z], 3));		
			}
			System.out.println();
			System.out.println("Entropy: " + td.origEntropy + " / " + td.entropy);			
			if (useRatio) {
				System.out.println("Gain Ratio: " + td.gainRatio);			
			}
		}

		System.out.println("----");
*/
	
		System.out.println("Unsegmented entropy: " + 
				wr.evaluateUnsegmentedSet(37));

		wr.findBestLatVelDistanceWallDistanceReverseWallDistanceVChangeTimeSlicesTwoAll(
				3, 3, 3, 1, 3, 37);
	}
	
	public void clearData() {
		waveSets = new HashMap<String, ArrayList>();
	}
	
	public void loadData(String filename) {
		ArrayList<Wave> waves = new ArrayList<Wave>();
		File f = new File(baseDir + filename);

		try {
			BufferedReader br = new BufferedReader(new FileReader(f));
		
			while (br.ready()) {
				String nextLine = br.readLine();
				if (nextLine != null) {
					waves.add(parseRecord(nextLine));
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("Error in loadData(" + f + ")");
		}
		
		waveSets.put(filename, waves);
	}

	public void loadDataFiringOnly(String filename) {
		ArrayList<Wave> waves = new ArrayList<Wave>();
		File f = new File(baseDir + filename);

		try {
			BufferedReader br = new BufferedReader(new FileReader(f));
		
			while (br.ready()) {
				String nextLine = br.readLine();
				if (nextLine != null) {
					Wave w = parseRecord(nextLine);
					if (w.firing) {
						waves.add(w);
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("Error in loadData(" + f + ")");
		}
		
		waveSets.put(filename, waves);
	}

	public Wave parseRecord(String record) {
		String[] fields = record.split(" : ");
		
		Wave w = new Wave();
		
		w.roundNum = (byte)Integer.parseInt(fields[0]);
		w.firing = (Integer.parseInt(fields[1]) == 1);
		w.orientation = (byte)Integer.parseInt(fields[2]);
		w.guessFactor = (float)Double.parseDouble(fields[3]);
		w.velocity = (float)Double.parseDouble(fields[4]);
		w.latVel = (float)Double.parseDouble(fields[5]);
		w.accel = (byte)Integer.parseInt(fields[6]);
		w.timeSinceVChange = Integer.parseInt(fields[7]);
		w.timeSinceZeroVelocity = Integer.parseInt(fields[8]);
		w.timeSinceMaxVelocity = Integer.parseInt(fields[9]);
		w.distance = (float)Double.parseDouble(fields[10]);
		w.wallDistance = (float)Double.parseDouble(fields[11]);
		w.reverseWallDistance = (float)Double.parseDouble(fields[12]);
		w.relativeHeading = (float)Double.parseDouble(fields[13]);
		w.distanceLastEightTicks = (float)Double.parseDouble(fields[14]);
		w.distanceLastFifteenTicks = (float)Double.parseDouble(fields[15]);
		w.distanceLastTwentyFiveTicks = (float)Double.parseDouble(fields[16]);
		
		return w;
	}
	
 	public void findBestLatVelDistanceWallDistanceVChangeTimeSlicesTwoAll(
 		int attrSlices, int gfSlices) {
 	 	 	 	 	 	 		
 	 	DataRecordTwoGroup[] drtg = new DataRecordTwoGroup[waveSets.size()];

 	 	Iterator iter = waveSets.keySet().iterator();
 	 	
 	 	int gIndex = 0;
 	 	while (iter.hasNext()) {
 	 	  	String filename = (String)iter.next();
 	 	  	drtg[gIndex++] = new DataRecordTwoGroup(gIndex, dataSetLatVel(filename, gfSlices));
 	 	}
 	 	 	 	 	 	 
 	 	int[] baseCounts = new int[drtg.length];
 	 	for (int x = 0; x < drtg.length; x++) {
 	 		baseCounts[x] = drtg[x].dataSet.length;
 	 	}
 	 	 	 	 	 	 		 		
 	 	ThresholdData latVelData = findBestAttrSlices(drtg, attrSlices,
 	 	 	0.25f, gfSlices, 0, 8, baseCounts);

 	 	float[] latVelSlices = new float[attrSlices + 1];
 	 	for (int x = 0; x < attrSlices; x++) {
 	 		latVelSlices[x] = latVelData.slices[x]; 	 		
 	 	}
 	 	latVelSlices[attrSlices] = Float.POSITIVE_INFINITY;
 	 	
 	 	float[] distSlices = new float[attrSlices + 1]; 	
 	 	drtg = new DataRecordTwoGroup[waveSets.size() * (attrSlices + 1)];
 	 	
 	 	for (int z = 0; z < latVelSlices.length; z++) {
 	 	 	iter = waveSets.keySet().iterator();

 	 	 	gIndex = 0;
 	 	 	while (iter.hasNext()) {
 	 	 	  	String filename = (String)iter.next();

 	 	 	  	ArrayList waves = waveSets.get(filename);
 	 			DataRecordTwo[] drt = new DataRecordTwo[waves.size()];
 	 			
 	 			int tempIndex = 0;
 	 			
 	 			for (int x = 0; x < waves.size(); x++) {
 	 				Wave w = (Wave)waves.get(x);
 	 				if (w.latVel < latVelSlices[z] && 
 	 					(z == 0 || w.latVel >= latVelSlices[z-1])) {
 	 					drt[tempIndex++] = parseWaveDistance(w, gfSlices);
 	 				}
 	 			}
 	 			
 	 			drt = trimDataSet(drt, tempIndex);
 	 			
 	 			drtg[(z * waveSets.size()) + gIndex] = new DataRecordTwoGroup(gIndex, drt);
 	 			gIndex++;
 	 	 	}
 	 	}

 	 	baseCounts = new int[drtg.length];
 	 	for (int x = 0; x < drtg.length; x++) {
 	 		baseCounts[x] = drtg[x].dataSet.length;
 	 	}
 	 	 	 	 	 	 	 		 		
 	 	ThresholdData distData = findBestAttrSlices(drtg, attrSlices,
 	 	 	25, gfSlices, 0, 1000, baseCounts);
 	 	 	
 	 	for (int x = 0; x < attrSlices; x++) {
 	 		distSlices[x] = distData.slices[x]; 	 		
 	 	}
 	 	distSlices[attrSlices] = Float.POSITIVE_INFINITY;

 	 	
 	 	float[] walldistSlices = new float[attrSlices + 1]; 	
 	 	drtg = new DataRecordTwoGroup[waveSets.size() * (attrSlices + 1) * (attrSlices + 1)];
 	 	
 	 	for (int z = 0; z < latVelSlices.length; z++) {
 	 	 	for (int a = 0; a < distSlices.length; a++) {
 	 	 	 	iter = waveSets.keySet().iterator();

 	 	 	 	gIndex = 0;
 	 	 	 	while (iter.hasNext()) {
 	 	 	 	  	String filename = (String)iter.next();

 	 	 	 	  	ArrayList waves = waveSets.get(filename);
 	 	 			DataRecordTwo[] drt = new DataRecordTwo[waves.size()];
 	 	 			
 	 	 			int tempIndex = 0;
 	 	 			
 	 	 			for (int x = 0; x < waves.size(); x++) {
 	 	 				Wave w = (Wave)waves.get(x);
 	 	 				if (w.latVel < latVelSlices[z] && 
 	 	 					(z == 0 || w.latVel >= latVelSlices[z-1]) &&
 	 	 					w.distance < distSlices[a] &&
 	 	 					(a == 0 || w.distance >= distSlices[a-1])) {
 	 	 					drt[tempIndex++] = parseWaveWallDistance(w, gfSlices);
 	 	 				}
 	 	 			}
 	 	 			
 	 	 			drt = trimDataSet(drt, tempIndex);
 	 	 			
 	 	 			drtg[((a + z * distSlices.length) * waveSets.size()) + gIndex] = new DataRecordTwoGroup(gIndex, drt);
 	 	 			gIndex++;
 	 	 	 	}
 	 	 	}
 	 	}
 	 	
 	 	baseCounts = new int[drtg.length];
 	 	for (int x = 0; x < drtg.length; x++) {
 	 		baseCounts[x] = drtg[x].dataSet.length;
 	 	}
 	 	 	 	 	 	 	 		 		
 	 	ThresholdData walldistData = findBestAttrSlices(drtg, attrSlices,
 	 	 	0.05f, gfSlices, 0, 1.2f, baseCounts);
 	 	 	
 	 	for (int x = 0; x < attrSlices; x++) {
 	 		walldistSlices[x] = walldistData.slices[x]; 	 		
 	 	}
 	 	walldistSlices[attrSlices] = Float.POSITIVE_INFINITY;

 	 	
 	 	float[] vchangeSlices = new float[attrSlices + 1]; 	
 	 	drtg = new DataRecordTwoGroup[waveSets.size() * (attrSlices + 1) * 
 	 	    (attrSlices + 1) * (attrSlices + 1)];
 	 	
 	 	for (int z = 0; z < latVelSlices.length; z++) {
 	 	 	for (int a = 0; a < distSlices.length; a++) {
 	 	 	 	for (int b = 0; b < walldistSlices.length; b++) {
 	 	 	 	 	iter = waveSets.keySet().iterator();

 	 	 	 	 	gIndex = 0;
 	 	 	 	 	while (iter.hasNext()) {
 	 	 	 	 	  	String filename = (String)iter.next();

 	 	 	 	 	  	ArrayList waves = waveSets.get(filename);
 	 	 	 			DataRecordTwo[] drt = new DataRecordTwo[waves.size()];
 	 	 	 			
 	 	 	 			int tempIndex = 0;
 	 	 	 			
 	 	 	 			for (int x = 0; x < waves.size(); x++) {
 	 	 	 				Wave w = (Wave)waves.get(x);
 	 	 	 				if (w.latVel < latVelSlices[z] && 
 	 	 	 					(z == 0 || w.latVel >= latVelSlices[z-1]) &&
 	 	 	 					w.distance < distSlices[a] &&
 	 	 	 					(a == 0 || w.distance >= distSlices[a-1]) &&
 	 	 	 					w.wallDistance < walldistSlices[b] &&
 	 	 	 					(b == 0 || w.wallDistance >= walldistSlices[b-1])) {
 	 	 	 					DataRecordTwo drtTemp = parseWaveVChangeTime(w, gfSlices);
 	 	 	 					if (drtTemp != null) {
 	 	 	 						drt[tempIndex++] = drtTemp;
 	 	 	 					}
 	 	 	 				}
 	 	 	 			}
 	 	 	 			
 	 	 	 			drt = trimDataSet(drt, tempIndex);
 	 	 	 			
 	 	 	 			drtg[((b + a * walldistSlices.length + z * distSlices.length * walldistSlices.length) * waveSets.size()) + gIndex] = new DataRecordTwoGroup(gIndex, drt);
 	 	 	 			gIndex++;
 	 	 	 	 	}
 	 	 	 	}
 	 	 	}
 	 	}
 	 	
 	 	baseCounts = new int[drtg.length];
 	 	for (int x = 0; x < drtg.length; x++) {
 	 		baseCounts[x] = drtg[x].dataSet.length;
 	 	}
 	 	 	 	 	 	 	 		 		
 	 	ThresholdData vchangeData = findBestAttrSlices(drtg, attrSlices,
 	 	 	0.05f, gfSlices, 0, 1.2f, baseCounts);
 	 	 	
 	 	for (int x = 0; x < attrSlices; x++) {
 	 		vchangeSlices[x] = vchangeData.slices[x]; 	 		
 	 	}
 	 	vchangeSlices[attrSlices] = Float.POSITIVE_INFINITY;
 	 	
		System.out.print("LatVel Slices: " + round(latVelSlices[0], 2));
		for (int z = 1; z < latVelSlices.length - 1; z++) {
			System.out.print(" / " + round(latVelSlices[z], 2));		
		}
		System.out.println();

		System.out.print("Distance Slices: " + round(distSlices[0], 0));
		for (int z = 1; z < distSlices.length - 1; z++) {
			System.out.print(" / " + round(distSlices[z], 0));		
		}
		System.out.println();

		System.out.print("WallDistance Slices: " + round(walldistSlices[0], 2));
		for (int z = 1; z < walldistSlices.length - 1; z++) {
			System.out.print(" / " + round(walldistSlices[z], 2));		
		}
		System.out.println();

		System.out.print("VChangeTime Slices: " + round(vchangeSlices[0], 2));
		for (int z = 1; z < vchangeSlices.length - 1; z++) {
			System.out.print(" / " + round(vchangeSlices[z], 2));		
		}
		System.out.println();

		System.out.println("Final entropy: " + vchangeData.entropy);
 	}
 	
 	public void findBestLatVelDistanceWallDistanceReverseWallDistanceVChangeTimeSlicesTwoAll(
 	 	int numLatVelSlices, int numDistSlices, int numWallDistSlices, 
 	 	int numReverseWallDistSlices, int numVChangeTimeSlices, int gfSlices) {
 	 	 	 	 	 	 	 		
 	 	DataRecordTwoGroup[] drtg = new DataRecordTwoGroup[waveSets.size() * 3];

 	 	Iterator iter; 	 	
 	 	int gIndex = 0;

 	 	for (int y = 0; y < 3; y++) {
 	 	 	iter = waveSets.keySet().iterator();

 	 	 	gIndex = 0;
 	 	 	while (iter.hasNext()) {
 	 	 	  	String filename = (String)iter.next();

 	 	 	  	ArrayList waves = waveSets.get(filename);
 	 			DataRecordTwo[] drt = new DataRecordTwo[waves.size()];
 	 			
 	 			int tempIndex = 0;
 	 			
 	 			for (int x = 0; x < waves.size(); x++) {
 	 				Wave w = (Wave)waves.get(x);
 	 				if (w.accel == y) {
 	 					drt[tempIndex++] = parseWaveLatVel(w, gfSlices);
 	 				}
 	 			}
 	 			
 	 			drt = trimDataSet(drt, tempIndex);
 	 			
 	 			drtg[(y * waveSets.size()) + gIndex] = new DataRecordTwoGroup(gIndex, drt);
 	 			gIndex++;
 	 	 	}
 	 	}

 	 	int[] baseCounts = new int[drtg.length];
 	 	for (int x = 0; x < drtg.length; x++) {
 	 		baseCounts[x] = drtg[x].dataSet.length;
 	 	}
 	 	 	 	 	 	 	 		 		
 	 	ThresholdData latVelData = findBestAttrSlices(drtg, numLatVelSlices,
 	 	 	0.25f, gfSlices, 0, 8, baseCounts);

 	 	float[] latVelSlices = new float[numLatVelSlices + 1];
 	 	for (int x = 0; x < numLatVelSlices; x++) {
	 		latVelSlices[x] = latVelData.slices[x]; 	 		
 	 	}
 	 	latVelSlices[numLatVelSlices] = Float.POSITIVE_INFINITY;
 	 	 	
 	 	
 	 	float[] distSlices = new float[numDistSlices + 1];
 	 	drtg = new DataRecordTwoGroup[waveSets.size() * 3 * (numLatVelSlices + 1)];
 	 	 	
 	 	for (int y = 0; y < 3; y++) {
 	 	 	for (int z = 0; z < latVelSlices.length; z++) {
 	 	 	 	iter = waveSets.keySet().iterator();

 	 	 	 	gIndex = 0;
 	 	 	 	while (iter.hasNext()) {
 	 	 	 	  	String filename = (String)iter.next();

 	 	 	 	  	ArrayList waves = waveSets.get(filename);
 	 	 			DataRecordTwo[] drt = new DataRecordTwo[waves.size()];
 	 	 			
 	 	 			int tempIndex = 0;
 	 	 			
 	 	 			for (int x = 0; x < waves.size(); x++) {
 	 	 				Wave w = (Wave)waves.get(x);
 	 	 				if (w.accel == y &&
 	 	 					w.latVel < latVelSlices[z] && 
 	 	 					(z == 0 || w.latVel >= latVelSlices[z-1])) {
 	 	 					drt[tempIndex++] = parseWaveDistance(w, gfSlices);
 	 	 				}
 	 	 			}
 	 	 			
 	 	 			drt = trimDataSet(drt, tempIndex);
 	 	 			
 	 	 			drtg[((y * latVelSlices.length + z) * waveSets.size()) + gIndex] = new DataRecordTwoGroup(gIndex, drt);
 	 	 			gIndex++;
 	 	 	 	}
 	 	 	}
 	 	}

 	 	baseCounts = new int[drtg.length];
 	 	for (int x = 0; x < drtg.length; x++) {
 	 		baseCounts[x] = drtg[x].dataSet.length;
 	 	}
 	 	 	 	 	 	 	 		 		
 	 	ThresholdData distData = findBestAttrSlices(drtg, numDistSlices,
 	 	 	25, gfSlices, 0, 1000, baseCounts);
 	 	 	
 	 	for (int x = 0; x < numDistSlices; x++) {
 	 		distSlices[x] = distData.slices[x]; 	 		
 	 	}
 	 	distSlices[numDistSlices] = Float.POSITIVE_INFINITY;

 	 	
 	 	float[] walldistSlices = new float[numWallDistSlices + 1]; 	
 	 	drtg = new DataRecordTwoGroup[waveSets.size() * 3 * (numLatVelSlices + 1) * (numDistSlices + 1)];
 	 	
 	 	for (int y = 0; y < 3; y++) {
 	 	 	for (int z = 0; z < latVelSlices.length; z++) {
 	 	 	 	for (int a = 0; a < distSlices.length; a++) {
 	 	 	 	 	iter = waveSets.keySet().iterator();

 	 	 	 	 	gIndex = 0;
 	 	 	 	 	while (iter.hasNext()) {
 	 	 	 	 	  	String filename = (String)iter.next();

 	 	 	 	 	  	ArrayList waves = waveSets.get(filename);
 	 	 	 			DataRecordTwo[] drt = new DataRecordTwo[waves.size()];
 	 	 	 			
 	 	 	 			int tempIndex = 0;
 	 	 	 			
 	 	 	 			for (int x = 0; x < waves.size(); x++) {
 	 	 	 				Wave w = (Wave)waves.get(x);
 	 	 	 				if (w.accel == y &&
 	 	 	 					w.latVel < latVelSlices[z] && 
 	 	 	 					(z == 0 || w.latVel >= latVelSlices[z-1]) &&
 	 	 	 					w.distance < distSlices[a] &&
 	 	 	 					(a == 0 || w.distance >= distSlices[a-1])) {
 	 	 	 					drt[tempIndex++] = parseWaveWallDistance(w, gfSlices);
 	 	 	 				}
 	 	 	 			}
 	 	 	 			
 	 	 	 			drt = trimDataSet(drt, tempIndex);
 	 	 	 			
 	 	 	 			drtg[((a + z * distSlices.length + y * latVelSlices.length * distSlices.length) * waveSets.size()) + gIndex] = new DataRecordTwoGroup(gIndex, drt);
 	 	 	 			gIndex++;
 	 	 	 	 	}
 	 	 	 	}
 	 	 	}
 	 	} 	 	
 	 	baseCounts = new int[drtg.length];
 	 	for (int x = 0; x < drtg.length; x++) {
 	 		baseCounts[x] = drtg[x].dataSet.length;
 	 	}
 	 	 	 	 	 	 	 		 		
 	 	ThresholdData walldistData = findBestAttrSlices(drtg, numWallDistSlices,
 	 	 	0.05f, gfSlices, 0, 1.2f, baseCounts);
 	 	 	
 	 	for (int x = 0; x < numWallDistSlices; x++) {
 	 		walldistSlices[x] = walldistData.slices[x]; 	 		
 	 	}
 	 	walldistSlices[numWallDistSlices] = Float.POSITIVE_INFINITY;
 	 	

 	 	float[] reverseWallDistSlices = new float[numReverseWallDistSlices + 1]; 	
 	 	drtg = new DataRecordTwoGroup[waveSets.size() * 3 * (numLatVelSlices + 1) * 
 	 	    (numDistSlices + 1) * (numWallDistSlices + 1)];
 	 	
 	 	for (int y = 0; y < 3; y++) {
 	 	 	for (int z = 0; z < latVelSlices.length; z++) {
 	 	 	 	for (int a = 0; a < distSlices.length; a++) {
 	 	 	 	 	for (int b = 0; b < walldistSlices.length; b++) {
 	 	 	 	 	 	iter = waveSets.keySet().iterator();

 	 	 	 	 	 	gIndex = 0;
 	 	 	 	 	 	while (iter.hasNext()) {
 	 	 	 	 	 	  	String filename = (String)iter.next();

 	 	 	 	 	 	  	ArrayList waves = waveSets.get(filename);
 	 	 	 	 			DataRecordTwo[] drt = new DataRecordTwo[waves.size()];
 	 	 	 	 			
 	 	 	 	 			int tempIndex = 0;
 	 	 	 	 			
 	 	 	 	 			for (int x = 0; x < waves.size(); x++) {
 	 	 	 	 				Wave w = (Wave)waves.get(x);
 	 	 	 	 				if (w.accel == y &&
 	 	 	 	 					w.latVel < latVelSlices[z] && 
 	 	 	 	 					(z == 0 || w.latVel >= latVelSlices[z-1]) &&
 	 	 	 	 					w.distance < distSlices[a] &&
 	 	 	 	 					(a == 0 || w.distance >= distSlices[a-1]) &&
 	 	 	 	 					w.wallDistance < walldistSlices[b] &&
 	 	 	 	 					(b == 0 || w.wallDistance >= walldistSlices[b-1])) {
 	 	 	 	 					DataRecordTwo drtTemp = 
 	 	 	 	 						parseWaveReverseWallDistance(w, gfSlices);
 	 	 	 	 					if (drtTemp != null) {
 	 	 	 	 						drt[tempIndex++] = drtTemp;
 	 	 	 	 					}
 	 	 	 	 				}
 	 	 	 	 			}
 	 	 	 	 			
 	 	 	 	 			drt = trimDataSet(drt, tempIndex);
 	 	 	 	 			
 	 	 	 	 			drtg[((b + a * walldistSlices.length + z * distSlices.length * walldistSlices.length + y * latVelSlices.length * distSlices.length * walldistSlices.length) * waveSets.size()) + gIndex] = new DataRecordTwoGroup(gIndex, drt);
 	 	 	 	 			gIndex++;
 	 	 	 	 	 	}
 	 	 	 	 	}
 	 	 	 	}
 	 	 	}
 	 	} 	 	
 	 	baseCounts = new int[drtg.length];
 	 	for (int x = 0; x < drtg.length; x++) {
 	 		baseCounts[x] = drtg[x].dataSet.length;
 	 	}
 	 	 	 	 	 	 	 		 		
 	 	ThresholdData reverseWallDistData = findBestAttrSlices(drtg, numReverseWallDistSlices,
 	 	 	0.05f, gfSlices, 0, 1.2f, baseCounts);
 	 	 	
 	 	for (int x = 0; x < numReverseWallDistSlices; x++) {
 	 		reverseWallDistSlices[x] = reverseWallDistData.slices[x]; 	 		
 	 	}
 	 	reverseWallDistSlices[numReverseWallDistSlices] = Float.POSITIVE_INFINITY;

 	 	
 	 	float[] vchangeSlices = new float[numVChangeTimeSlices + 1]; 	
 	 	drtg = new DataRecordTwoGroup[waveSets.size() * 3 * (numLatVelSlices + 1) * 
 	 	    (numDistSlices + 1) * (numWallDistSlices + 1) * (numReverseWallDistSlices + 1)];
 	 	
 	 	for (int y = 0; y < 3; y++) {
 	 	 	for (int z = 0; z < latVelSlices.length; z++) {
 	 	 	 	for (int a = 0; a < distSlices.length; a++) {
 	 	 	 	 	for (int b = 0; b < walldistSlices.length; b++) {
 	 	 	 	 	 	for (int c = 0; c < reverseWallDistSlices.length; c++) {
 	 	 	 	 	 	 	iter = waveSets.keySet().iterator();

 	 	 	 	 	 	 	gIndex = 0;
 	 	 	 	 	 	 	while (iter.hasNext()) {
 	 	 	 	 	 	 	  	String filename = (String)iter.next();

 	 	 	 	 	 	 	  	ArrayList waves = waveSets.get(filename);
 	 	 	 	 	 			DataRecordTwo[] drt = new DataRecordTwo[waves.size()];
 	 	 	 	 	 			
 	 	 	 	 	 			int tempIndex = 0;
 	 	 	 	 	 			
 	 	 	 	 	 			for (int x = 0; x < waves.size(); x++) {
 	 	 	 	 	 				Wave w = (Wave)waves.get(x);
 	 	 	 	 	 				if (w.accel == y &&
 	 	 	 	 	 					w.latVel < latVelSlices[z] && 
 	 	 	 	 	 					(z == 0 || w.latVel >= latVelSlices[z-1]) &&
 	 	 	 	 	 					w.distance < distSlices[a] &&
 	 	 	 	 	 					(a == 0 || w.distance >= distSlices[a-1]) &&
 	 	 	 	 	 					w.wallDistance < walldistSlices[b] &&
 	 	 	 	 	 					(b == 0 || w.wallDistance >= walldistSlices[b-1]) &&
 	 	 	 	 	 					w.reverseWallDistance < reverseWallDistSlices[c] &&
 	 	 	 	 	 					(c == 0 || w.reverseWallDistance >= reverseWallDistSlices[c-1])) {
 	 	 	 	 	 					DataRecordTwo drtTemp = parseWaveVChangeTime(w, gfSlices);
 	 	 	 	 	 					if (drtTemp != null) {
 	 	 	 	 	 						drt[tempIndex++] = drtTemp;
 	 	 	 	 	 					}
 	 	 	 	 	 				}
 	 	 	 	 	 			}
 	 	 	 	 	 			
 	 	 	 	 	 			drt = trimDataSet(drt, tempIndex);
 	 	 	 	 	 			
 	 	 	 	 	 			drtg[((c + b * reverseWallDistSlices.length + a * reverseWallDistSlices.length * walldistSlices.length + z * reverseWallDistSlices.length * distSlices.length * walldistSlices.length + y * latVelSlices.length * distSlices.length * walldistSlices.length * reverseWallDistSlices.length) * waveSets.size()) + gIndex] = new DataRecordTwoGroup(gIndex, drt);
 	 	 	 	 	 			gIndex++;
 	 	 	 	 	 	 	}
 	 	 	 	 	 	}
 	 	 	 	 	 }
 	 	 	 	}
 	 	 	}
 	 	} 	 	
 	 	baseCounts = new int[drtg.length];
 	 	for (int x = 0; x < drtg.length; x++) {
 	 		baseCounts[x] = drtg[x].dataSet.length;
 	 	}
 	 	 	 	 	 	 	 		 		
 	 	ThresholdData vchangeData = findBestAttrSlices(drtg, numVChangeTimeSlices,
 	 	 	0.05f, gfSlices, 0, 1.2f, baseCounts);
 	 	 	
 	 	for (int x = 0; x < numVChangeTimeSlices; x++) {
 	 		vchangeSlices[x] = vchangeData.slices[x]; 	 		
 	 	}
 	 	vchangeSlices[numVChangeTimeSlices] = Float.POSITIVE_INFINITY;
 	 	
		System.out.print("LatVel Slices: " + round(latVelSlices[0], 2));
		for (int z = 1; z < latVelSlices.length - 1; z++) {
			System.out.print(" / " + round(latVelSlices[z], 2));		
		}
		System.out.println();

		System.out.print("Distance Slices: " + round(distSlices[0], 0));
		for (int z = 1; z < distSlices.length - 1; z++) {
			System.out.print(" / " + round(distSlices[z], 0));		
		}
		System.out.println();

		System.out.print("WallDistance Slices: " + round(walldistSlices[0], 2));
		for (int z = 1; z < walldistSlices.length - 1; z++) {
			System.out.print(" / " + round(walldistSlices[z], 2));		
		}
		System.out.println();

		System.out.print("ReverseWallDistance Slices: " + round(reverseWallDistSlices[0], 2));
		for (int z = 1; z < reverseWallDistSlices.length - 1; z++) {
			System.out.print(" / " + round(reverseWallDistSlices[z], 2));		
		}
		System.out.println();

		System.out.print("VChangeTime Slices: " + round(vchangeSlices[0], 2));
		for (int z = 1; z < vchangeSlices.length - 1; z++) {
			System.out.print(" / " + round(vchangeSlices[z], 2));		
		}
		System.out.println();

		System.out.println("Final entropy: " + vchangeData.entropy);
 	 }

 	public ThresholdData findBestLatVelSlicesTwo(String filename, int attrSlices, 
 		float attrIncrement, int gfSlices, float lowBound, float highBound) {
		return findBestAttrSlices(dataSetLatVel(filename, gfSlices), attrSlices,
			attrIncrement, gfSlices, lowBound, highBound);
	}

 	public ThresholdData findBestLatVelSlicesTwoRatio(String filename, int attrSlices, 
 		float attrIncrement, int gfSlices, float lowBound, float highBound) {
		return findBestAttrSlicesRatio(dataSetLatVel(filename, gfSlices), attrSlices,
			attrIncrement, gfSlices, lowBound, highBound);
	}

 	public ThresholdData findBestLatVelSlicesTwoAll(int attrSlices, 
 	 	float attrIncrement, int gfSlices, float lowBound, float highBound) {
 	 	 	 	 	 		
 	 	DataRecordTwoGroup[] drtg = new DataRecordTwoGroup[waveSets.size()];
 	 	 	 	 	 		
 	 	Iterator iter = waveSets.keySet().iterator();
 	 	 	 	 	 		
 	 	int gIndex = 0;
 	 	while (iter.hasNext()) {
 	 	  	String filename = (String)iter.next();
 	 	  	drtg[gIndex++] = new DataRecordTwoGroup(gIndex, dataSetLatVel(filename, gfSlices));
 	 	}
 	 	 	 	 	 
 	 	int[] baseCounts = new int[drtg.length];
 	 	for (int x = 0; x < drtg.length; x++) {
 	 		baseCounts[x] = drtg[x].dataSet.length;
 	 	}
 	 	 	 	 	 		 		
 	 	return findBestAttrSlices(drtg, attrSlices,
 	  	 	attrIncrement, gfSlices, lowBound, highBound, baseCounts);
 	}
 	
 	public ThresholdData findBestLatVelSlicesTwoRatioAll(int attrSlices, 
 		float attrIncrement, int gfSlices, float lowBound, float highBound) {
 		
 		DataRecordTwoGroup[] drtg = new DataRecordTwoGroup[waveSets.size()];
 		
 		Iterator iter = waveSets.keySet().iterator();
 		
 		int gIndex = 0;
 		while (iter.hasNext()) {
 			String filename = (String)iter.next();
 			drtg[gIndex++] = new DataRecordTwoGroup(gIndex, dataSetLatVel(filename, gfSlices));
 		}
 		
 		int[] baseCounts = new int[drtg.length];
 		for (int x = 0; x < drtg.length; x++) {
 			baseCounts[x] = drtg[x].dataSet.length;
 		}
 		 		
		return findBestAttrSlicesRatio(drtg, attrSlices,
			attrIncrement, gfSlices, lowBound, highBound, baseCounts);
	}

 	public ThresholdData findBestDistanceSlicesTwo(String filename, int attrSlices, 
 	 	float attrIncrement, int gfSlices, float lowBound, float highBound) {
 		return findBestAttrSlices(dataSetDistance(filename, gfSlices), attrSlices,
 			attrIncrement, gfSlices, lowBound, highBound);
	}

 	public ThresholdData findBestDistanceSlicesTwoRatio(String filename, int attrSlices, 
 	 	 	float attrIncrement, int gfSlices, float lowBound, float highBound) {
 	 		return findBestAttrSlicesRatio(dataSetDistance(filename, gfSlices), attrSlices,
 	 			attrIncrement, gfSlices, lowBound, highBound);
	}
 	
 	public ThresholdData findBestDistanceSlicesTwoAll(int attrSlices, 
 	 	 float attrIncrement, int gfSlices, float lowBound, float highBound) {
 	 	 	 	 		
 	 	 DataRecordTwoGroup[] drtg = new DataRecordTwoGroup[waveSets.size()];
 	 	 	 	 		
 	 	 Iterator iter = waveSets.keySet().iterator();
 	 	 	 	 		
 	 	 int gIndex = 0;
 	 	 while (iter.hasNext()) {
 	 	 	 String filename = (String)iter.next();
 	 	  	 drtg[gIndex++] = new DataRecordTwoGroup(gIndex, dataSetDistance(filename, gfSlices));
 	 	 }
 	 	 	 	 
 	 	 int[] baseCounts = new int[drtg.length];
 	 	 for (int x = 0; x < drtg.length; x++) {
 	 	 	baseCounts[x] = drtg[x].dataSet.length;
 	 	 }
 	 	 	 	 		 		
 	 	 return findBestAttrSlices(drtg, attrSlices,
 	 	 	attrIncrement, gfSlices, lowBound, highBound, baseCounts);
 	}
 	
 	public ThresholdData findBestDistanceSlicesTwoRatioAll(int attrSlices, 
 	 	float attrIncrement, int gfSlices, float lowBound, float highBound) {
 	 		
 	 	DataRecordTwoGroup[] drtg = new DataRecordTwoGroup[waveSets.size()];
 	 		
 	 	Iterator iter = waveSets.keySet().iterator();
 	 		
 	 	int gIndex = 0;
 	 	while (iter.hasNext()) {
 	 		String filename = (String)iter.next();
 	 		drtg[gIndex++] = new DataRecordTwoGroup(gIndex, dataSetDistance(filename, gfSlices));
 	 	}
 	 	
 		int[] baseCounts = new int[drtg.length];
 		for (int x = 0; x < drtg.length; x++) {
 			baseCounts[x] = drtg[x].dataSet.length;
 		}
 	 		 		
 		return findBestAttrSlicesRatio(drtg, attrSlices,
 			attrIncrement, gfSlices, lowBound, highBound, baseCounts);
 	}

 	public ThresholdData findBestWallDistanceSlicesTwo(String filename, int attrSlices, 
 	 	float attrIncrement, int gfSlices, float lowBound, float highBound) {
 		return findBestAttrSlices(dataSetWallDistance(filename, gfSlices), attrSlices,
 			attrIncrement, gfSlices, lowBound, highBound);
	}

 	public ThresholdData findBestWallDistanceSlicesTwoRatio(String filename, int attrSlices, 
 	 	float attrIncrement, int gfSlices, float lowBound, float highBound) {
 	 	return findBestAttrSlicesRatio(dataSetWallDistance(filename, gfSlices), attrSlices,
 	 		attrIncrement, gfSlices, lowBound, highBound);
 	}
 	
 	public ThresholdData findBestWallDistanceSlicesTwoAll(int attrSlices, 
 	  	 float attrIncrement, int gfSlices, float lowBound, float highBound) {
 	 	 	 		
 	 	 DataRecordTwoGroup[] drtg = new DataRecordTwoGroup[waveSets.size()];
 	 	 	 		
 	 	 Iterator iter = waveSets.keySet().iterator();
 	 	 	 		
 	 	 int gIndex = 0;
 	 	 while (iter.hasNext()) {
 	 		 String filename = (String)iter.next();
 	 	 	 drtg[gIndex++] = new DataRecordTwoGroup(gIndex, dataSetWallDistance(filename, gfSlices));
 	 	 }
 	 	 	 
 	  	int[] baseCounts = new int[drtg.length];
 	 	for (int x = 0; x < drtg.length; x++) {
 	 		baseCounts[x] = drtg[x].dataSet.length;
 	 	}
 	 	 	 		 		
 	 	return findBestAttrSlices(drtg, attrSlices,
 	 		attrIncrement, gfSlices, lowBound, highBound, baseCounts);
 	}
 	
 	public ThresholdData findBestWallDistanceSlicesTwoRatioAll(int attrSlices, 
 	 	 float attrIncrement, int gfSlices, float lowBound, float highBound) {
 	 	 		
 	 	 DataRecordTwoGroup[] drtg = new DataRecordTwoGroup[waveSets.size()];
 	 	 		
 	 	 Iterator iter = waveSets.keySet().iterator();
 	 	 		
 	 	 int gIndex = 0;
 	 	 while (iter.hasNext()) {
 	 	 	String filename = (String)iter.next();
 	 	 	drtg[gIndex++] = new DataRecordTwoGroup(gIndex, dataSetWallDistance(filename, gfSlices));
 	 	 }
 	 	 
  		int[] baseCounts = new int[drtg.length];
 		for (int x = 0; x < drtg.length; x++) {
 			baseCounts[x] = drtg[x].dataSet.length;
 		}
 	 	 		 		
 	 	 return findBestAttrSlicesRatio(drtg, attrSlices,
 	 		attrIncrement, gfSlices, lowBound, highBound, baseCounts);
 	}
 	
 	public ThresholdData findBestVChangeTimeSlicesTwoAll(int attrSlices, 
 		float attrIncrement, int gfSlices, float lowBound, float highBound) {
	 		
 		DataRecordTwoGroup[] drtg = new DataRecordTwoGroup[waveSets.size()];
 	 	 	 	 		
 	 	Iterator iter = waveSets.keySet().iterator();
 	 	 	 	 		
 	 	int gIndex = 0;
 	 	while (iter.hasNext()) {
 	 		String filename = (String)iter.next();
 	 	 	drtg[gIndex++] = new DataRecordTwoGroup(gIndex, dataSetVChangeTime(filename, gfSlices));
 	 	}
 	 	 	 	 
 	 	int[] baseCounts = new int[drtg.length];
 	 	for (int x = 0; x < drtg.length; x++) {
 	 		baseCounts[x] = drtg[x].dataSet.length;
 	 	}
 	 	 	 	 		 		
 	 	return findBestAttrSlices(drtg, attrSlices,
 	 		attrIncrement, gfSlices, lowBound, highBound, baseCounts);
 	}

	public ThresholdData findBestVChangeTimeSlicesTwoRatioAll(int attrSlices, 
		float attrIncrement, int gfSlices, float lowBound, float highBound) {
 		 		
 	 	DataRecordTwoGroup[] drtg = new DataRecordTwoGroup[waveSets.size()];
 	 	 	 	 	 		
 	 	Iterator iter = waveSets.keySet().iterator();
 	 	 	 	 	 		
 	 	int gIndex = 0;
 	 	while (iter.hasNext()) {
 	 		String filename = (String)iter.next();
 	 	 	drtg[gIndex++] = new DataRecordTwoGroup(gIndex, dataSetVChangeTime(filename, gfSlices));
 	 	}
 	 	 	 	 	 
 	 	int[] baseCounts = new int[drtg.length];
 	 	for (int x = 0; x < drtg.length; x++) {
 	 		baseCounts[x] = drtg[x].dataSet.length;
 	 	}
 	 	 	 	 	 		 		
 	 	return findBestAttrSlicesRatio(drtg, attrSlices,
 	 		attrIncrement, gfSlices, lowBound, highBound, baseCounts);
 	 }
	
	public float evaluateUnsegmentedSet(int gfSlices) {
 	 	DataRecordTwoGroup[] drtg = new DataRecordTwoGroup[waveSets.size()];
	 		
 	 	Iterator iter = waveSets.keySet().iterator();
 	 		
 	 	int gIndex = 0;
 	 	while (iter.hasNext()) {
 	 		String filename = (String)iter.next();
 	 		drtg[gIndex++] = new DataRecordTwoGroup(gIndex, dataSetDistance(filename, gfSlices));
 	 	}
 	 	
 		int[] baseCounts = new int[drtg.length];
 		for (int x = 0; x < drtg.length; x++) {
 			baseCounts[x] = drtg[x].dataSet.length;
 		}
 		
 		return calculateEntropy(drtg, baseCounts);		
	}
	
 	public float evaluateSegmentationSet(float[] LATVEL_SLICES,
 		float[] DISTANCE_SLICES, float[] WALLDISTANCE_SLICES,
 		float[] VCHANGETIME_SLICES, float[] ACCEL_SLICES, int gfSlices) {
 		
 		int numSegments = LATVEL_SLICES.length * DISTANCE_SLICES.length *
 			WALLDISTANCE_SLICES.length * VCHANGETIME_SLICES.length * 
 			ACCEL_SLICES.length;
 		
 		DataRecordTwoGroup[] dg = new DataRecordTwoGroup[numSegments * waveSets.size()];
 	 	int[] dataSetLengths = new int[numSegments * waveSets.size()];

 	 	Iterator iter = waveSets.keySet().iterator();
 	 	 	 	 	 	 		
 	 	int gIndex = 0;
	 	while (iter.hasNext()) {
	 		String filename = (String)iter.next();
 	 		ArrayList waves = waveSets.get(filename);
 	 		
 	 	 	for (int a = 0; a < LATVEL_SLICES.length; a++) {
 	 			for (int b = 0; b < DISTANCE_SLICES.length; b++) {
 	 				for (int c = 0; c < WALLDISTANCE_SLICES.length; c++) {
 	 					for (int d = 0; d < VCHANGETIME_SLICES.length; d++) {
 	 						for (int e = 0; e < ACCEL_SLICES.length; e++, gIndex++) {
 	 							if (dg[gIndex] == null) {
 	 								dg[gIndex] = new DataRecordTwoGroup(gIndex,
 	 									new DataRecordTwo[200]);
 	 							} 
 	 							 	 							
 	 							for (int x = 0; x < waves.size(); x++) {
 	 	 							if (dg[gIndex].dataSet.length <= dataSetLengths[gIndex] + 1) {
 	 	 								DataRecordTwo[] newSet = new DataRecordTwo[dg[gIndex].dataSet.length * 2];
 	 	 								for (int z = 0; z < dg[gIndex].dataSet.length; z++) {
 	 	 									newSet[z] = dg[gIndex].dataSet[z];
 	 	 								}
 	 	 								
 	 	 								dg[gIndex].dataSet = newSet;
 	 	 							}

 	 	 							Wave w = (Wave)waves.get(x);
 	 	 							double vChange = ((double)w.timeSinceVChange) / (w.distance / 11);
 	 								if (w.latVel < LATVEL_SLICES[a] && (a == 0 || w.latVel > LATVEL_SLICES[a-1]) &&
 	 									w.distance < DISTANCE_SLICES[b] && (b == 0 || w.distance > DISTANCE_SLICES[b-1]) &&
 	 									w.wallDistance < WALLDISTANCE_SLICES[c] && (c == 0 || w.wallDistance > WALLDISTANCE_SLICES[c-1]) &&
 	 									vChange < VCHANGETIME_SLICES[d] && (d == 0 || vChange > VCHANGETIME_SLICES[d-1]) &&
 	 									w.accel <  ACCEL_SLICES[e] && (e == 0 || w.accel > ACCEL_SLICES[e-1])) {
 	 									dg[gIndex].dataSet[dataSetLengths[gIndex]++] =
 	 										new DataRecordTwo((float)gIndex, gfIndex(w.guessFactor, gfSlices));
  	 								}
 	 							}
 	 						}
 	 					}
 	 				}
 	 			}
 	 		}
 	 	}
	 	
 	 	return calculateEntropy(dg, dataSetLengths);
 	}
 	
 	public ThresholdData findBestAttrSlices(DataRecordTwo[] ds,
 		int attrSlices, float attrIncrement, int gfSlices, float lowBound, float highBound) {
 			
		DataRecordTwo[] ds1 = new DataRecordTwo[ds.length];
		DataRecordTwo[] ds2 = new DataRecordTwo[ds.length];
			              
		float origEntropy = calculateEntropy(ds);
		float bestEntropy = Float.POSITIVE_INFINITY;
		
		float[] slices = new float[attrSlices];
		
		for (float t1 = lowBound + attrIncrement; t1 < highBound; 
			t1 += attrIncrement) {
			int ds1Index = 0, ds2Index = 0;
			
			for (int x = 0; x < ds.length; x++) {
				DataRecordTwo dr = ds[x];
				if (dr.attr1 < t1) {
					ds1[ds1Index++] = dr;
				} else {
					ds2[ds2Index++] = dr;
				}
			}
					
			float newEntropy = 
					((((float)ds1Index) / ds.length) * 
						calculateEntropy(trimDataSet(ds1, ds1Index)));
			
			if (attrSlices == 1) {
				newEntropy += ((((float)ds2Index) / ds.length) *
					calculateEntropy(trimDataSet(ds2, ds2Index)));

				if (newEntropy < bestEntropy) {
					bestEntropy = newEntropy;
					slices[0] = t1;
				}
			} else {
				ThresholdData td = findBestAttrSlices(
					trimDataSet(ds2, ds2Index), attrSlices - 1, attrIncrement,
					gfSlices, t1, highBound);
					
				newEntropy += ((((float)ds2Index) / ds.length) *
					td.entropy);

				if (newEntropy < bestEntropy) {
					bestEntropy = newEntropy;
					slices[0] = t1;
					for (int i = 0; i < td.slices.length; i++) {
						slices[i+1] = td.slices[i];
					}
				}
			}				
		}
		
		return new ThresholdData(slices, bestEntropy, origEntropy);
	}
 	
 	public ThresholdData findBestAttrSlicesRatio(DataRecordTwo[] ds,
		int attrSlices, float attrIncrement, int gfSlices, float lowBound, float highBound) {
 	 			
 		DataRecordTwo[] ds1 = new DataRecordTwo[ds.length];
 		DataRecordTwo[] ds2 = new DataRecordTwo[ds.length];
 
 		float origEntropy = calculateEntropy(ds);
 				
		float bestRatio = Float.NEGATIVE_INFINITY;
		float bestEntropy = Float.POSITIVE_INFINITY;
		
		float[] slices = new float[attrSlices];
		
		for (float t1 = lowBound + attrIncrement; t1 < highBound; 
			t1 += attrIncrement) {
			int ds1Index = 0, ds2Index = 0;
			
			for (int x = 0; x < ds.length; x++) {
				DataRecordTwo dr = ds[x];
				if (dr.attr1 < t1) {
					ds1[ds1Index++] = dr;
				} else {
					ds2[ds2Index++] = dr;
				}
			}
					
			float newEntropy = 
					((((float)ds1Index) / ds.length) * 
						calculateEntropy(trimDataSet(ds1, ds1Index)));
			
			if (attrSlices == 1) {
				newEntropy += ((((float)ds2Index) / ds.length) *
					calculateEntropy(trimDataSet(ds2, ds2Index)));

				float[] tempSlices = new float[1];
				tempSlices[0] = t1;
				
				float gainRatio = (origEntropy - newEntropy)
					/ calculateSplitInformation(ds, tempSlices);

				if (gainRatio > bestRatio) {
					bestRatio = gainRatio;
					slices[0] = t1;
					bestEntropy = newEntropy;
				}
			} else {
				ThresholdData td = findBestAttrSlicesRatio(
					trimDataSet(ds2, ds2Index), attrSlices - 1, attrIncrement,
					gfSlices, t1, highBound);
					
				newEntropy += ((((float)ds2Index) / ds.length) *
					td.entropy);

				float[] tempSlices = new float[attrSlices];
				tempSlices[0] = t1;
				for (int i = 0; i < td.slices.length; i++) {
					tempSlices[i+1] = td.slices[i];
				}
				
				float gainRatio = (origEntropy - newEntropy)
					/ calculateSplitInformation(ds, tempSlices);

				if (gainRatio > bestRatio) {
					bestRatio = gainRatio;
					slices = tempSlices;
					bestEntropy = newEntropy;
				}
			}			
		}
	
		return new ThresholdData(slices, bestEntropy, origEntropy, bestRatio);
			
	}

 	public ThresholdData findBestAttrSlices(DataRecordTwoGroup[] dg,
 	 	int attrSlices, float attrIncrement, int gfSlices, float lowBound, 
 	 	float highBound, int[] baseCounts) {
 	 	 	 			 	 	 		
 		float origEntropy = calculateEntropy(dg, baseCounts);
 		 				
 		float bestGain = Float.NEGATIVE_INFINITY;
		float bestEntropy = Float.POSITIVE_INFINITY;

	 	DataRecordTwoGroup[] dg1 = new DataRecordTwoGroup[dg.length];
	 	DataRecordTwoGroup[] dg2 = new DataRecordTwoGroup[dg.length];
		
	 	for (int x = 0; x < dg.length; x++) {
	 		dg1[x] = new DataRecordTwoGroup(dg[x].group, 
	 			new DataRecordTwo[dg[x].dataSet.length]);
	 		dg2[x] = new DataRecordTwoGroup(dg[x].group, 
	 	 		new DataRecordTwo[dg[x].dataSet.length]);
	 	}

		float[] slices = new float[attrSlices];

		for (float t1 = lowBound + attrIncrement; t1 < highBound; 
			t1 += attrIncrement) {

			int dg1Count = 0;
			int dg2Count = 0;

			int[] trimCounts1 = new int[dg.length];
			int[] trimCounts2 = new int[dg.length];
			
			for (int z = 0; z < dg.length; z++) {
				int ds1Index = 0, ds2Index = 0;
			
				for (int x = 0; x < baseCounts[z]; x++) {
					DataRecordTwo dr = dg[z].dataSet[x];
					if (dr.attr1 < t1) {
						dg1[z].dataSet[ds1Index++] = dr;
						dg1Count++;
					} else {
						dg2[z].dataSet[ds2Index++] = dr;
						dg2Count++;
					}
				}

				trimCounts1[z] = ds1Index;
				trimCounts2[z] = ds2Index;
			}
					
			float newEntropy = 
					((((float)dg1Count) / (dg1Count + dg2Count)) * 
						calculateEntropy(dg1, trimCounts1));
			
			if (attrSlices == 1) {
				newEntropy += ((((float)dg2Count) / (dg1Count + dg2Count)) * 
						calculateEntropy(dg2, trimCounts2));

				float[] tempSlices = new float[1];
				tempSlices[0] = t1;
				
				float infoGain = (origEntropy - newEntropy);

				if (infoGain > bestGain) {
					bestGain = infoGain;
					slices[0] = t1;
					bestEntropy = newEntropy;
				}
			} else {
				ThresholdData td = findBestAttrSlices(
					dg2, attrSlices - 1, attrIncrement,
					gfSlices, t1, highBound, trimCounts2);
					
				newEntropy += ((((float)dg2Count) / (dg1Count + dg2Count)) *
					td.entropy);

				float[] tempSlices = new float[attrSlices];
				tempSlices[0] = t1;
				for (int i = 0; i < td.slices.length; i++) {
					tempSlices[i+1] = td.slices[i];
				}
				
				float infoGain = (origEntropy - newEntropy);

				if (infoGain > bestGain) {
					bestGain = infoGain;
					slices = tempSlices;
					bestEntropy = newEntropy;
				}
			}			
		}
	
		return new ThresholdData(slices, bestEntropy, origEntropy, 0);
	}

 	public ThresholdData findBestAttrSlicesRatio(DataRecordTwoGroup[] dg,
 		int attrSlices, float attrIncrement, int gfSlices, float lowBound, 
 		float highBound, int[] baseCounts) {
 	 	 			 	 	 		
	 	float origEntropy = calculateEntropy(dg, baseCounts);
	 				
		float bestRatio = Float.NEGATIVE_INFINITY;
		float bestEntropy = Float.POSITIVE_INFINITY;

 	 	DataRecordTwoGroup[] dg1 = new DataRecordTwoGroup[dg.length];
 	 	DataRecordTwoGroup[] dg2 = new DataRecordTwoGroup[dg.length];
	
 	 	for (int x = 0; x < dg.length; x++) {
 	 		dg1[x] = new DataRecordTwoGroup(dg[x].group, 
 	 			new DataRecordTwo[dg[x].dataSet.length]);
 	 		dg2[x] = new DataRecordTwoGroup(dg[x].group, 
 	 	 		new DataRecordTwo[dg[x].dataSet.length]);
 	 	}

		float[] slices = new float[attrSlices];

		for (float t1 = lowBound + attrIncrement; t1 < highBound; 
			t1 += attrIncrement) {

			int dg1Count = 0;
			int dg2Count = 0;

			int[] trimCounts1 = new int[dg.length];
			int[] trimCounts2 = new int[dg.length];
			
			for (int z = 0; z < dg.length; z++) {
				int ds1Index = 0, ds2Index = 0;
			
				for (int x = 0; x < baseCounts[z]; x++) {
					DataRecordTwo dr = dg[z].dataSet[x];
					if (dr.attr1 < t1) {
						dg1[z].dataSet[ds1Index++] = dr;
						dg1Count++;
					} else {
						dg2[z].dataSet[ds2Index++] = dr;
						dg2Count++;
					}
				}

				trimCounts1[z] = ds1Index;
				trimCounts2[z] = ds2Index;
			}
					
			float newEntropy = 
					((((float)dg1Count) / (dg1Count + dg2Count)) * 
						calculateEntropy(dg1, trimCounts1));
			
			if (attrSlices == 1) {
				newEntropy += ((((float)dg2Count) / (dg1Count + dg2Count)) * 
						calculateEntropy(dg2, trimCounts2));

				float[] tempSlices = new float[1];
				tempSlices[0] = t1;
				
				float gainRatio = (origEntropy - newEntropy)
					/ calculateSplitInformation(dg, tempSlices, baseCounts);

				if (gainRatio > bestRatio) {
					bestRatio = gainRatio;
					slices[0] = t1;
					bestEntropy = newEntropy;
				}
			} else {
				ThresholdData td = findBestAttrSlicesRatio(
					dg2, attrSlices - 1, attrIncrement,
					gfSlices, t1, highBound, trimCounts2);
					
				newEntropy += ((((float)dg2Count) / (dg1Count + dg2Count)) *
					td.entropy);

				float[] tempSlices = new float[attrSlices];
				tempSlices[0] = t1;
				for (int i = 0; i < td.slices.length; i++) {
					tempSlices[i+1] = td.slices[i];
				}
				
				float gainRatio = (origEntropy - newEntropy)
					/ calculateSplitInformation(dg, tempSlices, baseCounts);

				if (gainRatio > bestRatio) {
					bestRatio = gainRatio;
					slices = tempSlices;
					bestEntropy = newEntropy;
				}
			}			
		}
	
		return new ThresholdData(slices, bestEntropy, origEntropy, bestRatio);
	}
 	
	public DataRecordTwo[] dataSetLatVel(String filename, int gfSlices) {
		ArrayList waves = waveSets.get(filename);	
		DataRecordTwo[] drt = new DataRecordTwo[waves.size()];
		
		for (int x = 0; x < waves.size(); x++) {
			drt[x] = parseWaveLatVel((Wave)waves.get(x), gfSlices);
		}		
		
		return drt;
	}

	public DataRecordTwo[] dataSetDistance(String filename, int gfSlices) {
		ArrayList waves = waveSets.get(filename);
		DataRecordTwo[] drt = new DataRecordTwo[waves.size()];
		
		for (int x = 0; x < waves.size(); x++) {
			drt[x] = parseWaveDistance((Wave)waves.get(x), gfSlices);
		}
		
		return drt;
	}
	
	public DataRecordTwo[] dataSetWallDistance(String filename, int gfSlices) {
		ArrayList waves = waveSets.get(filename);
		DataRecordTwo[] drt = new DataRecordTwo[waves.size()];
		
		for (int x = 0; x < waves.size(); x++) {
			drt[x] = parseWaveWallDistance((Wave)waves.get(x), gfSlices);
		}		
		
		return drt;
	}
	
	public DataRecordTwo[] dataSetVChangeTime(String filename, int gfSlices) {
		ArrayList waves = waveSets.get(filename);
		DataRecordTwo[] drt = new DataRecordTwo[waves.size()];
		
		int skips = 0;
		
		for (int x = 0; x < waves.size(); x++) {
			Wave w = (Wave)waves.get(x);
			
			if (w.accel == 1) {
				drt[x - skips] = parseWaveVChangeTime(w, gfSlices);
			} else {
				skips++;
			}
		}
	
		return trimDataSet(drt, drt.length - skips);
	}
	
	public DataRecordTwo parseWaveLatVel(Wave w, int gfSlices) {
		DataRecordTwo drt = new DataRecordTwo();
			                                  
		drt.attr1 = w.latVel;
		drt.output = (int) limit(0, 
			Math.round(w.guessFactor * ((gfSlices - 1) / 2) + (gfSlices - 1)),
			gfSlices - 1);
		
		return drt;
	}
	
	public DataRecordTwo parseWaveDistance(Wave w, int gfSlices) {
		DataRecordTwo drt = new DataRecordTwo();
			                                  
		drt.attr1 = w.distance;
		drt.output = (int) limit(0, 
			Math.round(w.guessFactor * ((gfSlices - 1) / 2) + (gfSlices - 1)),
			gfSlices - 1);
		
		return drt;
	}
	
	public DataRecordTwo parseWaveWallDistance(Wave w, int gfSlices) {
		DataRecordTwo drt = new DataRecordTwo();
			                                  
		drt.attr1 = w.wallDistance;
		drt.output = (int) limit(0, 
			Math.round(w.guessFactor * ((gfSlices - 1) / 2) + (gfSlices - 1)),
			gfSlices - 1);
		
		return drt;
	}

	public DataRecordTwo parseWaveReverseWallDistance(Wave w, int gfSlices) {
		DataRecordTwo drt = new DataRecordTwo();
			                                  
		drt.attr1 = w.reverseWallDistance;
		drt.output = (int) limit(0, 
			Math.round(w.guessFactor * ((gfSlices - 1) / 2) + (gfSlices - 1)),
			gfSlices - 1);
		
		return drt;
	}

	public DataRecordTwo parseWaveVChangeTime(Wave w, int gfSlices) {
		DataRecordTwo drt = new DataRecordTwo();
		
		if (w.accel != 1) {
			return null;
		}
			                                  
		drt.attr1 = ((float)w.timeSinceVChange) / (w.distance / 11);
		drt.output = (int) limit(0, 
			Math.round(w.guessFactor * ((gfSlices - 1) / 2) + (gfSlices - 1)),
			gfSlices - 1);
		
		return drt;
	}
	
	// CREDIT: Taken from PEZ's CassiusClay
	// http://robowiki.net?CassiusClay
    public static int index(float[] slices, float v) {
    	for (int i = 0; i < slices.length; i++) {
    	    if (v < slices[i]) {
    	    	return i;
    	    }
    	}
    	
    	return slices.length;
    }
    
    public static int gfIndex(float guessFactor, int gfSlices) {
    	return (int) limit(0, 
    			Math.round(guessFactor * ((gfSlices - 1) / 2) + (gfSlices - 1)),
    			gfSlices - 1);
    }
    
    private static float limit(float min, float value, float max) {
        return Math.max(min, Math.min(value, max));
    }

    public float calculateEntropy(DataRecordTwo[] d) {   	
    	return calculateEntropy(d, d.length);
    }
    
    public float calculateEntropy(DataRecordTwo[] d, int dataSetLength) {   	
    	int min = 0, max = 0;
    	for (int x = 0; x < dataSetLength; x++) {
    		if (x == 0) {
    			min = max = d[x].output;
    		} else {
    			if (d[x].output > max) {
    				max = d[x].output;
    			}
    			if (d[x].output < min) {
    				min = d[x].output;
    			}
    		}
    	}
    	
    	float[] counts = new float[max - min + 1];
    	
    	for (int x = 0; x < dataSetLength; x++) {
    		counts[d[x].output - min]++;
    	}
    	
    	float entropy = 0;
    	for (int x = 0; x < counts.length; x++) {
    		if (counts[x] != 0) {
    			entropy += (counts[x] / dataSetLength) * Math.log((1 / (counts[x] / dataSetLength)));
    		}
    	}

    	return entropy;
    }
    
    public float calculateEntropy(DataRecordTwoGroup[] dg, int[] dataSetLengths) {
    	float totalEntropy = 0;
    	long groupCount = 0;
    	for (int x = 0; x < dg.length; x++) {
    		if (dg[x] != null) {
    			totalEntropy += calculateEntropy(dg[x].dataSet, dataSetLengths[x]) 
    				* dataSetLengths[x];
    			groupCount += dataSetLengths[x];
    		}
    	}
    	
    	return totalEntropy / groupCount;
    }

    public float calculateSplitInformation(DataRecordTwo[] d, 
        	float[] slices) {   	
    	return calculateSplitInformation(d, slices, d.length);
    }
    
    public float calculateSplitInformation(DataRecordTwo[] d, 
    	float[] slices, int dataSetLength) {   	

    	long[] sliceCounts = new long[slices.length+1];

    	for (int x = 0; x < dataSetLength; x++) {
    		sliceCounts[index(slices, d[x].attr1)]++;
    	}
    	
    	float splitInformation = 0;
    	for (int x = 0; x < sliceCounts.length; x++) {
    		float ratio = ((float)sliceCounts[x]) / dataSetLength;
    		if (sliceCounts[x] != 0) {
    			splitInformation -= ratio * Math.log(ratio);
    		}
    	}
    	
    	return splitInformation;
    }

    public float calculateSplitInformation(DataRecordTwoGroup[] dg,
    	float[] slices, int[] baseCounts) {
    	float totalSplitInformation = 0;
    	long groupCount = 0;
    	
    	for (int x = 0; x < dg.length; x++) {
    		if (dg[x] != null) {
    			totalSplitInformation += calculateSplitInformation(dg[x].dataSet,
    				slices, baseCounts[x]) * baseCounts[x];
    			groupCount += baseCounts[x];
    		}
    	}
    	
    	return totalSplitInformation / groupCount;
    }
    
    public DataRecordTwo[] trimDataSet(DataRecordTwo[] ds, int size) {
    	DataRecordTwo[] newArray = new DataRecordTwo[size];
    	
    	for (int x = 0; x < size; x++) {
    		newArray[x] = ds[x]; 
    	}
    	
    	return newArray;
    }
    
    public DataRecordTwoGroup[] trimDataSets(DataRecordTwoGroup[] dg,
    	int[] sizes) {
    	
    	DataRecordTwoGroup[] newDg = new DataRecordTwoGroup[dg.length];
    	for (int x = 0; x < dg.length; x++) {
    		newDg[x] = new DataRecordTwoGroup(dg[x].group, 
    			trimDataSet(dg[x].dataSet, sizes[x]));
    	}
    	
    	return newDg;
    }
    
    private static double round(double d, int i) {
    	long powerTen = 1;
    	
    	for (int x = 0; x < i; x++) {
    		powerTen *= 10;
    	}
    	
    	return ((double)Math.round(d * powerTen)) / powerTen;
    }
    
    /*
    public static float log2(float d) {
    	return _ln2 * Math.log(d);
    }
    */
}

class Wave {
    byte orientation, roundNum, accel;
    int timeSinceVChange, timeSinceZeroVelocity, timeSinceMaxVelocity;
    float velocity, distance, latVel, reverseWallDistance,
    	wallDistance, relativeHeading;
    float distanceLastEightTicks, distanceLastFifteenTicks,
    	distanceLastTwentyFiveTicks;
    boolean firing = false;
    float guessFactor;
}

class DataRecordTwoGroup {
	int group;
	DataRecordTwo[] dataSet;

	public DataRecordTwoGroup() { }

	public DataRecordTwoGroup(int g, DataRecordTwo[] ds) {
		group = g;
		dataSet = ds;
	}
	
	public Object clone() {
		DataRecordTwo[] newDs = new DataRecordTwo[dataSet.length];
		for (int x = 0; x < dataSet.length; x++) {
			newDs[x] = (DataRecordTwo)dataSet[x].clone();
		}
		
		return new DataRecordTwoGroup(group, newDs);
	}
}

class DataRecordTwo {
	float attr1;
	int output;

	public DataRecordTwo() { }
	
	public DataRecordTwo(float a, int o) {
		attr1 = a;
		output = o;
	}
	
	public Object clone() {
		return new DataRecordTwo(attr1, output);
	}
	
}

class ThresholdData {
	public ThresholdData(float[] sl, float en, float oe) {
		slices = sl;
		entropy = en;
		origEntropy = oe;
	}

	public ThresholdData(float[] sl, float en, float oe, float gr) {
		slices = sl;
		entropy = en;
		origEntropy = oe;
		gainRatio = gr;
	}

	float[] slices;
	float entropy;
	float origEntropy;
	float gainRatio;
	
	public float infoGain() {
		return origEntropy - entropy;
	}
}

/*	
public float[] findBestLatVelSlices(int latSlices, int gfSlices) {
	DataRecordTwo[] ds = dataSetLatVel(gfSlices);
	
	DataRecordTwo[] ds1 = new DataRecordTwo[ds.length];
	DataRecordTwo[] ds2 = new DataRecordTwo[ds.length];
	DataRecordTwo[] ds3 = new DataRecordTwo[ds.length];
	DataRecordTwo[] ds4 = new DataRecordTwo[ds.length];
	              
	float origEntropy = calculateEntropy(ds);
	
	// hard code this for now
	float latVelIncrement = 0.5;
	
	float bestEntropy = Double.POSITIVE_INFINITY;
	
	float[] slices = new float[3];
	
	for (float t1 = latVelIncrement; t1 < 8; t1 += latVelIncrement) {
	for (float t2 = t1 + latVelIncrement; t2 < 8; t2 += latVelIncrement) {
	for (float t3 = t2 + latVelIncrement; t3 < 8; t3 += latVelIncrement) {

		int ds1Index = 0, ds2Index = 0, ds3Index = 0, ds4Index = 0;
		
		for (int x = 0; x < ds.length; x++) {
			DataRecordTwo dr = ds[x];
			if (dr.attr1 < t1) {
				ds1[ds1Index++] = dr;
			} else if (dr.attr1 < t2) {
				ds2[ds2Index++] = dr;
			} else if (dr.attr1 < t3) {
				ds3[ds3Index++] = dr;
			} else {
				ds4[ds4Index++] = dr;
			}
		}
				
		float newEntropy =
			((((float)ds1Index) / ds.length) * 
				calculateEntropy(trimDataSet(ds1, ds1Index))) +
			((((float)ds2Index) / ds.length) *
				calculateEntropy(trimDataSet(ds2, ds2Index))) +
			((((float)ds3Index) / ds.length) *
				calculateEntropy(trimDataSet(ds3, ds3Index))) +
			((((float)ds4Index) / ds.length) *
				calculateEntropy(trimDataSet(ds4, ds4Index)));
		
		if (newEntropy < bestEntropy) {
			bestEntropy = newEntropy;
			slices[0] = t1;
			slices[1] = t2;
			slices[2] = t3;
		}
	}
	}
	}
	
	float infoGain = origEntropy - bestEntropy;
	
	System.out.println("Entropy 1: " + origEntropy);
	System.out.println("Info gain: " + infoGain);
	System.out.println("Entropy 2: " + bestEntropy);
	System.out.println("Best Slices: " + slices[0] + " / " + slices[1] +
			" / " + slices[2]);
			
	return slices;
}
*/

Robo Home | Voidious | Changes | Preferences | AllPages
Edit text of this page | View other revisions
Last edited October 24, 2006 13:02 EST by Voidious (diff)
Search: