import java.io.*; import java.lang.reflect.Field; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.Iterator; import java.util.Random; import java.util.SortedSet; import java.util.TreeSet; public class Read { public static class RoundData { public HashMap<Integer,BidData> Bids; public int timeLimitSeconds; public int numRegions; public int numBids; public int numCompanies; } // this class will result the temperature at a certain point in time // when time approaches the time limit, it will return zero temperature public static class Schedule { private long timeLimitMillis; private long startTimeMillis; private long delta; private FileWriter fw; private BufferedWriter bw; private double startTemperature=1000; public Schedule (long timelimitMillis, long startTimeMillis, double startTemperature) { this.timeLimitMillis = timelimitMillis; this.startTimeMillis = startTimeMillis; this.startTemperature = startTemperature; this.delta = (long) ((this.timeLimitMillis - this.startTimeMillis) * 0.85); if (Read.isDebug) { try { fw = new FileWriter("temperature.csv", false); } catch (IOException e) { // TODO Auto-generated catch block System.out.println("Unable to create temperature file"); e.printStackTrace(); } bw = new BufferedWriter(fw); } } @Override protected void finalize() throws Throwable { if (Read.isDebug) { fw.close(); bw.close(); } super.finalize(); } public double getTemperature() { long currentTime = System.currentTimeMillis(); double currentTemperature = 0; double currentDelta = currentTime - this.startTimeMillis; if (currentDelta > this.delta) { currentTemperature = 0.0; } else { double RC = delta / 2; // currentTemperature = // (( (1.0*(timeLimitMillis - currentTime)) / (timeLimitMillis - startTimeMillis))) * this.startTemperature; currentTemperature = this.startTemperature * Math.exp(-1.0 * currentDelta / RC); } if (Read.isDebug) { try { String out = String.format("%s, %s", (currentTime - this.startTimeMillis) , currentTemperature); bw.write(out); bw.write("\n"); } catch (IOException e) { System.out.println("unable to write to temperature output file"); } } return currentTemperature; } } public static class Node { public SortedSet<BidData> solutionSet; public SortedSet<BidData> remainingSet; public double value; public Node (Node toCopy) { solutionSet = new TreeSet<BidData>(); remainingSet = new TreeSet<BidData>(); solutionSet.addAll(toCopy.solutionSet); remainingSet.addAll(toCopy.remainingSet); value = toCopy.value; } public Node() { solutionSet = new TreeSet<BidData>(); remainingSet = new TreeSet<BidData>(); value = 0; } public Node(SortedSet<BidData> solutionSet, SortedSet<BidData> remainingSet, double value) { this.value = value; this.solutionSet = solutionSet; this.remainingSet = remainingSet; } } public static class SolutionPair { private SortedSet<Integer> bidIDs = new TreeSet<Integer>(); public double value; public double bestRandomAnswer; public void setBids(SortedSet<BidData> solutionSet) { bidIDs.clear(); for (BidData b : solutionSet) { bidIDs.add(b.bidID.intValue()); } } public String bidSetToString() { StringBuilder sb = new StringBuilder(); for (Integer b : bidIDs) { sb.append(b); sb.append(" "); } sb.append("#"); return sb.toString(); } } public static class MethodProfiler { public long ReadBidData; public long GenRandomSolution; public long refreshSolutionSet; public long getBestNeighbor; public long totalRunTime; public long numBadRefreshSolutions; public long numBids; public long numRestarts; public long numBetterSolutions; public long numCallsToGetBestNeighbor; public long numCallsToRefreshSolutionSet; public long timeFoundMaxValue; public long numChoseBadSolution; public long getRandomNeighbour; public long numCallsToGetRandomNeighbor; @Override public String toString() { Class<Read.MethodProfiler> cls = Read.MethodProfiler.class; StringBuilder sb = new StringBuilder(); Field[] fields = cls.getFields(); LinkedList<String> fieldNames = new LinkedList<String>(); for (int i = 0; i < fields.length; i++) { fieldNames.add(fields[i].getName()); } for (String profilerField : fieldNames) { try { Class<?> profilerClass = Read.profiler.getClass(); Field profileField = profilerClass.getDeclaredField(profilerField); String profilerValue = profileField.get(this).toString(); String output = String.format("%s = %s", profilerField, profilerValue); sb.append(output); sb.append(System.getProperty("line.separator")); } catch (Exception e) { e.printStackTrace(); } } /* StringBuilder sb = new StringBuilder(); sb.append("ReadBidData: " + this.ReadBidData + "\n"); sb.append("numBids: " + this.numBids + "\n"); sb.append("GenRandomSolution: " + this.GenRandomSolution + "\n"); sb.append("numBetterSolutions: " + this.numBetterSolutions + "\n"); sb.append("numRestarts: " + this.numRestarts + "\n"); sb.append("refreshSolutionSet: " + this.refreshSolutionSet + " for " + numCallsToRefreshSolutionSet + " times\n"); sb.append("numBadRefreshSolutions: " + this.numBadRefreshSolutions + "\n"); sb.append("getBestNeighbor: " + this.getBestNeighbor + " for " + numCallsToGetBestNeighbor + " times\n"); sb.append("Found best solution at: " + this.timeFoundMaxValue + "\n"); sb.append("TotalRunTime: " + this.totalRunTime + "\n"); */ return sb.toString(); } } public static boolean isDebug = false; public static MethodProfiler profiler = new MethodProfiler(); public static class BidData implements Comparable <BidData> { public HashSet<Integer> region; public Integer company; public Double value; public Integer bidID; public Double normalizedValue; public String toString(){ String s=new String(); s="Company:"+company.toString(); s=s+" Bid Amount:"+value.toString(); s=s+" Regions:"+region.toString(); return s; } @Override public int compareTo(BidData b) { if (this.normalizedValue > b.normalizedValue) { return -1; } else if (this.normalizedValue < b.normalizedValue) { return 1; } else if (this.bidID.equals(b.bidID)) { return 0; } else { return 1; } } @Override public boolean equals (Object other) { if (other == null) return false; if (other == this) return true; if (!(other instanceof BidData))return false; BidData otherMyClass = (BidData)other; return (otherMyClass.bidID.equals(this.bidID)); } } public static boolean ReadFileSorted(String fname, SortedSet<BidData> sortedBids, RoundData roundData, HashMap<Integer, BidData> bidsMap){ try{ long startTime = System.currentTimeMillis(); FileReader input = new FileReader(fname); BufferedReader bufRead = new BufferedReader(input); String line; line = bufRead.readLine(); int count = 0; // Reading lines ending with a # (bids), and store in Bids roundData.timeLimitSeconds = (int) Math.ceil(Double.parseDouble(line) * 60); line = bufRead.readLine(); roundData.numRegions = Integer.parseInt(bufRead.readLine()); line = bufRead.readLine(); roundData.numBids = Integer.parseInt(bufRead.readLine()); Read.profiler.numBids = roundData.numBids; line = bufRead.readLine(); roundData.numCompanies = Integer.parseInt(bufRead.readLine()); //SortedSet<BidData> sortedBids = Bids; while (line != null){ if(line.endsWith("#")){ String[] res=line.split(" "); BidData curbid= new BidData(); curbid.bidID = count; curbid.company=Integer.parseInt(res[0]); curbid.value=Double.parseDouble(res[1]); curbid.region=new HashSet<Integer>(); for(int k=2;k<res.length-1;k++){ curbid.region.add(Integer.parseInt(res[k])); } curbid.normalizedValue = curbid.value / 1; sortedBids.add(curbid); bidsMap.put(count, curbid); count++; } line = bufRead.readLine(); } bufRead.close(); Read.profiler.ReadBidData += System.currentTimeMillis() - startTime; return true; } catch(IOException e){ e.printStackTrace(); return false; } } /*Generate Random Feasible Solution For Problem */ public static double GenRandom(HashMap<Integer,BidData> Bids, LinkedList<Integer> accepted, SortedSet<BidData> solutionSet, SortedSet<BidData> remainingBids){ long startTime = System.currentTimeMillis(); //Set<Integer> Avail=(Bids.keySet()); HashSet<Integer> Avail=new HashSet<Integer>(Bids.keySet()); Random gen=new Random(); Double value=0.0; while(Avail.size()>0){ Integer newbid=gen.nextInt(Avail.size()); newbid=(Integer)Avail.toArray()[newbid]; solutionSet.add(Bids.get(newbid)); value+=Bids.get(newbid).value; accepted.add(newbid); HashSet<Integer> Remove=new HashSet<Integer>(); Iterator<Integer> it=Avail.iterator(); while(it.hasNext()){ Integer k=it.next(); HashSet<Integer> intersection = new HashSet<Integer>(Bids.get(k).region); intersection.retainAll(Bids.get(newbid).region); if((intersection.size()>0) || (Bids.get(newbid).company.equals(Bids.get(k).company))){ Remove.add(k); remainingBids.add(Bids.get(k)); } } Avail.removeAll(Remove); } Collections.sort(accepted); Read.profiler.GenRandomSolution += System.currentTimeMillis() - startTime; return value; } public static void processInputFolderForLocalSearch(String inputFolder, String resultsCsv, String AlgorithmType) throws Exception { StringBuilder CsvHeaders = new StringBuilder(); LinkedList<String> fieldNames = new LinkedList<String>(); FileWriter fw = new FileWriter(resultsCsv, false); BufferedWriter bw = new BufferedWriter(fw); try { CsvHeaders.append("AlgorithmType, InputFileName"); Class<Read.MethodProfiler> cls = Read.MethodProfiler.class; Field[] fields = cls.getFields(); for (int i = 0; i < fields.length; i++) { CsvHeaders.append(", "); CsvHeaders.append(fields[i].getName()); fieldNames.add(fields[i].getName()); } // write out header CsvHeaders.append(", BestRandomValue, MaxValue, SolutionSet\n"); bw.write(CsvHeaders.toString()); File folder = new File(inputFolder); File[] inputFiles = folder.listFiles(); for (File f : inputFiles) { if (f.isFile() && f.getName().toLowerCase().endsWith("txt")) { Read.profiler = new Read.MethodProfiler(); StringBuilder rowResult = new StringBuilder(); File inputFile = new File (folder, f.getName()); File outputFile = new File (folder, f.getName() + ".out.log"); SolutionPair sp = null; if (AlgorithmType.equals("HillClimbRestart")) { sp = doLocalSearch(inputFile.getAbsolutePath(), outputFile.getAbsolutePath()); } else if (AlgorithmType.equals("SimulatedAnnealing")) { sp = doSimulatedAnnealing(inputFile.getAbsolutePath(), outputFile.getAbsolutePath()); } else { throw new Exception("you didn't specify the right algorithm name"); } rowResult.append(AlgorithmType + ", " + f.getName() + ", "); for (String profilerField : fieldNames) { try { Class<?> profilerClass = Read.profiler.getClass(); Field profileField = profilerClass.getDeclaredField(profilerField); String profilerValue = profileField.get(Read.profiler).toString(); rowResult.append(profilerValue); rowResult.append(", "); } catch (Exception e) { e.printStackTrace(); } } rowResult.append(sp.bestRandomAnswer + ", "); rowResult.append(sp.value + ", "); rowResult.append(sp.bidSetToString()); rowResult.append("\n"); bw.write(rowResult.toString()); } } /* public long ReadBidData; public long GenRandomSolution; public long refreshSolutionSet; public long getBestNeighbor; public long totalRunTime; public long numCallsToRefreshSolutionSet; public long numBadRefreshSolutions; public long numCallsToGetBestNeighbor; public long timeFoundMaxValue; */ bw.close(); fw.close(); } catch (IOException e) { System.out.println("unable to create aggregate csv file"); } finally { bw.close(); fw.close(); } } /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { if (args.length == 2) { long startTime = System.currentTimeMillis(); try{ SortedSet<BidData> sortedBids = new TreeSet<BidData>(); HashMap<Integer,BidData> bidsMap = new HashMap<Integer,BidData>(); RoundData roundData = new RoundData(); ReadFileSorted(args[0], sortedBids, roundData, bidsMap); //doLocalSearch(args[0], args[1]); doSimulatedAnnealing(args[0], args[1]); }catch (ArrayIndexOutOfBoundsException e){ System.out.println("Usage: java Read InputFilename OutputFileName\n"); } Read.profiler.totalRunTime = System.currentTimeMillis() - startTime; System.out.println ("ProfileData:\n" + Read.profiler); } else if (args.length == 4) { // we're going to be doing our characterization pass assert(args[0].equals("agg")); // syntax // java Read agg inputFolder outputFile AlgorithmType String inputFolder = args[1]; String outputAggregateFile = args[2]; String algorithName = args[3]; // HillClimbRestart, SimulatedAnnealing processInputFolderForLocalSearch(inputFolder, outputAggregateFile , algorithName); //processInputFolderForLocalSearch(args[1], "algo2.csv" , "SimulatedAnnealing"); } else { System.out.println("Usage:\n" + "java Read inputFile.txt outputFile.txt"); } } public static SolutionPair doLocalSearch(String inputFile, String outputFile) { SortedSet<BidData> sortedBids = new TreeSet<BidData>(); HashMap<Integer,BidData> bidsMap = new HashMap<Integer,BidData>(); RoundData roundData = new RoundData(); LinkedList<Integer> randomAcceptedBidIDs = new LinkedList<Integer>(); SortedSet<Double> foo = new TreeSet<Double>(); ReadFileSorted(inputFile, sortedBids, roundData, bidsMap); long startTimeMillis = System.currentTimeMillis(); long timeLimitMillis = startTimeMillis + (roundData.timeLimitSeconds * 1000) - 200; // get best starting solution double currentBidsValue = 0; double nextBidsValue = 0; double bestBidsValue = 0; // diagnostic information int numRandomRestarts = 0; int numBetterSolutions = 0; SortedSet<BidData> bestSolutionSet = new TreeSet<BidData>(); SortedSet<BidData> solutionSet = new TreeSet<BidData>(); SortedSet<BidData> remainingBids = new TreeSet<BidData>(); nextBidsValue = getBestStartingSolution(sortedBids, solutionSet, remainingBids); System.out.println("Starting localSearch value: " + nextBidsValue); bestBidsValue = nextBidsValue; bestSolutionSet.addAll(solutionSet); while (System.currentTimeMillis() <= timeLimitMillis) { // only stop climbing if we hit a plateau or go downhill while (nextBidsValue > currentBidsValue) { currentBidsValue = nextBidsValue; if (currentBidsValue > bestBidsValue) { numBetterSolutions++; Read.profiler.numBetterSolutions++; bestBidsValue = currentBidsValue; bestSolutionSet.clear(); bestSolutionSet.addAll(solutionSet); Read.profiler.timeFoundMaxValue = System.currentTimeMillis() - startTimeMillis; } nextBidsValue = getBestNeighbor(solutionSet, remainingBids, currentBidsValue, timeLimitMillis); } // reset hill climbing currentBidsValue = 0; solutionSet.clear(); remainingBids.clear(); nextBidsValue = GenRandom(bidsMap, randomAcceptedBidIDs, solutionSet, remainingBids); foo.add(nextBidsValue); numRandomRestarts++; Read.profiler.numRestarts++; } // Write Solution to file System.out.println("Had " + numRandomRestarts + " restarts & " + numBetterSolutions + " better solutions"); logResult(outputFile, bestSolutionSet, bestBidsValue); SolutionPair sp = new SolutionPair(); sp.value = bestBidsValue; sp.setBids(bestSolutionSet); sp.bestRandomAnswer = foo.last().doubleValue(); Read.profiler.totalRunTime = System.currentTimeMillis() - startTimeMillis; return sp; } public static SolutionPair doSimulatedAnnealing(String inputFile, String outputFile) { SortedSet<BidData> sortedBids = new TreeSet<BidData>(); HashMap<Integer,BidData> bidsMap = new HashMap<Integer,BidData>(); RoundData roundData = new RoundData(); LinkedList<Integer> randomAcceptedBidIDs = new LinkedList<Integer>(); SortedSet<Double> foo = new TreeSet<Double>(); ReadFileSorted(inputFile, sortedBids, roundData, bidsMap); long startTimeMillis = System.currentTimeMillis(); long timeLimitMillis = startTimeMillis + (roundData.timeLimitSeconds * 1000) - 200; Schedule sch = new Schedule(timeLimitMillis, startTimeMillis, 10000); // get best starting solution double nextBidsValue = 0; // diagnostic information int numRandomRestarts = 0; int numBetterSolutions = 0; SortedSet<BidData> solutionSet = new TreeSet<BidData>(); SortedSet<BidData> remainingBids = new TreeSet<BidData>(); nextBidsValue = getBestStartingSolution(sortedBids, solutionSet, remainingBids); Node currentNode = new Node(solutionSet, remainingBids, nextBidsValue); Node nextNode; Node bestNodeFound = currentNode; System.out.println("Starting annealing search value: " + currentNode.value); while (System.currentTimeMillis() <= timeLimitMillis) { if (currentNode.value > bestNodeFound.value) { bestNodeFound = currentNode; Read.profiler.timeFoundMaxValue = System.currentTimeMillis() - startTimeMillis; } nextNode = getBestNeighborEx(currentNode, timeLimitMillis); double deltaE = nextNode.value - currentNode.value; if (deltaE > 0) { currentNode = nextNode; profiler.numBetterSolutions++; numBetterSolutions++; } else { double currentTemperature = sch.getTemperature(); // set currentNode to Next with a probability if (shouldUseBadNode(deltaE, currentTemperature)) { profiler.numChoseBadSolution++; currentNode = nextNode; } else { // otherwise generate a random solution Node randomNode = new Node(); nextBidsValue = GenRandom(bidsMap, randomAcceptedBidIDs, randomNode.solutionSet, randomNode.remainingSet); currentNode = randomNode; foo.add(nextBidsValue); numRandomRestarts++; Read.profiler.numRestarts++; } } } // Write Solution to file System.out.println("Had " + numRandomRestarts + " restarts & " + numBetterSolutions + " better solutions"); logResult(outputFile, bestNodeFound.solutionSet, bestNodeFound.value); //System.out.println("Random Values: " + foo); SolutionPair sp = new SolutionPair(); sp.value = bestNodeFound.value; sp.setBids(bestNodeFound.solutionSet); sp.bestRandomAnswer = foo.last().doubleValue(); Read.profiler.totalRunTime = System.currentTimeMillis() - startTimeMillis; return sp; } private static boolean shouldUseBadNode(double deltaE, double currentTemperature) { if (currentTemperature == 0) { return false; } double probabilityOfAcceptance = Math.exp(deltaE / currentTemperature); //System.out.println(deltaE + "," + currentTemperature + "," + Math.exp(deltaE / currentTemperature)); // Random rand = new Random(); double randValue = rand.nextDouble(); return (randValue <= probabilityOfAcceptance); } private static double getBestNeighbor(SortedSet<BidData> inSolutionSet, SortedSet<BidData> inSetRemainingBids, double inSolutionValue, long timeLimitMillis) { double currentBidsValue = 0; long startTime = System.currentTimeMillis(); SortedSet<BidData> remainingBidsCopy = new TreeSet<BidData>(inSetRemainingBids); Iterator <BidData> it = remainingBidsCopy.iterator(); SortedSet<BidData> currentSolutionSet = new TreeSet<BidData>(inSolutionSet); SortedSet<BidData> currentRemainingSet = new TreeSet<BidData>(inSetRemainingBids); int numNeighbours = remainingBidsCopy.size(); float threshold = 1.0f; int numNeighboursToSearch = (int) (numNeighbours * threshold); int numNeighboursSearched = 0; while (it.hasNext() && System.currentTimeMillis() <= timeLimitMillis && numNeighboursSearched <= numNeighboursToSearch) { numNeighboursSearched++; // construct a solution by refreshing the the solution set // because we want to add it.next() to the bid set BidData bidToAdd = it.next(); SortedSet<BidData> outRemainingSet = new TreeSet<BidData>(); SortedSet<BidData> outSolutionSet = new TreeSet<BidData>(); currentBidsValue = refreshSolutionSet(currentSolutionSet, currentRemainingSet, bidToAdd, outSolutionSet, outRemainingSet); if (currentBidsValue > inSolutionValue) { inSolutionSet.clear(); inSetRemainingBids.clear(); inSetRemainingBids.addAll(outRemainingSet); inSolutionSet.addAll(outSolutionSet); inSolutionValue = currentBidsValue; } } Read.profiler.getBestNeighbor += System.currentTimeMillis() - startTime; Read.profiler.numCallsToGetBestNeighbor++; return inSolutionValue; } private static Node getRandomNeighbour(Node baseNode, long timeLimitMillis) { double currentBidsValue = 0; long startTime = System.currentTimeMillis(); Node baseNodeCopy = new Node(baseNode); Node bestNodeFound = new Node(); int numNeighbours = baseNode.remainingSet.size(); // construct a solution by refreshing the the solution set // because we want to add it.next() to the bid set BidData bidToAdd = (BidData) baseNode.remainingSet.toArray()[(int)Math.floor(Math.random() * numNeighbours)]; //BidData bidToAdd = baseNode.remainingSet.first(); SortedSet<BidData> outRemainingSet = new TreeSet<BidData>(); SortedSet<BidData> outSolutionSet = new TreeSet<BidData>(); currentBidsValue = refreshSolutionSet(baseNodeCopy.solutionSet, baseNodeCopy.remainingSet, bidToAdd, outSolutionSet, outRemainingSet); bestNodeFound.solutionSet.clear(); bestNodeFound.solutionSet.addAll(outSolutionSet); bestNodeFound.remainingSet.clear(); bestNodeFound.remainingSet.addAll(outRemainingSet); bestNodeFound.value = currentBidsValue; Read.profiler.getRandomNeighbour += System.currentTimeMillis() - startTime; Read.profiler.numCallsToGetRandomNeighbor++; return bestNodeFound; } private static Node getBestNeighborEx(Node baseNode, long timeLimitMillis) { double currentBidsValue = 0; long startTime = System.currentTimeMillis(); Node baseNodeCopy = new Node(baseNode); Node bestNodeFound = new Node(); Iterator <BidData> it = baseNode.remainingSet.iterator(); int numNeighbours = baseNode.remainingSet.size(); float threshold = 1.0f; int numNeighboursToSearch = (int) (numNeighbours * threshold); int numNeighboursSearched = 0; while (it.hasNext() && System.currentTimeMillis() <= timeLimitMillis && numNeighboursSearched <= numNeighboursToSearch) { numNeighboursSearched++; // construct a solution by refreshing the the solution set // because we want to add it.next() to the bid set BidData bidToAdd = it.next(); SortedSet<BidData> outRemainingSet = new TreeSet<BidData>(); SortedSet<BidData> outSolutionSet = new TreeSet<BidData>(); currentBidsValue = refreshSolutionSet(baseNodeCopy.solutionSet, baseNodeCopy.remainingSet, bidToAdd, outSolutionSet, outRemainingSet); if (currentBidsValue >= bestNodeFound.value) { bestNodeFound.solutionSet.clear(); bestNodeFound.solutionSet.addAll(outSolutionSet); bestNodeFound.remainingSet.clear(); bestNodeFound.remainingSet.addAll(outRemainingSet); bestNodeFound.value = currentBidsValue; } } Read.profiler.getBestNeighbor += System.currentTimeMillis() - startTime; Read.profiler.numCallsToGetBestNeighbor++; return bestNodeFound; } /*** * add a bid to the current solution set. * remove any conflicting bids * * @param currentSolutionSet * @param currentRemainingBids * @param bidToAdd * @param outRemainingSet * @param outSolutionSet * @return value of the solution. */ private static double refreshSolutionSet( SortedSet<BidData> currentSolutionSet, SortedSet<BidData> currentRemainingBids, BidData bidToAdd, SortedSet<BidData> outSolutionSet, SortedSet<BidData> outRemainingSet) { long startTime = System.currentTimeMillis(); SortedSet<BidData> removedBids = new TreeSet<BidData>(); double valueOfUpdatedSolutionSet = 0; Read.profiler.numCallsToRefreshSolutionSet++; HashSet<Integer> companiesFound = new HashSet<Integer>(); HashSet<Integer> regionsCovered = new HashSet<Integer>(); // remove all bids from the current solution set that clash with the bid that is being Added for (BidData b : currentSolutionSet) { if (b.company.equals(bidToAdd.company) || hashSetContainsAny(b.region, bidToAdd.region)) { removedBids.add(b); } else { outSolutionSet.add(b); companiesFound.add(b.company); regionsCovered.addAll(b.region); } } if (!testIfValidSolution(outSolutionSet)) { System.out.println("Bad set 1"); } // now add the new bid outSolutionSet.add(bidToAdd); companiesFound.add(bidToAdd.company); regionsCovered.addAll(bidToAdd.region); if (!testIfValidSolution(outSolutionSet)) { System.out.println("Bad set 2"); } // we now have empty slots, they need to be filled first from // the current remaining bids input for (BidData b : currentRemainingBids) { // add as many of the remaining bids as possible to the set if (companiesFound.contains(b.company) || hashSetContainsAny(b.region, regionsCovered)) { // do nothing outRemainingSet.add(b); } else { outSolutionSet.add(b); companiesFound.add(b.company); regionsCovered.addAll(b.region); } } if (!testIfValidSolution(outSolutionSet)) { System.out.println("Bad set 3"); } SortedSet<BidData> removedBidsCopy = new TreeSet<BidData>(removedBids); for (BidData b : removedBidsCopy) { // add as many of the remaining bids as possible to the set if (companiesFound.contains(b.company) || hashSetContainsAny(b.region, regionsCovered)) { // do nothing } else { outSolutionSet.add(b); removedBids.remove(b); companiesFound.add(b.company); regionsCovered.addAll(b.region); } } if (!testIfValidSolution(outSolutionSet)) { System.out.println("Bad set 4"); } outRemainingSet.addAll(removedBids); for (BidData b : outSolutionSet) { valueOfUpdatedSolutionSet += b.value; } if (Read.isDebug) { if (!Read.testIfValidSolution(outSolutionSet)) { Read.profiler.numBadRefreshSolutions++; //System.out.println("Found invalid solution in refreshSolution"); } } Read.profiler.refreshSolutionSet += System.currentTimeMillis() - startTime; Read.profiler.numCallsToRefreshSolutionSet++; return valueOfUpdatedSolutionSet; } private static boolean testIfValidSolution( SortedSet<BidData> currentSolutionSet) { HashSet<Integer> regions = new HashSet<Integer>(); HashSet<Integer> companies = new HashSet<Integer>(); if (Read.isDebug) { for (BidData b : currentSolutionSet) { if (companies.contains(b.company)) { return false; } else { companies.add(b.company); } if (hashSetContainsAny(b.region, regions)) { return false; } else { regions.addAll(b.region); } } } return true; } private static double getBestStartingSolution( SortedSet<BidData> sortedBids, SortedSet<BidData> solutionSet, SortedSet<BidData> remainingBids) { // list of regions covered // list of companies covered HashSet <Integer> companyAlreadyBid = new HashSet<Integer>(); HashSet <Integer> regionAllocated = new HashSet<Integer>(); double bidsValue = 0; Iterator<BidData> it = sortedBids.iterator(); BidData currBid ; // start with the bid that has the highest normalized value if (it.hasNext()) { currBid = it.next(); companyAlreadyBid.add(currBid.company); regionAllocated.addAll(currBid.region); solutionSet.add(currBid); bidsValue += currBid.value; } while (it.hasNext()) { currBid = it.next(); if (!companyAlreadyBid.contains(currBid.company)) { if (!hashSetContainsAny(currBid.region, regionAllocated)) { companyAlreadyBid.add(currBid.company); regionAllocated.addAll(currBid.region); solutionSet.add(currBid); bidsValue += currBid.value; } else { remainingBids.add(currBid); } } else { remainingBids.add(currBid); } } return bidsValue; } private static boolean hashSetContainsAny(HashSet<Integer> region, HashSet<Integer> regionAllocated) { HashSet<Integer> intersectionRegion = new HashSet<Integer>(region); intersectionRegion.retainAll(regionAllocated); // return true if there is a commonality between the two hashsets return (intersectionRegion.size() > 0); } public static void logResult (String outputFile, SortedSet<BidData> solutionSet, double bidsValue) { if (!testIfValidSolution(solutionSet)) { System.out.println("******* invalid solution ******"); } if (bidsValue != calculateSolutionValue(solutionSet)) { System.out.println("******* solution value <> output value ******"); } System.out.println("Value: " + bidsValue); SortedSet <Integer> sortedBidIDs = new TreeSet<Integer>(); for (BidData b : solutionSet) { sortedBidIDs.add(b.bidID); } WriteOutputFile(outputFile, sortedBidIDs.iterator()); } private static double calculateSolutionValue(SortedSet<BidData> solutionSet) { double valueOfSolutionSet = 0; for (BidData b : solutionSet) { valueOfSolutionSet += b.value; } return valueOfSolutionSet; } public static void WriteOutputFile(String outputFile, Iterator<Integer> it) { try { FileWriter fw = new FileWriter(outputFile, false); BufferedWriter bw = new BufferedWriter(fw); while(it.hasNext()) { Integer i=it.next(); bw.write(i.toString()+" "); System.out.print(i.toString()+" "); } bw.write("#\n"); System.out.print("#\n"); bw.close(); fw.close(); } catch (IOException e) { System.out.println("unable to create output file" + outputFile); } } }