diff --git a/MetaHeuristics4Java-Examples/src/main/java/de/mh4j/examples/qap/model/Facility.java b/MetaHeuristics4Java-Examples/src/main/java/de/mh4j/examples/qap/model/Facility.java new file mode 100644 index 0000000..bd93471 --- /dev/null +++ b/MetaHeuristics4Java-Examples/src/main/java/de/mh4j/examples/qap/model/Facility.java @@ -0,0 +1,32 @@ +package de.mh4j.examples.qap.model; + +import java.util.List; +import java.util.ArrayList; + +public class Facility { + + public final String name; + + List facilitiesCosts = new ArrayList(); + + List facilitiesNames = new ArrayList(); + + static List facilities = new ArrayList(); + + public Facility(String name, List costs, + List facilities_names) { + + this.name = name; + for (int i = 0; i < costs.size(); i++) { + + this.facilitiesCosts.add(costs.get(i)); + + this.facilitiesNames.add(facilities_names.get(i)); + + } + + facilities.add(this); + + } + +} diff --git a/MetaHeuristics4Java-Examples/src/main/java/de/mh4j/examples/qap/model/Location.java b/MetaHeuristics4Java-Examples/src/main/java/de/mh4j/examples/qap/model/Location.java new file mode 100644 index 0000000..05b4353 --- /dev/null +++ b/MetaHeuristics4Java-Examples/src/main/java/de/mh4j/examples/qap/model/Location.java @@ -0,0 +1,31 @@ +package de.mh4j.examples.qap.model; + +import java.util.ArrayList; +import java.util.List; + +public class Location { + + public final String locationName; + + List distances = new ArrayList(); + List distancesNames = new ArrayList(); + + static List locations = new ArrayList(); + + public Location(String locationName, List distances, + List distancesNames) { + + this.locationName = locationName; + + for (int i = 0; i < distances.size(); i++) { + + this.distances.add(distances.get(i)); + + this.distancesNames.add(distancesNames.get(i)); + + } + + locations.add(this); + } + +} diff --git a/MetaHeuristics4Java-Examples/src/main/java/de/mh4j/examples/qap/model/Qap.java b/MetaHeuristics4Java-Examples/src/main/java/de/mh4j/examples/qap/model/Qap.java new file mode 100644 index 0000000..9128335 --- /dev/null +++ b/MetaHeuristics4Java-Examples/src/main/java/de/mh4j/examples/qap/model/Qap.java @@ -0,0 +1,105 @@ +package de.mh4j.examples.qap.model; + +import java.util.ArrayList; +import java.util.List; + +import de.mh4j.solver.Solution; + +/** + * + * The quadratic assignment problem (QAP) is one of fundamental combinatorial + * optimization problems in the branch of optimization or operations research in + * mathematics, from the category of the facilities-location problems. + * + * + * **/ + +public class Qap implements Solution { + + public List solution = new ArrayList<>();; + public int costs = 0; + + public Qap(List solution) { + + for (int i = 0; i < solution.size(); i++) { + + this.solution.add(solution.get(i)); + + } + + calculateCosts(this.solution); + } + + public Qap(Qap original) { + + this.solution = new ArrayList<>(original.solution); + this.costs = original.costs; + } + + /** + * __n__ __n__ + * \ \ + * \ \ Fij*Dp(i)p(j) for minimizing or maximizing the costs + * / / where F are the facilities' flows and D the + * /____ /____ the distances + * i=1 j=1 + * + * + * for example in case of 3 facilities(1,2,3) and 3 locations(A,B,C) this + * method would calculate: f12*dAB+f13*dAC+f21*dBA+f23*dBC+ f31*dCA+f32*dCB + * + * + * */ + + public void calculateCosts(List solution) { + + costs = 0; + + int k = 0; + int m; + + for (int i = 0; i < solution.size(); i++) { + + for (int j = 0; j < Facility.facilities.size(); j++) { + + if (solution.get(i).equals(Facility.facilities.get(j).name)) { + + m = 0; + + for (int l = 0; l < solution.size(); l++) { + + for (int o = 0; o < Facility.facilities.get(j).facilitiesNames + .size(); o++) { + + if (solution.get(l).equals( + Facility.facilities.get(j).facilitiesNames + .get(o))) { + + k = Facility.facilities.get(j).facilitiesCosts + .get(o); + + costs = costs + + k + * Location.locations.get(i).distances + .get(m); + m++; + } + } + } + } + } + } + } + + public int getCosts() { + + return costs; + } + + @Override + public boolean isBetterThan(Qap otherSolution) { + + return otherSolution.getCosts() < costs; + } + +} \ No newline at end of file diff --git a/MetaHeuristics4Java-Examples/src/main/java/de/mh4j/examples/qap/solver/QapCoolingScheme.java b/MetaHeuristics4Java-Examples/src/main/java/de/mh4j/examples/qap/solver/QapCoolingScheme.java new file mode 100644 index 0000000..cdc0731 --- /dev/null +++ b/MetaHeuristics4Java-Examples/src/main/java/de/mh4j/examples/qap/solver/QapCoolingScheme.java @@ -0,0 +1,23 @@ +package de.mh4j.examples.qap.solver; + +import de.mh4j.examples.qap.model.Qap; +import de.mh4j.solver.simulatedAnnealing.AbstractCoolingScheme; + +public class QapCoolingScheme extends AbstractCoolingScheme { + + @Override + protected double getInitialTemperature() { + return 90; + } + + @Override + protected int getInitialEpochLength() { + return 50; + } + + @Override + protected double decreaseTemperature(double currentTemperature) { + return currentTemperature * 0.5; + } + +} diff --git a/MetaHeuristics4Java-Examples/src/main/java/de/mh4j/examples/qap/solver/SimulatedAnnealingQapSolver.java b/MetaHeuristics4Java-Examples/src/main/java/de/mh4j/examples/qap/solver/SimulatedAnnealingQapSolver.java new file mode 100644 index 0000000..c978c7c --- /dev/null +++ b/MetaHeuristics4Java-Examples/src/main/java/de/mh4j/examples/qap/solver/SimulatedAnnealingQapSolver.java @@ -0,0 +1,73 @@ +package de.mh4j.examples.qap.solver; + +import java.util.ArrayList; +import java.util.List; + +import de.mh4j.examples.qap.model.Qap; +import de.mh4j.solver.simulatedAnnealing.AbstractSimulatedAnnealingSolver; +import de.mh4j.solver.termination.StagnationTermination; +import de.mh4j.solver.termination.StepCountTermination; + +public class SimulatedAnnealingQapSolver extends + AbstractSimulatedAnnealingSolver { + + static List locs = new ArrayList(); + + public SimulatedAnnealingQapSolver() { + super(new QapCoolingScheme()); + + addTerminationCondition(new StepCountTermination(this, 50)); + addTerminationCondition(new StagnationTermination(this, 5)); + } + + @Override + protected Qap createRandomNeighbor() { + + Qap neighbor = new Qap(currentSolution); + + return createNeighborFromSwap(neighbor); + + } + + private Qap createNeighborFromSwap(Qap neighbor) { + + int randomIndex1 = randomizer.nextInt(neighbor.solution.size() - 1); + int randomIndex2 = randomizer.nextInt(neighbor.solution.size() - 1); + + while (randomIndex1 == randomIndex2) { + + randomIndex2 = randomizer.nextInt(neighbor.solution.size() - 1); + + } + + String element1 = neighbor.solution.get(randomIndex1); + String element2 = neighbor.solution.get(randomIndex2); + + neighbor.solution.remove(randomIndex1); + neighbor.solution.add(randomIndex1, element2); + + neighbor.solution.remove(randomIndex2); + + neighbor.solution.add(randomIndex2, element1); + + log.trace("Created neighbor from SWAP :"); + + for (int i = 0; i < neighbor.solution.size(); i++) { + log.trace(neighbor.solution.get(i)); + } + + neighbor.calculateCosts(neighbor.solution); + + return neighbor; + + } + + protected Qap createInitialSolution() { + + Qap qap1 = new Qap(locs); + + return qap1; + + } + +} diff --git a/MetaHeuristics4Java-Examples/src/test/java/de/mh4j/examples/qap/model/FacilityTest.java b/MetaHeuristics4Java-Examples/src/test/java/de/mh4j/examples/qap/model/FacilityTest.java new file mode 100644 index 0000000..7db6b79 --- /dev/null +++ b/MetaHeuristics4Java-Examples/src/test/java/de/mh4j/examples/qap/model/FacilityTest.java @@ -0,0 +1,67 @@ +package de.mh4j.examples.qap.model; + +import org.testng.annotations.Test; + +import java.util.List; + +import java.util.ArrayList; + +public class FacilityTest { + + @Test + public void testCreate() { + + String facilityName1 = "1"; + String facilityName2 = "2"; + String facilityName3 = "3"; + String facilityName4 = "4"; + + List cost_list1 = new ArrayList(); + List cost_list2 = new ArrayList(); + List cost_list3 = new ArrayList(); + List cost_list4 = new ArrayList(); + + cost_list1.add(8); + cost_list1.add(1); + cost_list1.add(5); + + cost_list2.add(8); + cost_list2.add(1); + cost_list2.add(1); + + cost_list3.add(1); + cost_list3.add(1); + cost_list3.add(2); + + cost_list4.add(5); + cost_list4.add(1); + cost_list4.add(2); + + List names1 = new ArrayList(); + List names2 = new ArrayList(); + List names3 = new ArrayList(); + List names4 = new ArrayList(); + + names1.add("2"); + names1.add("3"); + names1.add("4"); + + names2.add("1"); + names2.add("3"); + names2.add("4"); + + names3.add("1"); + names3.add("2"); + names3.add("4"); + + names4.add("1"); + names4.add("2"); + names4.add("3"); + + new Facility(facilityName1, cost_list1, names1); + new Facility(facilityName2, cost_list2, names2); + new Facility(facilityName3, cost_list3, names3); + new Facility(facilityName4, cost_list4, names4); + } + +} \ No newline at end of file diff --git a/MetaHeuristics4Java-Examples/src/test/java/de/mh4j/examples/qap/model/LocationTest.java b/MetaHeuristics4Java-Examples/src/test/java/de/mh4j/examples/qap/model/LocationTest.java new file mode 100644 index 0000000..7ada45f --- /dev/null +++ b/MetaHeuristics4Java-Examples/src/test/java/de/mh4j/examples/qap/model/LocationTest.java @@ -0,0 +1,67 @@ +package de.mh4j.examples.qap.model; + +import org.testng.annotations.Test; + +import java.util.List; + +import java.util.ArrayList; + +public class LocationTest { + + @Test + public void testCreate() { + + String locationName1 = "A"; + String locationName2 = "B"; + String locationName3 = "C"; + String locationName4 = "D"; + + List distances1 = new ArrayList(); + List distances2 = new ArrayList(); + List distances3 = new ArrayList(); + List distances4 = new ArrayList(); + + distances1.add(20); + distances1.add(56); + distances1.add(11); + + distances2.add(20); + distances2.add(40); + distances2.add(25); + + distances3.add(56); + distances3.add(40); + distances3.add(54); + + distances4.add(11); + distances4.add(25); + distances4.add(54); + + List distancesNames1 = new ArrayList(); + List distancesNames2 = new ArrayList(); + List distancesNames3 = new ArrayList(); + List distancesNames4 = new ArrayList(); + + distancesNames1.add("B"); + distancesNames1.add("C"); + distancesNames1.add("D"); + + distancesNames2.add("A"); + distancesNames2.add("C"); + distancesNames2.add("D"); + + distancesNames3.add("A"); + distancesNames3.add("B"); + distancesNames3.add("D"); + + distancesNames4.add("A"); + distancesNames4.add("B"); + distancesNames4.add("C"); + + new Location(locationName1, distances1, distancesNames1); + new Location(locationName2, distances2, distancesNames2); + new Location(locationName3, distances3, distancesNames3); + new Location(locationName4, distances4, distancesNames4); + } + +} \ No newline at end of file diff --git a/MetaHeuristics4Java-Examples/src/test/java/de/mh4j/examples/qap/model/QapTest.java b/MetaHeuristics4Java-Examples/src/test/java/de/mh4j/examples/qap/model/QapTest.java new file mode 100644 index 0000000..ca3a0de --- /dev/null +++ b/MetaHeuristics4Java-Examples/src/test/java/de/mh4j/examples/qap/model/QapTest.java @@ -0,0 +1,140 @@ +package de.mh4j.examples.qap.model; + +import static org.testng.Assert.assertTrue; + +import org.testng.annotations.Test; + +import java.util.List; + +import java.util.ArrayList; + +public class QapTest { + + @Test + public void testCreate() { + + String facilityName1 = "1"; + String facilityName2 = "2"; + String facilityName3 = "3"; + String facilityName4 = "4"; + + List cost_list1 = new ArrayList(); + List cost_list2 = new ArrayList(); + List cost_list3 = new ArrayList(); + List cost_list4 = new ArrayList(); + + cost_list1.add(8); + cost_list1.add(1); + cost_list1.add(5); + + cost_list2.add(8); + cost_list2.add(1); + cost_list2.add(1); + + cost_list3.add(1); + cost_list3.add(1); + cost_list3.add(2); + + cost_list4.add(5); + cost_list4.add(1); + cost_list4.add(2); + + List names1 = new ArrayList(); + List names2 = new ArrayList(); + List names3 = new ArrayList(); + List names4 = new ArrayList(); + + names1.add("2"); + names1.add("3"); + names1.add("4"); + + names2.add("1"); + names2.add("3"); + names2.add("4"); + + names3.add("1"); + names3.add("2"); + names3.add("4"); + + names4.add("1"); + names4.add("2"); + names4.add("3"); + + new Facility(facilityName1, cost_list1, names1); + new Facility(facilityName2, cost_list2, names2); + new Facility(facilityName3, cost_list3, names3); + new Facility(facilityName4, cost_list4, names4); + + String locationName1 = "A"; + String locationName2 = "B"; + String locationName3 = "C"; + String locationName4 = "D"; + + List distances1 = new ArrayList(); + List distances2 = new ArrayList(); + List distances3 = new ArrayList(); + List distances4 = new ArrayList(); + + distances1.add(20); + distances1.add(56); + distances1.add(11); + + distances2.add(20); + distances2.add(40); + distances2.add(25); + + distances3.add(56); + distances3.add(40); + distances3.add(54); + + distances4.add(11); + distances4.add(25); + distances4.add(54); + + List distancesNames1 = new ArrayList(); + List distancesNames2 = new ArrayList(); + List distancesNames3 = new ArrayList(); + List distancesNames4 = new ArrayList(); + + distancesNames1.add("B"); + distancesNames1.add("C"); + distancesNames1.add("D"); + + distancesNames2.add("A"); + distancesNames2.add("C"); + distancesNames2.add("D"); + + distancesNames3.add("A"); + distancesNames3.add("B"); + distancesNames3.add("D"); + + distancesNames4.add("A"); + distancesNames4.add("B"); + distancesNames4.add("C"); + + new Location(locationName1, distances1, distancesNames1); + new Location(locationName2, distances2, distancesNames2); + new Location(locationName3, distances3, distancesNames3); + new Location(locationName4, distances4, distancesNames4); + + List locs = new ArrayList(); + + locs.add("1"); + locs.add("2"); + locs.add("4"); + locs.add("3"); + + List locs2 = new ArrayList(); + locs2.add("2"); + locs2.add("1"); + locs2.add("4"); + locs2.add("3"); + + Qap qap1 = new Qap(locs); + Qap qap2 = new Qap(locs2); + + assertTrue(qap1.isBetterThan(qap2)); + + } + +} \ No newline at end of file diff --git a/MetaHeuristics4Java-Examples/src/test/java/de/mh4j/examples/qap/solver/SimulatedAnnealingQapSolverTest.java b/MetaHeuristics4Java-Examples/src/test/java/de/mh4j/examples/qap/solver/SimulatedAnnealingQapSolverTest.java new file mode 100644 index 0000000..57c9a0d --- /dev/null +++ b/MetaHeuristics4Java-Examples/src/test/java/de/mh4j/examples/qap/solver/SimulatedAnnealingQapSolverTest.java @@ -0,0 +1,138 @@ +package de.mh4j.examples.qap.solver; + +import java.util.ArrayList; +import java.util.List; + +import org.testng.annotations.Test; + +import ch.qos.logback.classic.Level; + +import de.mh4j.examples.qap.model.Facility; +import de.mh4j.examples.qap.model.Location; + +import de.mh4j.examples.qap.solver.SimulatedAnnealingQapSolver; + +public class SimulatedAnnealingQapSolverTest { + + @Test + public void testSolveSimpleInstance() { + + String facilityName1 = "1"; + String facilityName2 = "2"; + String facilityName3 = "3"; + String facilityName4 = "4"; + + List cost_list1 = new ArrayList(); + List cost_list2 = new ArrayList(); + List cost_list3 = new ArrayList(); + List cost_list4 = new ArrayList(); + + cost_list1.add(8); + cost_list1.add(1); + cost_list1.add(5); + + cost_list2.add(8); + cost_list2.add(1); + cost_list2.add(1); + + cost_list3.add(1); + cost_list3.add(1); + cost_list3.add(2); + + cost_list4.add(5); + cost_list4.add(1); + cost_list4.add(2); + + List names1 = new ArrayList(); + List names2 = new ArrayList(); + List names3 = new ArrayList(); + List names4 = new ArrayList(); + + names1.add("2"); + names1.add("3"); + names1.add("4"); + + names2.add("1"); + names2.add("3"); + names2.add("4"); + + names3.add("1"); + names3.add("2"); + names3.add("4"); + + names4.add("1"); + names4.add("2"); + names4.add("3"); + + new Facility(facilityName1, cost_list1, names1); + new Facility(facilityName2, cost_list2, names2); + new Facility(facilityName3, cost_list3, names3); + new Facility(facilityName4, cost_list4, names4); + + String locationName1 = "A"; + String locationName2 = "B"; + String locationName3 = "C"; + String locationName4 = "D"; + + List distances1 = new ArrayList(); + List distances2 = new ArrayList(); + List distances3 = new ArrayList(); + List distances4 = new ArrayList(); + + distances1.add(20); + distances1.add(56); + distances1.add(11); + + distances2.add(20); + distances2.add(40); + distances2.add(25); + + distances3.add(56); + distances3.add(40); + distances3.add(54); + + distances4.add(11); + distances4.add(25); + distances4.add(54); + + List distancesNames1 = new ArrayList(); + List distancesNames2 = new ArrayList(); + List distancesNames3 = new ArrayList(); + List distancesNames4 = new ArrayList(); + + distancesNames1.add("B"); + distancesNames1.add("C"); + distancesNames1.add("D"); + + distancesNames2.add("A"); + distancesNames2.add("C"); + distancesNames2.add("D"); + + distancesNames3.add("A"); + distancesNames3.add("B"); + distancesNames3.add("D"); + + distancesNames4.add("A"); + distancesNames4.add("B"); + distancesNames4.add("C"); + + new Location(locationName1, distances1, distancesNames1); + new Location(locationName2, distances2, distancesNames2); + new Location(locationName3, distances3, distancesNames3); + new Location(locationName4, distances4, distancesNames4); + + SimulatedAnnealingQapSolver solver = new SimulatedAnnealingQapSolver(); + + SimulatedAnnealingQapSolver.locs.add("1"); + SimulatedAnnealingQapSolver.locs.add("2"); + SimulatedAnnealingQapSolver.locs.add("4"); + SimulatedAnnealingQapSolver.locs.add("3"); + + solver.createInitialSolution(); + + solver.setLogLevel(Level.TRACE); + solver.run(); + + } + +}