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);
}
}
}