From e02df09c51ce665e166d3b1309b6b025eca4da32 Mon Sep 17 00:00:00 2001 From: StephanPirnbaum Date: Thu, 27 Jul 2017 11:43:53 +0200 Subject: [PATCH] Closes #2 Updated to MQ --- .../ModularizationQualityCalculator.java | 56 +++++++++++++++++++ .../cohesion/LongObjectiveChromosome.java | 17 +++++- .../LongObjectiveCouplingChromosome.java | 14 ++++- .../LongObjectiveSimilarityChromosome.java | 11 +++- .../criterion/cohesion/Partitioner.java | 8 +-- .../sarf/repository/MetricRepository.java | 4 +- src/main/resources/benchmark3.xml | 3 +- src/main/resources/configuration_3.xml | 3 +- 8 files changed, 104 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/buchmais/sarf/benchmark/ModularizationQualityCalculator.java diff --git a/src/main/java/com/buchmais/sarf/benchmark/ModularizationQualityCalculator.java b/src/main/java/com/buchmais/sarf/benchmark/ModularizationQualityCalculator.java new file mode 100644 index 0000000..5fe5059 --- /dev/null +++ b/src/main/java/com/buchmais/sarf/benchmark/ModularizationQualityCalculator.java @@ -0,0 +1,56 @@ +package com.buchmais.sarf.benchmark; + +import com.buchmais.sarf.SARFRunner; +import com.buchmais.sarf.repository.MetricRepository; + +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +/** + * @author Stephan Pirnbaum + */ +public class ModularizationQualityCalculator { + + public static Double computeSimilarityBasedMQ(Map> decomposition) { + Double intraConnectivity = 0d; + Double interConnectivity = 0d; + MetricRepository metricRepository = SARFRunner.xoManager.getRepository(MetricRepository.class); + for (Map.Entry> component1 : decomposition.entrySet()) { + long[] ids1 = component1.getValue().stream().mapToLong(l -> l).toArray(); + int denominator = ids1.length == 1 ? 1 : ((ids1.length * (ids1.length - 1)) / 2); + intraConnectivity += metricRepository.computeSimilarityCohesionInComponent(ids1) / denominator; + for (Map.Entry> component2 : decomposition.entrySet()) { + if (!Objects.equals(component1.getKey(), component2.getKey())) { + long[] ids2 = component2.getValue().stream().mapToLong(l -> l).toArray(); + denominator = ((ids1.length + ids2.length) * (ids1.length + ids2.length - 1)) / 2; + interConnectivity += metricRepository.computeSimilarityCouplingBetweenComponents(ids1, ids2) / denominator; + } + } + } + intraConnectivity /= decomposition.size(); + interConnectivity /= (decomposition.size() * (decomposition.size() - 1)) / 2; + return intraConnectivity - interConnectivity; + } + + public static Double computeCouplingBasedMQ(Map> decomposition) { + Double intraConnectivity = 0d; + Double interConnectivity = 0d; + MetricRepository metricRepository = SARFRunner.xoManager.getRepository(MetricRepository.class); + for (Map.Entry> component1 : decomposition.entrySet()) { + long[] ids1 = component1.getValue().stream().mapToLong(l -> l).toArray(); + int denominator = ids1.length == 1 ? 1 : ((ids1.length * (ids1.length - 1)) / 2); + intraConnectivity += metricRepository.computeCouplingCohesionInComponent(ids1) / denominator; + for (Map.Entry> component2 : decomposition.entrySet()) { + if (!Objects.equals(component1.getKey(), component2.getKey())) { + long[] ids2 = component2.getValue().stream().mapToLong(l -> l).toArray(); + denominator = ((ids1.length + ids2.length) * (ids1.length + ids2.length - 1)) / 2; + interConnectivity += metricRepository.computeCouplingBetweenComponents(ids1, ids2) / denominator; + } + } + } + intraConnectivity /= decomposition.size(); + interConnectivity /= (decomposition.size() * (decomposition.size() - 1)); + return intraConnectivity - interConnectivity; + } +} diff --git a/src/main/java/com/buchmais/sarf/classification/criterion/cohesion/LongObjectiveChromosome.java b/src/main/java/com/buchmais/sarf/classification/criterion/cohesion/LongObjectiveChromosome.java index 81bb340..2e15c41 100644 --- a/src/main/java/com/buchmais/sarf/classification/criterion/cohesion/LongObjectiveChromosome.java +++ b/src/main/java/com/buchmais/sarf/classification/criterion/cohesion/LongObjectiveChromosome.java @@ -2,6 +2,7 @@ import com.buchmais.sarf.SARFRunner; import com.buchmais.sarf.benchmark.MoJoCalculator; +import com.buchmais.sarf.benchmark.ModularizationQualityCalculator; import com.buchmais.sarf.repository.MetricRepository; import com.google.common.collect.Sets; import org.jenetics.LongChromosome; @@ -34,6 +35,8 @@ public abstract class LongObjectiveChromosome extends LongChromosome { private Double componentRangeObjective = 0d; + private Double mQ = 0d; + protected LongObjectiveChromosome(ISeq genes) { super(genes); } @@ -73,7 +76,7 @@ private void evaluate() { } } } - this.couplingObjective /= (identifiedComponents.size() * (identifiedComponents.size() - 1)) / 2; // TODO: 22.07.2017 Improve + this.couplingObjective /= (identifiedComponents.size() * (identifiedComponents.size() - 1)) / 2; // TODO: 27.07.2017 Similarity undirected, coupling directed this.cohesionObjective /= identifiedComponents.size(); //SARFRunner.xoManager.currentTransaction().commit(); // minimize the difference between min and max component size @@ -86,6 +89,7 @@ private void evaluate() { identifiedComponents.size() <= 0.25 * Partitioner.ids.length ? (identifiedComponents.size() / (Partitioner.ids.length / 4d)) : (Partitioner.ids.length - identifiedComponents.size()) / (0.75 * Partitioner.ids.length); + this.mQ = computeMQ(identifiedComponents); if (MoJoCalculator.reference != null) { writeBenchmarkLine(identifiedComponents); } @@ -97,6 +101,8 @@ private void evaluate() { abstract Double computeCoupling(MetricRepository mR, long[] ids1, long[] ids2); + abstract Double computeMQ(Map> decomposition); + protected Double getCohesionObjective() { if (!this.evaluated) evaluate(); return this.cohesionObjective; @@ -122,6 +128,11 @@ protected Double getComponentCountObjective() { return this.componentCountObjective; } + protected Double getMQ() { + if (!this.evaluated) evaluate(); + return this.mQ; + } + /** * * @param chromosome @@ -168,6 +179,8 @@ private void writeBenchmarkLine(Map> identifiedComponents) { Long mojoPlus = Math.min(mojoPlusCompRef, mojoPlusRefComp); Double fitness = this.cohesionObjective + this.couplingObjective + this.componentCountObjective + this.componentRangeObjective + this.componentSizeObjective; + Double mQSim = ModularizationQualityCalculator.computeSimilarityBasedMQ(identifiedComponents); + Double mQCoup = ModularizationQualityCalculator.computeCouplingBasedMQ(identifiedComponents); try(FileWriter fw = new FileWriter("benchmark.csv", true); BufferedWriter bw = new BufferedWriter(fw); PrintWriter out = new PrintWriter(bw)) { @@ -181,6 +194,8 @@ private void writeBenchmarkLine(Map> identifiedComponents) { out.print(mojo + ", "); out.print(mojoFm + ", "); out.print(mojoPlus + ", "); + out.print(mQSim + ", "); + out.print(mQCoup + ", "); out.println(fitness); } catch (IOException e) { } diff --git a/src/main/java/com/buchmais/sarf/classification/criterion/cohesion/LongObjectiveCouplingChromosome.java b/src/main/java/com/buchmais/sarf/classification/criterion/cohesion/LongObjectiveCouplingChromosome.java index 4f0da59..113e5a6 100644 --- a/src/main/java/com/buchmais/sarf/classification/criterion/cohesion/LongObjectiveCouplingChromosome.java +++ b/src/main/java/com/buchmais/sarf/classification/criterion/cohesion/LongObjectiveCouplingChromosome.java @@ -1,10 +1,14 @@ package com.buchmais.sarf.classification.criterion.cohesion; +import com.buchmais.sarf.benchmark.ModularizationQualityCalculator; import com.buchmais.sarf.repository.MetricRepository; import org.jenetics.LongGene; import org.jenetics.util.ISeq; import org.jenetics.util.LongRange; +import java.util.Map; +import java.util.Set; + /** * @author Stephan Pirnbaum */ @@ -24,12 +28,18 @@ public LongObjectiveCouplingChromosome(Long min, Long max) { @Override Double computeCohesion(MetricRepository mR, long[] ids) { - return mR.computeCouplingCohesionInComponent(ids) / ids.length; + int denominator = ids.length == 1 ? 1 : ((ids.length * (ids.length - 1)) / 2); + return mR.computeCouplingCohesionInComponent(ids) / denominator; } @Override Double computeCoupling(MetricRepository mR, long[] ids1, long[] ids2) { - return mR.computeCouplingBetweenComponents(ids1, ids2); + return mR.computeCouplingBetweenComponents(ids1, ids2) / ((ids1.length + ids2.length) * (ids1.length + ids2.length - 1) / 2); + } + + @Override + Double computeMQ(Map> decomposition) { + return ModularizationQualityCalculator.computeCouplingBasedMQ(decomposition); } @Override diff --git a/src/main/java/com/buchmais/sarf/classification/criterion/cohesion/LongObjectiveSimilarityChromosome.java b/src/main/java/com/buchmais/sarf/classification/criterion/cohesion/LongObjectiveSimilarityChromosome.java index 94a29c8..e07a1ca 100644 --- a/src/main/java/com/buchmais/sarf/classification/criterion/cohesion/LongObjectiveSimilarityChromosome.java +++ b/src/main/java/com/buchmais/sarf/classification/criterion/cohesion/LongObjectiveSimilarityChromosome.java @@ -1,10 +1,14 @@ package com.buchmais.sarf.classification.criterion.cohesion; +import com.buchmais.sarf.benchmark.ModularizationQualityCalculator; import com.buchmais.sarf.repository.MetricRepository; import org.jenetics.LongGene; import org.jenetics.util.ISeq; import org.jenetics.util.LongRange; +import java.util.Map; +import java.util.Set; + /** * @author Stephan Pirnbaum */ @@ -30,7 +34,12 @@ Double computeCohesion(MetricRepository mR, long[] ids) { @Override Double computeCoupling(MetricRepository mR, long[] ids1, long[] ids2) { - return mR.computeSimilarityCouplingBetweenComponents(ids1, ids2); + return mR.computeSimilarityCouplingBetweenComponents(ids1, ids2) / ((ids1.length + ids2.length) * (ids1.length + ids2.length - 1) / 2); + } + + @Override + Double computeMQ(Map> decomposition) { + return ModularizationQualityCalculator.computeSimilarityBasedMQ(decomposition); } @Override diff --git a/src/main/java/com/buchmais/sarf/classification/criterion/cohesion/Partitioner.java b/src/main/java/com/buchmais/sarf/classification/criterion/cohesion/Partitioner.java index bce2089..256e40c 100644 --- a/src/main/java/com/buchmais/sarf/classification/criterion/cohesion/Partitioner.java +++ b/src/main/java/com/buchmais/sarf/classification/criterion/cohesion/Partitioner.java @@ -33,15 +33,15 @@ public static Map> partition(long[] ids, Map> in Genotype genotype = createGenotype(initialPartitioning, similarityBased); final Engine engine = Engine .builder(Partitioner::computeFitnessValue, genotype) - .offspringFraction(0.7) + .offspringFraction(0.5) .survivorsSelector(new ParetoFrontierSelector()) .offspringSelector(new ParetoFrontierSelector()) .populationSize(100) .alterers( new MultiPointCrossover<>(1), similarityBased ? - new SimilarityMutator(0.004 * Math.log10(ids.length) / Math.log10(2)) : - new CouplingMutator(0.004 * Math.log10(ids.length) / Math.log10(2)), + new SimilarityMutator(0.008 * Math.log10(ids.length) / Math.log10(2)) : + new CouplingMutator(0.008 * Math.log10(ids.length) / Math.log10(2)), new GaussianMutator<>(0.004 * Math.log10(ids.length) / Math.log10(2))) .executor(Runnable::run) .build(); @@ -94,7 +94,7 @@ private static Genotype createGenotype(Map> initialPar static Double computeFitnessValue(final Genotype prospect) { LongObjectiveChromosome chromosome = (LongObjectiveChromosome) prospect.getChromosome(); - return chromosome.getCohesionObjective() + chromosome.getCouplingObjective() + chromosome.getComponentCountObjective() + chromosome.getComponentRangeObjective() + chromosome.getComponentSizeObjective(); + return chromosome.getMQ(); } private static void update(final EvolutionResult result) { diff --git a/src/main/java/com/buchmais/sarf/repository/MetricRepository.java b/src/main/java/com/buchmais/sarf/repository/MetricRepository.java index 5029081..53e940b 100644 --- a/src/main/java/com/buchmais/sarf/repository/MetricRepository.java +++ b/src/main/java/com/buchmais/sarf/repository/MetricRepository.java @@ -303,7 +303,7 @@ Long countInvokesStatic(@Parameter("t1") Long t1, "WHERE" + " ID(e1) IN {ids1} AND ID(e2) IN {ids2} " + "RETURN" + - " toFloat(SUM(c.coupling) / COUNT(c))") + " toFloat(SUM(c.coupling))") Double computeCouplingBetweenComponents(@Parameter("ids1") long[] ids1, @Parameter("ids2") long[] ids2); @ResultOf @@ -339,7 +339,7 @@ Long countInvokesStatic(@Parameter("t1") Long t1, "WHERE" + " ID(e1) IN {ids1} AND ID(e2) IN {ids2} " + "RETURN" + - " toFloat(SUM(s.similarity)/(COUNT(s) + 0.00000001))") + " toFloat(SUM(s.similarity))") Double computeSimilarityCouplingBetweenComponents(@Parameter("ids1") long[] ids1, @Parameter("ids2") long[] ids2); @ResultOf diff --git a/src/main/resources/benchmark3.xml b/src/main/resources/benchmark3.xml index f12bcd1..382d54d 100644 --- a/src/main/resources/benchmark3.xml +++ b/src/main/resources/benchmark3.xml @@ -1,4 +1,5 @@ - + diff --git a/src/main/resources/configuration_3.xml b/src/main/resources/configuration_3.xml index 2373ba1..40c934b 100644 --- a/src/main/resources/configuration_3.xml +++ b/src/main/resources/configuration_3.xml @@ -1,4 +1,5 @@ - +