From 489fa41036b312f27d501cddd395f72d59288eda Mon Sep 17 00:00:00 2001 From: afroggattsl Date: Wed, 11 Sep 2019 11:25:30 +0100 Subject: [PATCH 1/2] feat(#1306): remove ability to turn off partitioning and optimising --- .../generation/GenerationConfigSource.java | 2 -- .../guice/DecisionTreeOptimiserProvider.java | 12 +---------- .../guice/TreePartitioningProvider.java | 13 ++---------- .../generate/GenerateCommandLine.java | 21 ------------------- .../utils/CucumberGenerationConfigSource.java | 10 --------- 5 files changed, 3 insertions(+), 55 deletions(-) diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/GenerationConfigSource.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/GenerationConfigSource.java index 5e899a15f..b12943ee4 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/GenerationConfigSource.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/GenerationConfigSource.java @@ -24,7 +24,5 @@ public interface GenerationConfigSource { long getMaxRows(); MonitorType getMonitorType(); - boolean shouldDoPartitioning(); boolean requireFieldTyping(); - boolean dontOptimise(); } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/guice/DecisionTreeOptimiserProvider.java b/generator/src/main/java/com/scottlogic/deg/generator/guice/DecisionTreeOptimiserProvider.java index 1313486e6..635f888e3 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/guice/DecisionTreeOptimiserProvider.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/guice/DecisionTreeOptimiserProvider.java @@ -16,26 +16,16 @@ package com.scottlogic.deg.generator.guice; -import com.google.inject.Inject; import com.google.inject.Provider; import com.scottlogic.deg.generator.decisiontree.DecisionTreeOptimiser; import com.scottlogic.deg.generator.decisiontree.MostProlificConstraintOptimiser; -import com.scottlogic.deg.generator.decisiontree.NoopDecisionTreeOptimiser; -import com.scottlogic.deg.generator.generation.GenerationConfigSource; public class DecisionTreeOptimiserProvider implements Provider { - private final GenerationConfigSource configSource; - - @Inject - public DecisionTreeOptimiserProvider(GenerationConfigSource configSource) { - this.configSource = configSource; + public DecisionTreeOptimiserProvider() { } @Override public DecisionTreeOptimiser get() { - if(configSource.dontOptimise()) { - return new NoopDecisionTreeOptimiser(); - } return new MostProlificConstraintOptimiser(); } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/guice/TreePartitioningProvider.java b/generator/src/main/java/com/scottlogic/deg/generator/guice/TreePartitioningProvider.java index df595c696..4fe403e21 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/guice/TreePartitioningProvider.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/guice/TreePartitioningProvider.java @@ -16,26 +16,17 @@ package com.scottlogic.deg.generator.guice; -import com.google.inject.Inject; import com.google.inject.Provider; -import com.scottlogic.deg.generator.decisiontree.treepartitioning.NoopTreePartitioner; import com.scottlogic.deg.generator.decisiontree.treepartitioning.RelatedFieldTreePartitioner; import com.scottlogic.deg.generator.decisiontree.treepartitioning.TreePartitioner; -import com.scottlogic.deg.generator.generation.GenerationConfigSource; public class TreePartitioningProvider implements Provider { - private final GenerationConfigSource configSource; - @Inject - public TreePartitioningProvider(GenerationConfigSource configSource) { - this.configSource = configSource; + public TreePartitioningProvider() { } @Override public TreePartitioner get() { - if (configSource.shouldDoPartitioning()){ - return new RelatedFieldTreePartitioner(); - } - return new NoopTreePartitioner(); + return new RelatedFieldTreePartitioner(); } } diff --git a/orchestrator/src/main/java/com/scottlogic/deg/orchestrator/generate/GenerateCommandLine.java b/orchestrator/src/main/java/com/scottlogic/deg/orchestrator/generate/GenerateCommandLine.java index 5c6c6c9e2..663f3b1c5 100644 --- a/orchestrator/src/main/java/com/scottlogic/deg/orchestrator/generate/GenerateCommandLine.java +++ b/orchestrator/src/main/java/com/scottlogic/deg/orchestrator/generate/GenerateCommandLine.java @@ -75,12 +75,6 @@ private void checkForAlphaGenerationDataTypes() { description = "The path to write the generated data file to.") private Path outputPath; - @CommandLine.Option( - names = {"--no-optimise"}, - description = "Prevents tree optimisation", - hidden = true) - boolean dontOptimise; - @CommandLine.Option( names = "--help", usageHelp = true, @@ -106,12 +100,6 @@ private void checkForAlphaGenerationDataTypes() { description = "Determines the type of combination strategy used (${COMPLETION-CANDIDATES})") private CombinationStrategyType combinationType = MINIMAL; - @CommandLine.Option( - names = {"--no-partition"}, - description = "Prevents tree partitioning", - hidden = true) - private boolean dontPartitionTrees; - @CommandLine.Option( names = {"-n", "--max-rows"}, description = "Defines the maximum number of rows that should be generated") @@ -149,15 +137,6 @@ private void checkForAlphaGenerationDataTypes() { ) private String fromFilePath = ""; - public boolean shouldDoPartitioning() { - return !this.dontPartitionTrees; - } - - @Override - public boolean dontOptimise() { - return this.dontOptimise; - } - @Override public File getProfileFile() { return this.profileFile; diff --git a/orchestrator/src/test/java/com/scottlogic/deg/orchestrator/cucumber/testframework/utils/CucumberGenerationConfigSource.java b/orchestrator/src/test/java/com/scottlogic/deg/orchestrator/cucumber/testframework/utils/CucumberGenerationConfigSource.java index 9667b7c10..2acb067e8 100644 --- a/orchestrator/src/test/java/com/scottlogic/deg/orchestrator/cucumber/testframework/utils/CucumberGenerationConfigSource.java +++ b/orchestrator/src/test/java/com/scottlogic/deg/orchestrator/cucumber/testframework/utils/CucumberGenerationConfigSource.java @@ -67,16 +67,6 @@ public long getMaxRows() { return state.maxRows; } - @Override - public boolean shouldDoPartitioning() { - return false; - } - - @Override - public boolean dontOptimise() { - return false; - } - @Override public Path getOutputPath() { return new File("mockFilePath").toPath(); From 90c5b59b74dc757201f5f3962754b2c81174d4d0 Mon Sep 17 00:00:00 2001 From: afroggattsl Date: Wed, 11 Sep 2019 13:32:33 +0100 Subject: [PATCH 2/2] feat(#1306): remove ability to turn off partitioning and optimising * got rid of providers and unnecessary interface and implementation of optimiser and partitioner --- .../decisiontree/DecisionTreeOptimiser.java | 219 +++++++++++++++- .../MostProlificConstraintOptimiser.java | 237 ------------------ .../NoopDecisionTreeOptimiser.java | 25 -- .../treepartitioning/NoopTreePartitioner.java | 28 --- .../RelatedFieldTreePartitioner.java | 193 -------------- .../treepartitioning/TreePartitioner.java | 170 ++++++++++++- .../generation/DecisionTreeDataGenerator.java | 4 +- .../guice/DecisionTreeOptimiserProvider.java | 31 --- .../deg/generator/guice/GeneratorModule.java | 6 +- .../guice/TreePartitioningProvider.java | 32 --- ...st.java => DecisionTreeOptimiserTest.java} | 4 +- ...erTests.java => TreePartitionerTests.java} | 4 +- 12 files changed, 392 insertions(+), 561 deletions(-) delete mode 100644 generator/src/main/java/com/scottlogic/deg/generator/decisiontree/MostProlificConstraintOptimiser.java delete mode 100644 generator/src/main/java/com/scottlogic/deg/generator/decisiontree/NoopDecisionTreeOptimiser.java delete mode 100644 generator/src/main/java/com/scottlogic/deg/generator/decisiontree/treepartitioning/NoopTreePartitioner.java delete mode 100644 generator/src/main/java/com/scottlogic/deg/generator/decisiontree/treepartitioning/RelatedFieldTreePartitioner.java delete mode 100644 generator/src/main/java/com/scottlogic/deg/generator/guice/DecisionTreeOptimiserProvider.java delete mode 100644 generator/src/main/java/com/scottlogic/deg/generator/guice/TreePartitioningProvider.java rename generator/src/test/java/com/scottlogic/deg/generator/decisiontree/{MostProlificConstraintOptimiserTest.java => DecisionTreeOptimiserTest.java} (97%) rename generator/src/test/java/com/scottlogic/deg/generator/decisiontree/treepartitioning/{RelatedFieldTreePartitionerTests.java => TreePartitionerTests.java} (99%) diff --git a/generator/src/main/java/com/scottlogic/deg/generator/decisiontree/DecisionTreeOptimiser.java b/generator/src/main/java/com/scottlogic/deg/generator/decisiontree/DecisionTreeOptimiser.java index b453cccda..018a06874 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/decisiontree/DecisionTreeOptimiser.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/decisiontree/DecisionTreeOptimiser.java @@ -16,6 +16,221 @@ package com.scottlogic.deg.generator.decisiontree; -public interface DecisionTreeOptimiser { - DecisionTree optimiseTree(DecisionTree tree); +import com.scottlogic.deg.common.profile.constraints.atomic.AtomicConstraint; +import com.scottlogic.deg.common.profile.constraints.atomic.NotConstraint; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class DecisionTreeOptimiser { + private static final int MAX_ITERATIONS = 50; + + public DecisionTree optimiseTree(DecisionTree tree){ + ConstraintNode newRootNode = optimiseLevelOfTree(tree.getRootNode()); + return new DecisionTree(newRootNode, tree.getFields()); + } + + private ConstraintNode optimiseLevelOfTree(ConstraintNode rootNode){ + for (int iteration = 0; iteration < MAX_ITERATIONS; iteration++) { + ConstraintNode newRootNode = optimiseDecisions(rootNode); + + if (noChangeInDecisionCount(rootNode, newRootNode)) { + return newRootNode; + } + + rootNode = newRootNode; + } + + return rootNode; + } + + private boolean noChangeInDecisionCount(ConstraintNode rootNode, ConstraintNode newRootNode) { + return newRootNode.getDecisions().size() == rootNode.getDecisions().size(); + } + + private ConstraintNode optimiseDecisions(ConstraintNode rootNode){ + AtomicConstraint mostProlificAtomicConstraint = getMostProlificAtomicConstraint(rootNode.getDecisions()); + if (mostProlificAtomicConstraint == null){ + return rootNode; + } + // Add negation of most prolific constraint to new decision node + AtomicConstraint negatedMostProlificConstraint = mostProlificAtomicConstraint.negate(); + + List factorisableDecisionNodes = rootNode.getDecisions().stream() + .filter(node -> this.decisionIsFactorisable(node, mostProlificAtomicConstraint, negatedMostProlificConstraint)) + .collect(Collectors.toList()); + if (factorisableDecisionNodes.size() < 2){ + return rootNode; + } + + // Add most prolific constraint to new decision node + ConstraintNode factorisingConstraintNode = new ConstraintNodeBuilder().addAtomicConstraints(mostProlificAtomicConstraint).build(); + ConstraintNode negatedFactorisingConstraintNode = new ConstraintNodeBuilder().addAtomicConstraints(negatedMostProlificConstraint).build(); + + Set otherOptions = new HashSet<>(); + Set decisionsToRemove = new HashSet<>(); + + for (DecisionNode decision : factorisableDecisionNodes) { + DecisionAnalyser analyser = new DecisionAnalyser(decision, mostProlificAtomicConstraint); + DecisionAnalysisResult result = analyser.performAnalysis(); + + // Perform movement of options + factorisingConstraintNode = addOptionsAsDecisionUnderConstraintNode(factorisingConstraintNode, result.optionsToFactorise); + negatedFactorisingConstraintNode = addOptionsAsDecisionUnderConstraintNode(negatedFactorisingConstraintNode, result.negatedOptionsToFactorise); + otherOptions.addAll(result.adjacentOptions); + decisionsToRemove.add(decision); + } + + // Add new decision node + DecisionNode factorisedDecisionNode = new DecisionNode( + Stream.concat( + Stream.of( + optimiseLevelOfTree(factorisingConstraintNode), + optimiseLevelOfTree(negatedFactorisingConstraintNode)), + otherOptions.stream()) + .collect(Collectors.toList())); + + return rootNode.builder() + .removeDecisions(decisionsToRemove) + .addDecision(factorisedDecisionNode).build(); + } + + private boolean constraintNodeContainsNegatedConstraints(ConstraintNode node, Set constraints){ + return node.getAtomicConstraints().stream() + .map(AtomicConstraint::negate) + .allMatch(constraints::contains); + } + + private ConstraintNode addOptionsAsDecisionUnderConstraintNode( + ConstraintNode newNode, + Collection optionsToAdd) { + if (optionsToAdd.isEmpty()) { + return newNode; + } + + return newNode.builder().addDecision(new DecisionNode(optionsToAdd)).build(); + } + + private int disfavourNotConstraints(Map.Entry> entry){ + return entry.getKey() instanceof NotConstraint ? 1 : 0; + } + + private AtomicConstraint getMostProlificAtomicConstraint(Collection decisions) { + Map> decisionConstraints = + decisions.stream() + .flatMap(dn -> dn.getOptions().stream()) + .flatMap(option -> option.getAtomicConstraints().stream()) + .collect(Collectors.groupingBy(Function.identity())); + + Comparator>> comparator = Comparator + .comparing(entry -> entry.getValue().size()); + comparator = comparator.reversed() + .thenComparing(this::disfavourNotConstraints) + .thenComparing(entry -> entry.getKey().toString()); + + return decisionConstraints.entrySet() + .stream() + .filter(constraint -> constraint.getValue().size() > 1) // where the number of occurrences > 1 + .sorted(comparator) + .map(entry -> getConstraint(entry.getValue())) + .findFirst() + .orElse(null); //otherwise return null + } + + private AtomicConstraint getConstraint(List identicalAtomicConstraints) { + return identicalAtomicConstraints.iterator().next(); + } + + private boolean decisionIsFactorisable(DecisionNode decision, AtomicConstraint factorisingConstraint, AtomicConstraint negatedFactorisingConstraint){ + // The decision should contain ONE option with the MPC + boolean optionWithMPCExists = decision.getOptions().stream() + .filter(option -> atomicConstraintExists(option, factorisingConstraint)) + .count() == 1; + + // The decision should contain ONE separate option with the negated MPC (which is atomic). + boolean optionWithNegatedMPCExists = decision.getOptions().stream() + .filter(option -> atomicConstraintExists(option, negatedFactorisingConstraint) && option.getAtomicConstraints().size() == 1) + .count() == 1; + + return optionWithMPCExists && optionWithNegatedMPCExists; + } + + private boolean atomicConstraintExists(ConstraintNode atomicConstraints, AtomicConstraint constraint) { + return atomicConstraints.getAtomicConstraints().stream() + .anyMatch(c -> c.equals(constraint)); + } + + class DecisionAnalyser { + private DecisionNode decision; + private AtomicConstraint factorisingConstraint; + private AtomicConstraint negatedFactorisingConstraint; + private Set atomicConstraintsAssociatedWithFactorisingOption = new HashSet<>(); + private Set atomicConstraintsAssociatedWithNegatedOption = new HashSet<>(); + + DecisionAnalyser(DecisionNode decisionNode, AtomicConstraint factorisingConstraint){ + this.decision = decisionNode; + this.factorisingConstraint = factorisingConstraint; + this.negatedFactorisingConstraint = factorisingConstraint.negate(); + } + + /** + * Iterate through a decision nodes options and determine whether factorisation is possible + */ + DecisionAnalysisResult performAnalysis() { + DecisionAnalysisResult result = new DecisionAnalysisResult(); + List otherOptions = new ArrayList<>(); + for (ConstraintNode option : decision.getOptions()) { + boolean optionContainsProlificConstraint = atomicConstraintExists(option, factorisingConstraint); + boolean optionContainsNegatedProlificConstraint = atomicConstraintExists(option, negatedFactorisingConstraint); + if (optionContainsProlificConstraint && optionContainsNegatedProlificConstraint) { + throw new RuntimeException("Contradictory constraint node"); + } else if (optionContainsProlificConstraint) { + markOptionForFactorisation(factorisingConstraint, option, result.optionsToFactorise, atomicConstraintsAssociatedWithFactorisingOption); + } else if (optionContainsNegatedProlificConstraint) { + markOptionForFactorisation(negatedFactorisingConstraint, option, result.negatedOptionsToFactorise, atomicConstraintsAssociatedWithNegatedOption); + } else { + // This option does not contain the factorising constraint so add to a separate list. + otherOptions.add(option); + } + } + + // The following options need moving either to: + // * an option under the factorising constraint node, + // * an option under the negated factorising constraint node, + // * or another option alongside the factorising constraint node + for (ConstraintNode option : otherOptions) { + boolean nodeCanBeMovedUnderFactorised = constraintNodeContainsNegatedConstraints(option, atomicConstraintsAssociatedWithFactorisingOption); + boolean nodeCanBeMovedUnderNegatedFactorised = constraintNodeContainsNegatedConstraints(option, atomicConstraintsAssociatedWithNegatedOption); + if (nodeCanBeMovedUnderFactorised) { + result.optionsToFactorise.add(option); + } else if (nodeCanBeMovedUnderNegatedFactorised) { + result.negatedOptionsToFactorise.add(option); + } else { + result.adjacentOptions.add(option); + } + } + return result; + } + + + private void markOptionForFactorisation( + AtomicConstraint factorisingConstraint, + ConstraintNode node, + List options, + Set constraints) { + ConstraintNode newOption = node.builder().removeAtomicConstraint(factorisingConstraint).build(); + if (!newOption.getAtomicConstraints().isEmpty()) { + options.add(newOption); + constraints.addAll(newOption.getAtomicConstraints()); + } + } + } + + static class DecisionAnalysisResult { + List optionsToFactorise = new ArrayList<>(); + List negatedOptionsToFactorise = new ArrayList<>(); + List adjacentOptions = new ArrayList<>(); + } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/decisiontree/MostProlificConstraintOptimiser.java b/generator/src/main/java/com/scottlogic/deg/generator/decisiontree/MostProlificConstraintOptimiser.java deleted file mode 100644 index 9f9dad67a..000000000 --- a/generator/src/main/java/com/scottlogic/deg/generator/decisiontree/MostProlificConstraintOptimiser.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright 2019 Scott Logic Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.scottlogic.deg.generator.decisiontree; - -import com.scottlogic.deg.common.profile.constraints.atomic.AtomicConstraint; -import com.scottlogic.deg.common.profile.constraints.atomic.NotConstraint; - -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class MostProlificConstraintOptimiser implements DecisionTreeOptimiser { - private final int maxIterations = 50; - - @Override - public DecisionTree optimiseTree(DecisionTree tree){ - ConstraintNode newRootNode = optimiseLevelOfTree(tree.getRootNode()); - return new DecisionTree(newRootNode, tree.getFields()); - } - - private ConstraintNode optimiseLevelOfTree(ConstraintNode rootNode){ - for (int iteration = 0; iteration < maxIterations; iteration++) { - ConstraintNode newRootNode = optimiseDecisions(rootNode); - - if (noChangeInDecisionCount(rootNode, newRootNode)) { - return newRootNode; - } - - rootNode = newRootNode; - } - - return rootNode; - } - - private boolean noChangeInDecisionCount(ConstraintNode rootNode, ConstraintNode newRootNode) { - return newRootNode.getDecisions().size() == rootNode.getDecisions().size(); - } - - private ConstraintNode optimiseDecisions(ConstraintNode rootNode){ - AtomicConstraint mostProlificAtomicConstraint = getMostProlificAtomicConstraint(rootNode.getDecisions()); - if (mostProlificAtomicConstraint == null){ - return rootNode; - } - // Add negation of most prolific constraint to new decision node - AtomicConstraint negatedMostProlificConstraint = mostProlificAtomicConstraint.negate(); - - List factorisableDecisionNodes = rootNode.getDecisions().stream() - .filter(node -> this.decisionIsFactorisable(node, mostProlificAtomicConstraint, negatedMostProlificConstraint)) - .collect(Collectors.toList()); - if (factorisableDecisionNodes.size() < 2){ - return rootNode; - } - - // Add most prolific constraint to new decision node - ConstraintNode factorisingConstraintNode = new ConstraintNodeBuilder().addAtomicConstraints(mostProlificAtomicConstraint).build(); - ConstraintNode negatedFactorisingConstraintNode = new ConstraintNodeBuilder().addAtomicConstraints(negatedMostProlificConstraint).build(); - - Set otherOptions = new HashSet<>(); - Set decisionsToRemove = new HashSet<>(); - - for (DecisionNode decision : factorisableDecisionNodes) { - DecisionAnalyser analyser = new DecisionAnalyser(decision, mostProlificAtomicConstraint); - DecisionAnalysisResult result = analyser.performAnalysis(); - - // Perform movement of options - factorisingConstraintNode = addOptionsAsDecisionUnderConstraintNode(factorisingConstraintNode, result.optionsToFactorise); - negatedFactorisingConstraintNode = addOptionsAsDecisionUnderConstraintNode(negatedFactorisingConstraintNode, result.negatedOptionsToFactorise); - otherOptions.addAll(result.adjacentOptions); - decisionsToRemove.add(decision); - } - - // Add new decision node - DecisionNode factorisedDecisionNode = new DecisionNode( - Stream.concat( - Stream.of( - optimiseLevelOfTree(factorisingConstraintNode), - optimiseLevelOfTree(negatedFactorisingConstraintNode)), - otherOptions.stream()) - .collect(Collectors.toList())); - - return rootNode.builder() - .removeDecisions(decisionsToRemove) - .addDecision(factorisedDecisionNode).build(); - } - - private boolean constraintNodeContainsNegatedConstraints(ConstraintNode node, Set constraints){ - return node.getAtomicConstraints().stream() - .map(AtomicConstraint::negate) - .allMatch(constraints::contains); - } - - private ConstraintNode addOptionsAsDecisionUnderConstraintNode( - ConstraintNode newNode, - Collection optionsToAdd) { - if (optionsToAdd.isEmpty()) { - return newNode; - } - - return newNode.builder().addDecision(new DecisionNode(optionsToAdd)).build(); - } - - private int disfavourNotConstraints(Map.Entry> entry){ - return entry.getKey() instanceof NotConstraint ? 1 : 0; - } - - private AtomicConstraint getMostProlificAtomicConstraint(Collection decisions) { - Map> decisionConstraints = - decisions.stream() - .flatMap(dn -> dn.getOptions().stream()) - .flatMap(option -> option.getAtomicConstraints().stream()) - .collect(Collectors.groupingBy(Function.identity())); - - Comparator>> comparator = Comparator - .comparing(entry -> entry.getValue().size()); - comparator = comparator.reversed() - .thenComparing(this::disfavourNotConstraints) - .thenComparing(entry -> entry.getKey().toString()); - - return decisionConstraints.entrySet() - .stream() - .filter(constraint -> constraint.getValue().size() > 1) // where the number of occurrences > 1 - .sorted(comparator) - .map(entry -> getConstraint(entry.getValue())) - .findFirst() - .orElse(null); //otherwise return null - } - - private AtomicConstraint getConstraint(List identicalAtomicConstraints) { - return identicalAtomicConstraints.iterator().next(); - } - - private boolean decisionIsFactorisable(DecisionNode decision, AtomicConstraint factorisingConstraint, AtomicConstraint negatedFactorisingConstraint){ - // The decision should contain ONE option with the MPC - boolean optionWithMPCExists = decision.getOptions().stream() - .filter(option -> atomicConstraintExists(option, factorisingConstraint)) - .count() == 1; - - // The decision should contain ONE separate option with the negated MPC (which is atomic). - boolean optionWithNegatedMPCExists = decision.getOptions().stream() - .filter(option -> atomicConstraintExists(option, negatedFactorisingConstraint) && option.getAtomicConstraints().size() == 1) - .count() == 1; - - return optionWithMPCExists && optionWithNegatedMPCExists; - } - - public boolean atomicConstraintExists(ConstraintNode atomicConstraints, AtomicConstraint constraint) { - return atomicConstraints.getAtomicConstraints().stream() - .anyMatch(c -> c.equals(constraint)); - } - - class DecisionAnalyser { - private DecisionNode decision; - private AtomicConstraint factorisingConstraint; - private AtomicConstraint negatedFactorisingConstraint; - private Set atomicConstraintsAssociatedWithFactorisingOption = new HashSet<>(); - private Set atomicConstraintsAssociatedWithNegatedOption = new HashSet<>(); - - DecisionAnalyser(DecisionNode decisionNode, AtomicConstraint factorisingConstraint){ - this.decision = decisionNode; - this.factorisingConstraint = factorisingConstraint; - this.negatedFactorisingConstraint = factorisingConstraint.negate(); - } - - /** - * Iterate through a decision nodes options and determine whether factorisation is possible - */ - DecisionAnalysisResult performAnalysis() { - DecisionAnalysisResult result = new DecisionAnalysisResult(); - List otherOptions = new ArrayList<>(); - for (ConstraintNode option : decision.getOptions()) { - boolean optionContainsProlificConstraint = atomicConstraintExists(option, factorisingConstraint); - boolean optionContainsNegatedProlificConstraint = atomicConstraintExists(option, negatedFactorisingConstraint); - if (optionContainsProlificConstraint && optionContainsNegatedProlificConstraint) { - throw new RuntimeException("Contradictory constraint node"); - } else if (optionContainsProlificConstraint) { - markOptionForFactorisation(factorisingConstraint, option, result.optionsToFactorise, atomicConstraintsAssociatedWithFactorisingOption); - } else if (optionContainsNegatedProlificConstraint) { - markOptionForFactorisation(negatedFactorisingConstraint, option, result.negatedOptionsToFactorise, atomicConstraintsAssociatedWithNegatedOption); - } else { - // This option does not contain the factorising constraint so add to a separate list. - otherOptions.add(option); - } - } - - // The following options need moving either to: - // * an option under the factorising constraint node, - // * an option under the negated factorising constraint node, - // * or another option alongside the factorising constraint node - for (ConstraintNode option : otherOptions) { - boolean nodeCanBeMovedUnderFactorised = constraintNodeContainsNegatedConstraints(option, atomicConstraintsAssociatedWithFactorisingOption); - boolean nodeCanBeMovedUnderNegatedFactorised = constraintNodeContainsNegatedConstraints(option, atomicConstraintsAssociatedWithNegatedOption); - if (nodeCanBeMovedUnderFactorised) { - result.optionsToFactorise.add(option); - } else if (nodeCanBeMovedUnderNegatedFactorised) { - result.negatedOptionsToFactorise.add(option); - } else { - result.adjacentOptions.add(option); - } - } - return result; - } - - - private void markOptionForFactorisation( - AtomicConstraint factorisingConstraint, - ConstraintNode node, - List options, - Set constraints) { - ConstraintNode newOption = node.builder().removeAtomicConstraint(factorisingConstraint).build(); - if (!newOption.getAtomicConstraints().isEmpty()) { - options.add(newOption); - constraints.addAll(newOption.getAtomicConstraints()); - } - } - } - - class DecisionAnalysisResult { - List optionsToFactorise = new ArrayList<>(); - List negatedOptionsToFactorise = new ArrayList<>(); - List adjacentOptions = new ArrayList<>(); - } -} diff --git a/generator/src/main/java/com/scottlogic/deg/generator/decisiontree/NoopDecisionTreeOptimiser.java b/generator/src/main/java/com/scottlogic/deg/generator/decisiontree/NoopDecisionTreeOptimiser.java deleted file mode 100644 index 382acc6dc..000000000 --- a/generator/src/main/java/com/scottlogic/deg/generator/decisiontree/NoopDecisionTreeOptimiser.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2019 Scott Logic Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.scottlogic.deg.generator.decisiontree; - -public class NoopDecisionTreeOptimiser implements DecisionTreeOptimiser { - - @Override - public DecisionTree optimiseTree(DecisionTree tree) { - return tree; - } -} diff --git a/generator/src/main/java/com/scottlogic/deg/generator/decisiontree/treepartitioning/NoopTreePartitioner.java b/generator/src/main/java/com/scottlogic/deg/generator/decisiontree/treepartitioning/NoopTreePartitioner.java deleted file mode 100644 index 6d6085496..000000000 --- a/generator/src/main/java/com/scottlogic/deg/generator/decisiontree/treepartitioning/NoopTreePartitioner.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2019 Scott Logic Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.scottlogic.deg.generator.decisiontree.treepartitioning; - -import com.scottlogic.deg.generator.decisiontree.DecisionTree; - -import java.util.stream.Stream; - -public class NoopTreePartitioner implements TreePartitioner { - @Override - public Stream splitTreeIntoPartitions(DecisionTree decisionTree) { - return Stream.of(decisionTree); - } -} diff --git a/generator/src/main/java/com/scottlogic/deg/generator/decisiontree/treepartitioning/RelatedFieldTreePartitioner.java b/generator/src/main/java/com/scottlogic/deg/generator/decisiontree/treepartitioning/RelatedFieldTreePartitioner.java deleted file mode 100644 index 825519e8f..000000000 --- a/generator/src/main/java/com/scottlogic/deg/generator/decisiontree/treepartitioning/RelatedFieldTreePartitioner.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright 2019 Scott Logic Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.scottlogic.deg.generator.decisiontree.treepartitioning; - -import com.scottlogic.deg.common.profile.Field; -import com.scottlogic.deg.common.profile.constraints.delayed.DelayedAtomicConstraint; -import com.scottlogic.deg.common.util.FlatMappingSpliterator; -import com.scottlogic.deg.common.profile.ProfileFields; -import com.scottlogic.deg.common.profile.constraints.atomic.AtomicConstraint; -import com.scottlogic.deg.generator.decisiontree.ConstraintNodeBuilder; -import com.scottlogic.deg.generator.decisiontree.DecisionNode; -import com.scottlogic.deg.generator.decisiontree.DecisionTree; - -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * Given a decision tress, split it into multiple trees based on which constraints and decisions affect which fields - */ -public class RelatedFieldTreePartitioner implements TreePartitioner { - private final ConstraintToFieldMapper fieldMapper; - private static Integer partitionIndex = 0; - - public RelatedFieldTreePartitioner() { - fieldMapper = new ConstraintToFieldMapper(); - } - - public Stream splitTreeIntoPartitions(DecisionTree decisionTree) { - final PartitionIndex partitions = new PartitionIndex(); - - final Map> mapping = fieldMapper.mapConstraintsToFields(decisionTree); - - // each set of fields iterated here are constrained by a single root-level constraint/decision - for (RootLevelConstraint constraint : mapping.keySet()) { - Set fields = mapping.get(constraint); - - // find which existing partitions this constraint/decision affects (if any) - final Set existingIntersectingPartitions = fields - .stream() - .map(partitions::getPartitionId) - .distinct() - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - - // then, add new partition for this new constraint - final Integer partitionId = partitions.addPartition(fields, new HashSet<>(Collections.singletonList(constraint))); - - // if there are any intersecting partitions, merge them with the new one - if (existingIntersectingPartitions.size() > 0) { - final Set partitionsToMerge = new HashSet<>(); - partitionsToMerge.add(partitionId); - partitionsToMerge.addAll(existingIntersectingPartitions); - - partitions.mergePartitions(partitionsToMerge); - } - } - - // any leftover fields must be grouped into their own partition - final Stream unpartitionedFields = decisionTree - .getFields() - .stream() - .filter(field -> Objects.isNull(partitions.getPartitionId(field))); - - return Stream.concat( - partitions - .getPartitions() - .stream() - .sorted(Comparator.comparingInt(p -> p.id)) - .map(partition -> new DecisionTree( - new ConstraintNodeBuilder() - .addAtomicConstraints(partition.getAtomicConstraints()) - .addDelayedAtomicConstraints(partition.getDelayedAtomicConstraints()) - .setDecisions(partition.getDecisionNodes()) - .build(), - new ProfileFields(new ArrayList<>(partition.fields)) - )), - unpartitionedFields - .map(field -> new DecisionTree( - new ConstraintNodeBuilder().build(), - new ProfileFields(Collections.singletonList(field)) - )) - ); - } - - class Partition { - final Integer id; - final Set fields; - final Set constraints; - - Partition(Integer id, Set fields, Set constraints) { - this.id = id; - this.fields = fields; - this.constraints = constraints; - } - - Set getAtomicConstraints() { - return constraints - .stream() - .map(RootLevelConstraint::getAtomicConstraint) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - } - - Set getDecisionNodes() { - return constraints - .stream() - .map(RootLevelConstraint::getDecisionNode) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - } - - Set getDelayedAtomicConstraints() { - return constraints - .stream() - .map(RootLevelConstraint::getDelayedAtomicConstraint) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - } - } - - class PartitionIndex { - private final Map idToPartition = new HashMap<>(); - private final Map fieldsToPartition = new HashMap<>(); - - Integer addPartition(Set fields, Set constraints) { - final Partition newPartition = new Partition( - partitionIndex++, - fields, - constraints); - - idToPartition.put(newPartition.id, newPartition); - - for (Field field : fields) - fieldsToPartition.put(field, newPartition); - - return newPartition.id; - } - - Integer mergePartitions(Set ids) { - final Set partitions = ids - .stream() - .map(idToPartition::get) - .collect(Collectors.toSet()); - - final Set fields = getFromAllPartitions(partitions, partition -> partition.fields); - final Set constraints = getFromAllPartitions(partitions, partition -> partition.constraints); - - final Partition newPartition = new Partition( - partitionIndex++, - fields, - constraints); - idToPartition.put(newPartition.id, newPartition); - fields.forEach(field -> fieldsToPartition.put(field, newPartition)); - - ids.forEach(idToPartition::remove); - - return newPartition.id; - } - - private Set getFromAllPartitions(Set partitions, Function> getter) { - return FlatMappingSpliterator.flatMap(partitions - .stream(), - partition -> getter.apply(partition).stream()) - .collect(Collectors.toSet()); - } - - Integer getPartitionId(Field field) { - return fieldsToPartition.containsKey(field) - ? fieldsToPartition.get(field).id - : null; - } - - Collection getPartitions() { - return idToPartition.values(); - } - } -} diff --git a/generator/src/main/java/com/scottlogic/deg/generator/decisiontree/treepartitioning/TreePartitioner.java b/generator/src/main/java/com/scottlogic/deg/generator/decisiontree/treepartitioning/TreePartitioner.java index b78df21f0..966bd2105 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/decisiontree/treepartitioning/TreePartitioner.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/decisiontree/treepartitioning/TreePartitioner.java @@ -16,10 +16,176 @@ package com.scottlogic.deg.generator.decisiontree.treepartitioning; +import com.scottlogic.deg.common.profile.Field; +import com.scottlogic.deg.common.profile.ProfileFields; +import com.scottlogic.deg.common.profile.constraints.atomic.AtomicConstraint; +import com.scottlogic.deg.common.profile.constraints.delayed.DelayedAtomicConstraint; +import com.scottlogic.deg.common.util.FlatMappingSpliterator; +import com.scottlogic.deg.generator.decisiontree.ConstraintNodeBuilder; +import com.scottlogic.deg.generator.decisiontree.DecisionNode; import com.scottlogic.deg.generator.decisiontree.DecisionTree; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; import java.util.stream.Stream; -public interface TreePartitioner { - Stream splitTreeIntoPartitions(DecisionTree decisionTree); +/** + * Given a decision tress, split it into multiple trees based on which constraints and decisions affect which fields + */ +public class TreePartitioner { + private final ConstraintToFieldMapper fieldMapper; + private static Integer partitionIndex = 0; + + public TreePartitioner() { + fieldMapper = new ConstraintToFieldMapper(); + } + + public Stream splitTreeIntoPartitions(DecisionTree decisionTree) { + final PartitionIndex partitions = new PartitionIndex(); + + final Map> mapping = fieldMapper.mapConstraintsToFields(decisionTree); + + // each set of fields iterated here are constrained by a single root-level constraint/decision + for (RootLevelConstraint constraint : mapping.keySet()) { + Set fields = mapping.get(constraint); + + // find which existing partitions this constraint/decision affects (if any) + final Set existingIntersectingPartitions = fields + .stream() + .map(partitions::getPartitionId) + .distinct() + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + // then, add new partition for this new constraint + final Integer partitionId = partitions.addPartition(fields, new HashSet<>(Collections.singletonList(constraint))); + + // if there are any intersecting partitions, merge them with the new one + if (existingIntersectingPartitions.size() > 0) { + final Set partitionsToMerge = new HashSet<>(); + partitionsToMerge.add(partitionId); + partitionsToMerge.addAll(existingIntersectingPartitions); + + partitions.mergePartitions(partitionsToMerge); + } + } + + // any leftover fields must be grouped into their own partition + final Stream unpartitionedFields = decisionTree + .getFields() + .stream() + .filter(field -> Objects.isNull(partitions.getPartitionId(field))); + + return Stream.concat( + partitions + .getPartitions() + .stream() + .sorted(Comparator.comparingInt(p -> p.id)) + .map(partition -> new DecisionTree( + new ConstraintNodeBuilder() + .addAtomicConstraints(partition.getAtomicConstraints()) + .addDelayedAtomicConstraints(partition.getDelayedAtomicConstraints()) + .setDecisions(partition.getDecisionNodes()) + .build(), + new ProfileFields(new ArrayList<>(partition.fields)) + )), + unpartitionedFields + .map(field -> new DecisionTree( + new ConstraintNodeBuilder().build(), + new ProfileFields(Collections.singletonList(field)) + )) + ); + } + + static class Partition { + final Integer id; + final Set fields; + final Set constraints; + + Partition(Integer id, Set fields, Set constraints) { + this.id = id; + this.fields = fields; + this.constraints = constraints; + } + + Set getAtomicConstraints() { + return constraints + .stream() + .map(RootLevelConstraint::getAtomicConstraint) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + } + + Set getDecisionNodes() { + return constraints + .stream() + .map(RootLevelConstraint::getDecisionNode) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + } + + Set getDelayedAtomicConstraints() { + return constraints + .stream() + .map(RootLevelConstraint::getDelayedAtomicConstraint) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + } + } + + static class PartitionIndex { + private final Map idToPartition = new HashMap<>(); + private final Map fieldsToPartition = new HashMap<>(); + + Integer addPartition(Set fields, Set constraints) { + final Partition newPartition = new Partition( + partitionIndex++, + fields, + constraints); + + idToPartition.put(newPartition.id, newPartition); + + for (Field field : fields) + fieldsToPartition.put(field, newPartition); + + return newPartition.id; + } + + void mergePartitions(Set ids) { + final Set partitions = ids + .stream() + .map(idToPartition::get) + .collect(Collectors.toSet()); + + final Set fields = getFromAllPartitions(partitions, partition -> partition.fields); + final Set constraints = getFromAllPartitions(partitions, partition -> partition.constraints); + + final Partition newPartition = new Partition( + partitionIndex++, + fields, + constraints); + idToPartition.put(newPartition.id, newPartition); + fields.forEach(field -> fieldsToPartition.put(field, newPartition)); + + ids.forEach(idToPartition::remove); + } + + private Set getFromAllPartitions(Set partitions, Function> getter) { + return FlatMappingSpliterator.flatMap(partitions + .stream(), + partition -> getter.apply(partition).stream()) + .collect(Collectors.toSet()); + } + + Integer getPartitionId(Field field) { + return fieldsToPartition.containsKey(field) + ? fieldsToPartition.get(field).id + : null; + } + + Collection getPartitions() { + return idToPartition.values(); + } + } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/DecisionTreeDataGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/DecisionTreeDataGenerator.java index aeb9e444a..81f0d00e1 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/DecisionTreeDataGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/DecisionTreeDataGenerator.java @@ -18,14 +18,14 @@ import com.google.inject.Inject; import com.google.inject.name.Named; +import com.scottlogic.deg.common.output.GeneratedObject; import com.scottlogic.deg.common.profile.Profile; import com.scottlogic.deg.generator.decisiontree.DecisionTree; import com.scottlogic.deg.generator.decisiontree.DecisionTreeFactory; import com.scottlogic.deg.generator.decisiontree.DecisionTreeOptimiser; import com.scottlogic.deg.generator.decisiontree.treepartitioning.TreePartitioner; import com.scottlogic.deg.generator.generation.combinationstrategies.CombinationStrategy; -import com.scottlogic.deg.generator.generation.databags.*; -import com.scottlogic.deg.common.output.GeneratedObject; +import com.scottlogic.deg.generator.generation.databags.DataBag; import com.scottlogic.deg.generator.walker.DecisionTreeWalker; import java.util.function.Supplier; diff --git a/generator/src/main/java/com/scottlogic/deg/generator/guice/DecisionTreeOptimiserProvider.java b/generator/src/main/java/com/scottlogic/deg/generator/guice/DecisionTreeOptimiserProvider.java deleted file mode 100644 index 635f888e3..000000000 --- a/generator/src/main/java/com/scottlogic/deg/generator/guice/DecisionTreeOptimiserProvider.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2019 Scott Logic Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.scottlogic.deg.generator.guice; - -import com.google.inject.Provider; -import com.scottlogic.deg.generator.decisiontree.DecisionTreeOptimiser; -import com.scottlogic.deg.generator.decisiontree.MostProlificConstraintOptimiser; - -public class DecisionTreeOptimiserProvider implements Provider { - public DecisionTreeOptimiserProvider() { - } - - @Override - public DecisionTreeOptimiser get() { - return new MostProlificConstraintOptimiser(); - } -} diff --git a/generator/src/main/java/com/scottlogic/deg/generator/guice/GeneratorModule.java b/generator/src/main/java/com/scottlogic/deg/generator/guice/GeneratorModule.java index 2404f030e..1a2f04dcd 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/guice/GeneratorModule.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/guice/GeneratorModule.java @@ -20,14 +20,12 @@ import com.google.inject.Singleton; import com.google.inject.name.Names; import com.scottlogic.deg.generator.config.detail.DataGenerationType; -import com.scottlogic.deg.generator.decisiontree.DecisionTreeOptimiser; -import com.scottlogic.deg.generator.decisiontree.treepartitioning.TreePartitioner; import com.scottlogic.deg.generator.generation.*; import com.scottlogic.deg.generator.generation.combinationstrategies.CombinationStrategy; import com.scottlogic.deg.generator.inputs.validation.ProfileValidator; import com.scottlogic.deg.generator.utils.JavaUtilRandomNumberGenerator; -import com.scottlogic.deg.generator.walker.decisionbased.OptionPicker; import com.scottlogic.deg.generator.walker.DecisionTreeWalker; +import com.scottlogic.deg.generator.walker.decisionbased.OptionPicker; import java.time.OffsetDateTime; @@ -48,8 +46,6 @@ protected void configure() { bind(GenerationConfigSource.class).toInstance(generationConfigSource); // Bind providers - used to retrieve implementations based on user input - bind(DecisionTreeOptimiser.class).toProvider(DecisionTreeOptimiserProvider.class); - bind(TreePartitioner.class).toProvider(TreePartitioningProvider.class); bind(DecisionTreeWalker.class).toProvider(DecisionTreeWalkerProvider.class); bind(ProfileValidator.class).toProvider(ProfileValidatorProvider.class); bind(AbstractDataGeneratorMonitor.class).toProvider(MonitorProvider.class).in(Singleton.class); diff --git a/generator/src/main/java/com/scottlogic/deg/generator/guice/TreePartitioningProvider.java b/generator/src/main/java/com/scottlogic/deg/generator/guice/TreePartitioningProvider.java deleted file mode 100644 index 4fe403e21..000000000 --- a/generator/src/main/java/com/scottlogic/deg/generator/guice/TreePartitioningProvider.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2019 Scott Logic Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.scottlogic.deg.generator.guice; - -import com.google.inject.Provider; -import com.scottlogic.deg.generator.decisiontree.treepartitioning.RelatedFieldTreePartitioner; -import com.scottlogic.deg.generator.decisiontree.treepartitioning.TreePartitioner; - -public class TreePartitioningProvider implements Provider { - - public TreePartitioningProvider() { - } - - @Override - public TreePartitioner get() { - return new RelatedFieldTreePartitioner(); - } -} diff --git a/generator/src/test/java/com/scottlogic/deg/generator/decisiontree/MostProlificConstraintOptimiserTest.java b/generator/src/test/java/com/scottlogic/deg/generator/decisiontree/DecisionTreeOptimiserTest.java similarity index 97% rename from generator/src/test/java/com/scottlogic/deg/generator/decisiontree/MostProlificConstraintOptimiserTest.java rename to generator/src/test/java/com/scottlogic/deg/generator/decisiontree/DecisionTreeOptimiserTest.java index 5fa60714a..e80753a39 100644 --- a/generator/src/test/java/com/scottlogic/deg/generator/decisiontree/MostProlificConstraintOptimiserTest.java +++ b/generator/src/test/java/com/scottlogic/deg/generator/decisiontree/DecisionTreeOptimiserTest.java @@ -26,9 +26,9 @@ import static com.shazam.shazamcrest.MatcherAssert.assertThat; import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs; -class MostProlificConstraintOptimiserTest { +class DecisionTreeOptimiserTest { - MostProlificConstraintOptimiser optimiser = new MostProlificConstraintOptimiser(); + DecisionTreeOptimiser optimiser = new DecisionTreeOptimiser(); Field A = new Field("A"); Field B = new Field("B"); Field C = new Field("C"); diff --git a/generator/src/test/java/com/scottlogic/deg/generator/decisiontree/treepartitioning/RelatedFieldTreePartitionerTests.java b/generator/src/test/java/com/scottlogic/deg/generator/decisiontree/treepartitioning/TreePartitionerTests.java similarity index 99% rename from generator/src/test/java/com/scottlogic/deg/generator/decisiontree/treepartitioning/RelatedFieldTreePartitionerTests.java rename to generator/src/test/java/com/scottlogic/deg/generator/decisiontree/treepartitioning/TreePartitionerTests.java index a24fb7141..a2184680e 100644 --- a/generator/src/test/java/com/scottlogic/deg/generator/decisiontree/treepartitioning/RelatedFieldTreePartitionerTests.java +++ b/generator/src/test/java/com/scottlogic/deg/generator/decisiontree/treepartitioning/TreePartitionerTests.java @@ -33,7 +33,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -class RelatedFieldTreePartitionerTests { +class TreePartitionerTests { private static final ConstraintNode emptyConstraint = new ConstraintNodeBuilder().addAtomicConstraints(Collections.emptySet()).setDecisions(Collections.emptySet()).build(); @@ -310,7 +310,7 @@ private void givenTree(DecisionTree decisionTree) { } private void partitionTrees() { - partitionedTrees = new RelatedFieldTreePartitioner() + partitionedTrees = new TreePartitioner() .splitTreeIntoPartitions(decisionTree) .collect(Collectors.toList()); }