From e14d9e81408414f00def8056794af33b7ce045b1 Mon Sep 17 00:00:00 2001 From: antimon Date: Fri, 1 Apr 2011 20:18:22 +0000 Subject: [PATCH] Parallel bee colony algoritmasi (yani.. umarim oyledir. "Haldir Huldur" software engineering practice gururla sunar...). Onceki parallel degil miydi de bu ne? denecek olursa eger, simdi is boka sardi, 3 tane ABC var: - BeeColonyAlgorithm - Bu baya single machine bee colony. - ConcurrentBeeColony - Bu oncekinin uzerinde wrapper olarak calisiyor. Birden fazla makinaya runlari dagitmak icin. Su ana kadarki parallel buydu. - ConcurrentParallelBeeColony - Bu ise yeniden yazildi, populasyonu makinalar bolup calisiyor (umidimi o en azindan). O yuzden ismi Arjantin'li F1 pilotlarini andiriyor. Eger daha iyi isim bulan olursa kendisine mansiyon verecegim. Hedefimiz bir gun ConcurrentParallelParetoMultiDimensionalAllahAllahQueenHoneyBeeAlgorithm yazmak. Henuz o noktaya gelemedik. Pareto front kodunun da bir kismi hazir. Aslinda muhtemelen onun da tumu hazir ama henuz output vermiyor, o yuzden ne kadarinin hazir oldugu konusunda spekulasyon yapmak istemiyorum. Yeni dizi bolumu var mi bakalim... "We're gonna need another Timmy!" - Homeworld Command --- a-cma/data/benchmarks/simple.zip | Bin 46038 -> 0 bytes a-cma/data/user/user.config | Bin 2397 -> 2397 bytes a-cma/src/edu/atilim/acma/Core.java | 2 + .../atilim/acma/ParetoFrontCalculator.java | 87 ++++++ a-cma/src/edu/atilim/acma/RunResult.java | 132 +++++++++ a-cma/src/edu/atilim/acma/Server.java | 1 + .../atilim/acma/metrics/MetricSummary.java | 5 + .../search/ConcurrentParallelBeeColony.java | 251 ++++++++++++++++++ a-cma/src/edu/atilim/acma/ui/DesignPanel.java | 7 +- .../acma/ui/design/DesignPanelBase.java | 9 + 10 files changed, 493 insertions(+), 1 deletion(-) delete mode 100644 a-cma/data/benchmarks/simple.zip create mode 100644 a-cma/src/edu/atilim/acma/ParetoFrontCalculator.java create mode 100644 a-cma/src/edu/atilim/acma/RunResult.java create mode 100644 a-cma/src/edu/atilim/acma/search/ConcurrentParallelBeeColony.java diff --git a/a-cma/data/benchmarks/simple.zip b/a-cma/data/benchmarks/simple.zip deleted file mode 100644 index 298e90464815f360428bfa83a22598f1c0d3ae76..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46038 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%0DuDXmtVmF4vn{v#c?f+-O;|%rQsRU;{V+2 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Ή%kcq17KIpvtWeO+F3zEoQ_)4>#m z-htE)Pa_QE^^UQhX>Wye*guJ99PsbF zOj$PB=s4o=l347FY?`Z?-`~pXt%?XFW=H5D{N<1FOr#@%V8t|0gbLS=c)I_rb^kySeG(#t8X&BulnNa% zakKmSqZei|Sf0ITUi*HVu`hPttHFdO7&xfPDa)>z%077^oNWd?yR1%t-k~Ei_*cG$ ziryLE_2>>#Me-gTmCMPsK~sfb$q84CBsFqcqTJus^A}N3=q`+AD6sofkQx07Lqs^10w- zfUY;g5KU5vu~F+-M6l(CC&Tk+jRbPO2^n|2PPU3q&#r@Apb}IJiw$hz5uJUs`U++c zNjcT%p>^vuRWCw|c|6Uo$t2@)Qe|%g1m`JUQMyP4ah-gri9VO1HTnHRg=FJG$skn2 z{?L<#L`7bm2b}%$Ir;`k`2m?Q_~qo8$fGT3L*yu9+74ANQCevDBINFY8+z;fOSxU* z<>1`)2KKPEHA%paqHGmD#OBz{*=y=F=?uVFSgB;Lx1$Ae=LCD#UW@q-V$%w#0f6lr69Buy8mcyiV;gUxW*ShHx8yC~r(~ z{M|rj8+1#YLQF5CI`gKOiZG)KYjSF~)B>qv$!qsqiF?GZWd~Y9qZgaZK}`Hd2b?cT z5O<-e%BmJP;*a0M?y{##X@XwplT!*EYuJ{a&`9y&B?i-68M6)s&>`jU)!NM6<0l=Y(RoY!{#ihG{FjhgZ|H1F68=|QjT_4n6B?&=L)WHJf9^p+d zIWaF%b>K380ET;xm;t~^q(imN60|g7KO@gT0HUZxtBbU*O;vrH3LtK~?S!ZKWfkJ+ ztC_>Qw`QEEU#f=mpbQN})phcr6nS6NoY`W~Z)GTbR_Vf7k4QN6a(RL%Mmb(&Ss<(jSi8%I$t&ds}QyUQ2q7Vq6nMx{%&IZ+(lBa>-26 zjPUzPPQbir&3@TL^`qR7O#a>tA z=ad9aZDm-&TY#s>Zt6jx6A+VTg^1I@OMJqZPN+QI0$T?&Je=aySN>g1_ov z@+!nBD(MQETVdoYs2L_+maDuP&V=t|BJPqKprqAUV=k2T9M6o} z4J!zzC5;@Xsy;EuTJz*1R)=KC@_>uykJV#36`2b_@-(An=nM}Rk|n&BPMF0)+D;hD zmXgzoH9JbfQxπ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 diff --git a/a-cma/data/user/user.config b/a-cma/data/user/user.config index a1ba4b68d1065285b202596884a398b0046c55ce..2d3d0370ab97bd20cce0e67cacd8cd3a8607fced 100644 GIT binary patch delta 180 zcmcaBbXRCXy}+hz?vjGt{dp@FCayGo;3zV&-@@c~LHVkMr&A1g7#J!F%J~^UfYU3n zEKx5cwW6fBkfDx&X?N)Is2TqfmAm&|xbq~__v2=w5sKf5z2^!i6UJ6%HKS&L_dTr5NuqPPSv05SYB@ Yt#O+30j5OL?j4HPoddwKt?V}#0g%{5bN~PV diff --git a/a-cma/src/edu/atilim/acma/Core.java b/a-cma/src/edu/atilim/acma/Core.java index 4288be8..f32984b 100644 --- a/a-cma/src/edu/atilim/acma/Core.java +++ b/a-cma/src/edu/atilim/acma/Core.java @@ -29,6 +29,8 @@ public static void main(String[] args) throws IOException { runner = new Client(args[1], port); } else if (args[0].equals("-ai")) { runner = new ActionImpactCalculator(); + } else if (args[0].equals("-pf")) { + runner = new ParetoFrontCalculator(); } if (runner == null) { diff --git a/a-cma/src/edu/atilim/acma/ParetoFrontCalculator.java b/a-cma/src/edu/atilim/acma/ParetoFrontCalculator.java new file mode 100644 index 0000000..7b1ee5e --- /dev/null +++ b/a-cma/src/edu/atilim/acma/ParetoFrontCalculator.java @@ -0,0 +1,87 @@ +package edu.atilim.acma; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map.Entry; + +import edu.atilim.acma.metrics.MetricNormalizer; +import edu.atilim.acma.metrics.MetricSummary; +import edu.atilim.acma.ui.ConfigManager; + +public class ParetoFrontCalculator implements Runnable { + @Override + public void run() { + ArrayList results = new ArrayList(); + + System.out.println("Please enter the results folder location: "); + String root = Console.readLine(); + + if (root.length() == 0) { + root = ".//data//results"; + } + + File rd = new File(root); + + try { + if (rd.exists() && rd.isDirectory()) { + for (File inner : rd.listFiles()) { + if (inner.isDirectory()) { + for (File result : inner.listFiles()) { + if (!result.isFile() || !result.getName().endsWith(".txt")) continue; + + results.add(RunResult.readFrom(result.getAbsolutePath())); + } + } + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + + results = getParetoFront(results); + + for (RunResult r : results) { + System.out.println(r.getRunInfo()); + } + } + + private ArrayList getParetoFront(ArrayList res) { + RunConfig config = ConfigManager.getRunConfig("Default"); + ArrayList front = new ArrayList(); + + cur: + for (int i = 0; i < res.size(); i++) { + RunResult cur = res.get(i); + + HashMap curMetrics = MetricNormalizer.normalizeEach(new MetricSummary(cur.getFinalDesign().getMetrics()), config); + + for (int j = 0; j < res.size(); j++) { + if (i == j) continue; + + RunResult check = res.get(j); + + if (!cur.getBenchmark().equalsIgnoreCase(check.getBenchmark())) continue; + + HashMap checkMetrics = MetricNormalizer.normalizeEach(new MetricSummary(check.getFinalDesign().getMetrics()), config); + + boolean paretobetter = true; + + for (Entry metric : checkMetrics.entrySet()) { + double checkVal = metric.getValue(); + double curVal = curMetrics.get(metric.getKey()); + + if (checkVal > curVal) + paretobetter = false; + } + + if (paretobetter) + continue cur; + } + + front.add(cur); + } + + return front; + } +} diff --git a/a-cma/src/edu/atilim/acma/RunResult.java b/a-cma/src/edu/atilim/acma/RunResult.java new file mode 100644 index 0000000..218c934 --- /dev/null +++ b/a-cma/src/edu/atilim/acma/RunResult.java @@ -0,0 +1,132 @@ +package edu.atilim.acma; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.HashMap; +import java.util.UUID; + +public class RunResult { + public class DesignInfo { + private double score; + + private HashMap metrics; + + protected HashMap getMetrics() { + return metrics; + } + + protected double getScore() { + return score; + } + + private DesignInfo() { + metrics = new HashMap(); + } + } + + private enum ReadStage { + HEADER, + INITIAL, + INITIALMETRICS, + FINAL, + FINALMETRICS + } + + public static RunResult readFrom(String file) throws IOException { + BufferedReader br = new BufferedReader(new FileReader(file)); + + RunResult result = new RunResult(); + + ReadStage stage = ReadStage.HEADER; + String line = null; + while ((line = br.readLine()) != null) { + line = line.trim(); + + if (stage == ReadStage.HEADER) { + if (line.startsWith("* Name:")) + result.name = line.substring(8); + else if (line.startsWith("* Run Info:")) + result.runInfo = line.substring(12); + else if (line.startsWith("* Initial Design:")) + stage = ReadStage.INITIAL; + else if (line.startsWith("* Final Design:")) + stage = ReadStage.FINAL; + } else if (stage == ReadStage.INITIAL || stage == ReadStage.FINAL) { + DesignInfo design = stage == ReadStage.INITIAL ? result.initialDesign : result.finalDesign; + + if (line.startsWith("* Score:")) + design.score = Double.parseDouble(line.substring(9).replace(',', '.')); + else if (line.startsWith("* Metric Summary:")) { + if (stage == ReadStage.INITIAL) stage = ReadStage.INITIALMETRICS; + else if (stage == ReadStage.FINAL) stage = ReadStage.FINALMETRICS; + continue; + } + } else if (stage == ReadStage.INITIALMETRICS || stage == ReadStage.FINALMETRICS) { + DesignInfo design = stage == ReadStage.INITIALMETRICS ? result.initialDesign : result.finalDesign; + + if (line.length() == 0) { + stage = ReadStage.HEADER; + continue; + } + + String[] tokens = line.split(" "); + + String mName = tokens[1].trim(); + mName = mName.replace(":", ""); + + double mVal = Double.parseDouble(tokens[2].replace(',', '.')); + + design.metrics.put(mName, mVal); + } + } + + br.close(); + + return result; + } + + private UUID id; + private String name; + private String runInfo; + private DesignInfo initialDesign; + private DesignInfo finalDesign; + + private RunResult() { + id = UUID.randomUUID(); + initialDesign = new DesignInfo(); + finalDesign = new DesignInfo(); + } + + private RunResult(UUID id, String name, String runInfo, DesignInfo initialDesign, DesignInfo finalDesign) { + this.id = id; + this.name = name; + this.runInfo = runInfo; + this.initialDesign = initialDesign; + this.finalDesign = finalDesign; + } + + public String getBenchmark() { + return name.split(" ")[0].trim(); + } + + public DesignInfo getFinalDesign() { + return finalDesign; + } + + public UUID getId() { + return id; + } + + public DesignInfo getInitialDesign() { + return initialDesign; + } + + public String getName() { + return name; + } + + public String getRunInfo() { + return runInfo; + } +} diff --git a/a-cma/src/edu/atilim/acma/Server.java b/a-cma/src/edu/atilim/acma/Server.java index a4dd6b9..c0ce84c 100644 --- a/a-cma/src/edu/atilim/acma/Server.java +++ b/a-cma/src/edu/atilim/acma/Server.java @@ -42,6 +42,7 @@ public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { } } catch (Exception e) { + e.printStackTrace(); String name = String.format("./output/%s_exception.log", UUID.randomUUID().toString()); PrintWriter pw = null; try { diff --git a/a-cma/src/edu/atilim/acma/metrics/MetricSummary.java b/a-cma/src/edu/atilim/acma/metrics/MetricSummary.java index fb064dd..4eab0ec 100644 --- a/a-cma/src/edu/atilim/acma/metrics/MetricSummary.java +++ b/a-cma/src/edu/atilim/acma/metrics/MetricSummary.java @@ -56,6 +56,11 @@ public MetricSummary() { metrics = new HashMap(); } + public MetricSummary(HashMap metrics) { + this(); + this.metrics = metrics; + } + public String getName() { return name; } diff --git a/a-cma/src/edu/atilim/acma/search/ConcurrentParallelBeeColony.java b/a-cma/src/edu/atilim/acma/search/ConcurrentParallelBeeColony.java new file mode 100644 index 0000000..c238ea5 --- /dev/null +++ b/a-cma/src/edu/atilim/acma/search/ConcurrentParallelBeeColony.java @@ -0,0 +1,251 @@ +package edu.atilim.acma.search; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.ArrayList; +import java.util.UUID; + +import edu.atilim.acma.RunConfig; +import edu.atilim.acma.concurrent.Instance; +import edu.atilim.acma.concurrent.InstanceSet; +import edu.atilim.acma.design.Design; +import edu.atilim.acma.util.ACMAUtil; + +public class ConcurrentParallelBeeColony extends ConcurrentAlgorithm { + private static final int randomDepth = 20; + + private static final int COMMAND_GENERATE = 1; + private static final int COMMAND_STEP = 2; + private static final int COMMAND_EXIT = 4; + + private int maxTrials; + private int populationSize; + private int iterations; + private int runCount; + + public ConcurrentParallelBeeColony() { + } + + public ConcurrentParallelBeeColony(String name, RunConfig config, Design initialDesign, int maxTrials, int populationSize, int iterations, int runCount) { + super(name, config, initialDesign); + + this.maxTrials = maxTrials; + this.populationSize = populationSize; + this.iterations = iterations; + this.runCount = runCount; + } + + @Override + public void runMaster(InstanceSet instances) { + for (int run = 0; run < runCount; run++) { + long startTime = System.currentTimeMillis(); + + System.out.printf("Ordering food source generation to %d instances.\n", instances.size()); + + boolean first = true; + int sourcesPerInstance = populationSize / instances.size(); + int remainder = populationSize % instances.size(); + for (Instance i : instances) { + i.send(COMMAND_GENERATE); + + if (first) i.send(sourcesPerInstance + remainder); + else i.send(sourcesPerInstance); + + first = false; + } + + SolutionDesign best = null; + + for (int i = 0; i < iterations; i++) { + System.out.printf("Starting iteration %d, current best score: %.4f.\n", i + 1, best == null ? 0 : best.getScore()); + + instances.broadcast(COMMAND_STEP); + + for (Instance instance : instances) { + SolutionDesign cur = new SolutionDesign(instance.receive(Design.class), getConfig()); + + if (best == null || cur.isBetterThan(best)) + best = cur; + } + instances.broadcast(best.getDesign()); + } + + System.out.printf("Finished %d iterations. Found best design with score: %.6f.\n", iterations, best.getScore()); + + Design bestDesign = best.getDesign(); + bestDesign.setTag(new RunInfoTag(System.currentTimeMillis() - startTime, + String.format("Artificial Bee Colony. Population Size: %d, Max Trials: %d, Iterations: %d.", populationSize, maxTrials, iterations))); + onFinish(bestDesign); + } + + instances.broadcast(COMMAND_EXIT); + } + + @Override + public void runWorker(Instance master) { + ArrayList foods = new ArrayList(); + FoodSource best = null; + + infinite: + while(true) { + int command = master.receive(Integer.class); + + switch(command) { + case COMMAND_GENERATE: + createFoodSources(foods, master.receive(Integer.class)); + break; + case COMMAND_STEP: + sendEmployedBees(foods); + master.send(getBestSource(foods).design.getDesign()); + best = new FoodSource(new SolutionDesign(master.receive(Design.class), getConfig())); + calculateProbabilities(foods, best.getFitness()); + sendOnlookerBees(foods); + sendScoutBees(foods, best.design); + break; + case COMMAND_EXIT: + break infinite; + } + } + + System.out.println("Finalizing..."); + } + + private void createFoodSources(ArrayList foods, int n) { + System.out.printf("Creating %d food sources as initial population.\n", n); + foods.clear(); + + SolutionDesign initial = new SolutionDesign(getInitialDesign(), getConfig()); + for (int i = 0; i < n; i++) { + foods.add(new FoodSource(initial.getRandomNeighbor(randomDepth))); + } + System.out.printf("Created food sources.\n", n); + } + + private void sendEmployedBees(ArrayList foods) { + int better = 0; + + System.out.println("Sending employed bees."); + + for (int i = 0; i < foods.size(); i++) { + FoodSource current = foods.get(i); + FoodSource neighbor = current.mutate(); + + if (neighbor.isBetterThan(current)) { + foods.set(i, neighbor); + better++; + } else { + current.trialCount++; + } + } + } + + private FoodSource getBestSource(ArrayList foods) { + FoodSource best = null; + + for (int i = 0; i < foods.size(); i++) { + FoodSource current = foods.get(i); + + if (best == null || current.getFitness() > best.getFitness()) { + best = current; + } + } + + return best; + } + + private void calculateProbabilities(ArrayList foods, double maxFitness) { + System.out.println("Calculating probabilities."); + + for (int i = 0; i < foods.size(); i++) { + FoodSource current = foods.get(i); + + current.probability = (0.9 * (current.getFitness() / maxFitness)) + 0.1; + } + } + + private void sendOnlookerBees(ArrayList foods) { + System.out.println("Sending onlooker bees."); + + for (int i = 0; i < foods.size(); i++) { + FoodSource current = foods.get(i); + + if (current.probability > ACMAUtil.RANDOM.nextDouble()) { + FoodSource neighbor = current.mutate(); + + if (neighbor.isBetterThan(current)) { + foods.set(i, neighbor); + } else { + current.trialCount++; + } + } + } + } + + private void sendScoutBees(ArrayList foods, SolutionDesign randomSource) { + System.out.println("Sending scout bees."); + + for (int i = 0; i < foods.size(); i++) { + FoodSource current = foods.get(i); + + if (current.trialCount > maxTrials) { + foods.set(i, new FoodSource(randomSource.getRandomNeighbor(randomDepth))); + } + } + } + + @Override + public void writeExternal(ObjectOutput out) throws IOException { + super.writeExternal(out); + + out.writeInt(0); //version + + out.writeInt(maxTrials); + out.writeInt(populationSize); + out.writeInt(iterations); + out.writeInt(runCount); + } + + @Override + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + super.readExternal(in); + + in.readInt(); + maxTrials = in.readInt(); + populationSize = in.readInt(); + iterations = in.readInt(); + runCount = in.readInt(); + } + + private class FoodSource { + private UUID id; + private SolutionDesign design; + private int trialCount; + private double probability; + + private FoodSource(SolutionDesign design) { + this.id = UUID.randomUUID(); + + this.design = design; + this.trialCount = 0; + this.probability = 0.0; + } + + public double getFitness() { + return 1.0 / design.getScore(); + } + + public FoodSource mutate() { + return new FoodSource(design.getRandomNeighbor()); + } + + public boolean isBetterThan(FoodSource other) { + return design.isBetterThan(other.design); + } + + @Override + public int hashCode() { + return id.hashCode(); + } + } +} diff --git a/a-cma/src/edu/atilim/acma/ui/DesignPanel.java b/a-cma/src/edu/atilim/acma/ui/DesignPanel.java index a43112c..afeb3a4 100644 --- a/a-cma/src/edu/atilim/acma/ui/DesignPanel.java +++ b/a-cma/src/edu/atilim/acma/ui/DesignPanel.java @@ -50,6 +50,7 @@ import edu.atilim.acma.search.ConcurrentBeamSearch; import edu.atilim.acma.search.ConcurrentBeeColony; import edu.atilim.acma.search.ConcurrentHillClimbing; +import edu.atilim.acma.search.ConcurrentParallelBeeColony; import edu.atilim.acma.search.ConcurrentRandomSearch; import edu.atilim.acma.search.ConcurrentSimAnn; import edu.atilim.acma.search.ConcurrentStochasticBeamSearch; @@ -171,7 +172,11 @@ public void actionPerformed(ActionEvent e) { int mi = (Integer)abcIterations.getValue(); int mt = (Integer)abcMaxTrials.getValue(); int pc = (Integer)abcPopSize.getValue(); - task = new ConcurrentBeeColony(name, getRunConfig(), design, mt, pc, mi, runs); + + if (abcParallel.isSelected()) + task = new ConcurrentParallelBeeColony(name, getRunConfig(), design, mt, pc, mi, runs); + else + task = new ConcurrentBeeColony(name, getRunConfig(), design, mt, pc, mi, runs); } if (task != null) diff --git a/a-cma/src/edu/atilim/acma/ui/design/DesignPanelBase.java b/a-cma/src/edu/atilim/acma/ui/design/DesignPanelBase.java index 6ec7795..b6ebbd0 100644 --- a/a-cma/src/edu/atilim/acma/ui/design/DesignPanelBase.java +++ b/a-cma/src/edu/atilim/acma/ui/design/DesignPanelBase.java @@ -132,6 +132,8 @@ public class DesignPanelBase extends JPanel { protected JButton abcBtnAddTask; protected JCheckBox bsIsStochastic; protected Component hs100; + protected JCheckBox abcParallel; + protected Component horizontalStrut_2; public DesignPanelBase() { setOpaque(false); @@ -445,6 +447,13 @@ public DesignPanelBase() { algorithmsTabPane.addTab("Artificial Bee Colony", null, beeColonyPanel, null); beeColonyPanel.setLayout(new BoxLayout(beeColonyPanel, BoxLayout.X_AXIS)); + abcParallel = new JCheckBox("Parallel"); + abcParallel.setOpaque(false); + beeColonyPanel.add(abcParallel); + + horizontalStrut_2 = Box.createHorizontalStrut(5); + beeColonyPanel.add(horizontalStrut_2); + lblPopulationSize = new JLabel("Population Size:"); beeColonyPanel.add(lblPopulationSize);