From 94e9eaaeb00adcc6ced213c1f05f951e0f16734e Mon Sep 17 00:00:00 2001 From: Johannes Mey <johannes.mey@tu-dresden.de> Date: Tue, 17 Jul 2018 14:28:12 +0200 Subject: [PATCH] initial commit of genetic solver (not working yet) --- .../src/main/jastadd/solvers/Helpers.jadd | 151 +++++++++++++++++- .../jastadd/solvers/genetic/Checking.jrag | 150 +++++++++++++++++ jastadd-mquat-benchmark/build.gradle | 1 + .../inf/st/mquat/benchmark/SolverFactory.java | 4 +- jastadd-mquat-solver-genetic/.gitignore | 2 + jastadd-mquat-solver-genetic/build.gradle | 24 +++ .../mquat/solving/genetic/GeneticSolver.java | 100 ++++++++++++ .../solving/genetic/opt4j/Opt4jCreator.java | 43 +++++ .../solving/genetic/opt4j/Opt4jDecoder.java | 74 +++++++++ .../solving/genetic/opt4j/Opt4jEvaluator.java | 34 ++++ .../solving/genetic/opt4j/Opt4jModule.java | 75 +++++++++ .../opt4j/custom/genotypes/TreeGenotype.java | 59 +++++++ .../custom/genotypes/TreeGenotypeNode.java | 75 +++++++++ .../operator/copy/TreeCopyOperator.java | 16 ++ .../operator/copy/TreeCopyOperatorModule.java | 12 ++ .../crossover/TreeCrossoverOperator.java | 94 +++++++++++ .../TreeCrossoverOperatorModule.java | 21 +++ .../operator/mutate/TreeMutateOperator.java | 83 ++++++++++ .../mutate/TreeMutateOperatorModule.java | 12 ++ .../mquat/solving/SimpleHandwrittenTest.java | 11 ++ .../st/mquat/solving/SimpleSolverTest.java | 54 +++++++ settings.gradle | 1 + 22 files changed, 1094 insertions(+), 2 deletions(-) create mode 100644 jastadd-mquat-base/src/main/jastadd/solvers/genetic/Checking.jrag create mode 100644 jastadd-mquat-solver-genetic/.gitignore create mode 100644 jastadd-mquat-solver-genetic/build.gradle create mode 100644 jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/GeneticSolver.java create mode 100644 jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/Opt4jCreator.java create mode 100644 jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/Opt4jDecoder.java create mode 100644 jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/Opt4jEvaluator.java create mode 100644 jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/Opt4jModule.java create mode 100644 jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/genotypes/TreeGenotype.java create mode 100644 jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/genotypes/TreeGenotypeNode.java create mode 100644 jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/copy/TreeCopyOperator.java create mode 100644 jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/copy/TreeCopyOperatorModule.java create mode 100644 jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/crossover/TreeCrossoverOperator.java create mode 100644 jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/crossover/TreeCrossoverOperatorModule.java create mode 100644 jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/mutate/TreeMutateOperator.java create mode 100644 jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/mutate/TreeMutateOperatorModule.java create mode 100644 jastadd-mquat-solver-genetic/src/test/java/de/tudresden/inf/st/mquat/solving/SimpleHandwrittenTest.java create mode 100644 jastadd-mquat-solver-genetic/src/test/java/de/tudresden/inf/st/mquat/solving/SimpleSolverTest.java diff --git a/jastadd-mquat-base/src/main/jastadd/solvers/Helpers.jadd b/jastadd-mquat-base/src/main/jastadd/solvers/Helpers.jadd index b90d02d..8ca652d 100644 --- a/jastadd-mquat-base/src/main/jastadd/solvers/Helpers.jadd +++ b/jastadd-mquat-base/src/main/jastadd/solvers/Helpers.jadd @@ -37,4 +37,153 @@ aspect Helpers { return assignment; } -} \ No newline at end of file + + + public Solution Root.createRandomSolution(java.util.Random random) { + Solution solution = new Solution(); + + // create a resource bucket + java.util.List<Resource> resourceList = populateResourceList(this.getHardwareModel().getResourceList(), new ArrayList<>()); + + for (Request request : getRequestList()) { + solution.addAssignment(createRandomAssignment(true, request, request.getTarget().getRef(),resourceList, random)); + } + + return solution; + } + + + private java.util.List<Resource> Root.populateResourceList(List<Resource> resourceList, java.util.List<Resource> list) { + for (Resource resource : resourceList) { + if (resource.getType().getRef().getContainer()) { + list.add(resource); + } + populateResourceList(resource.getSubResourceList(), list); + } + return list; + } + + public Assignment Root.createRandomAssignment(boolean isTopLevel, Request request, Component component, java.util.List<Resource> resourceList, java.util.Random random) { + + Implementation implementation = component.getImplementation(random.nextInt(component.getNumImplementation())); + + Assignment assignment = new Assignment(); + assignment.setImplementation(implementation); + assignment.setRequest(request); + assignment.setTopLevel(isTopLevel); + + // assign dependent software components + for (ComponentRequirement componentRequirement : implementation.getComponentRequirementList()) { + Component requiredComponent = componentRequirement.getComponentRef().getRef(); + for (Instance componentRequirementInstance : componentRequirement.getInstanceList()) { + ComponentMapping mapping = new ComponentMapping(); + mapping.setInstance(componentRequirementInstance); + mapping.setAssignment(createRandomAssignment(false, request, requiredComponent, resourceList, random)); + assignment.addComponentMapping(mapping); + } + } + + // assign resources + ResourceRequirement resourceRequirement = implementation.getResourceRequirement(); + ResourceType requiredResourceType = resourceRequirement.getResourceTypeRef().getRef(); + for (Instance instance : resourceRequirement.getInstanceList()) { + ResourceMapping mapping = new ResourceMapping(); + mapping.setInstance(instance); + Resource chosenResource; + int resourceNumber; + do { + resourceNumber = random.nextInt(resourceList.size()); + chosenResource = resourceList.get(resourceNumber); + } while (chosenResource.getType().getRef() != requiredResourceType); + mapping.setResource(resourceList.remove(resourceNumber)); + + assignment.setResourceMapping(mapping); + } + + + return assignment; + } + + public java.util.List<Resource> Root.unassignedResources(Solution solution) { + java.util.List<Resource> assignedResources = solution.assignedResources(); + java.util.List<Resource> allResources = getHardwareModel().allContainers(); + + allResources.removeAll(assignedResources); + + return allResources; + } + + public java.util.List<Resource> HardwareModel.allContainers() { + java.util.List<Resource> allContainers = new java.util.ArrayList<>(); + + for (Resource resource : getResourceList()) { + allContainers.addAll(resource.allContainers()); + } + + return allContainers; + } + + public java.util.List<Resource> Resource.allContainers() { + + java.util.List<Resource> allContainers = null; + + for (Resource subResource : getSubResourceList()) { + java.util.List<Resource> subResourceContainers = subResource.allContainers(); + if (!subResourceContainers.isEmpty()) { + if (allContainers == null) { + allContainers = new ArrayList<>(subResourceContainers); + } else { + allContainers.addAll(subResourceContainers); + } + } + } + + if (this.getType().getRef().getContainer()) { + if (allContainers == null || allContainers.isEmpty()) { + return java.util.Collections.singletonList(this); + } else { + allContainers.add(this); + } + } + + return allContainers == null ? java.util.Collections.emptyList() : allContainers; + } + + public java.util.List<Resource> Assignment.assignedResources() { + java.util.List<Resource> assignedResources = new java.util.ArrayList<>(); + + if (this.getResource() != null) { + assignedResources.add(this.getResource()); + } + + for (ComponentMapping mapping : this.getComponentMappingList()) { + assignedResources.addAll(mapping.getAssignment().assignedResources()); + } + + return assignedResources; + } + + public java.util.List<Resource> Solution.assignedResources() { + + java.util.List<Resource> assignedResources = new java.util.ArrayList<>(); + + for (Assignment assignment : this.getAssignmentList()) { + assignedResources.addAll(assignment.assignedResources()); + } + + return assignedResources; + } + + + inh Solution Assignment.containingSolution(); + eq Solution.getAssignment().containingSolution() = this; + + public boolean List.contains(ASTNode node) { + for (Object o : astChildren()) { + if (node == o) { + return true; + } + } + return false; + } +} diff --git a/jastadd-mquat-base/src/main/jastadd/solvers/genetic/Checking.jrag b/jastadd-mquat-base/src/main/jastadd/solvers/genetic/Checking.jrag new file mode 100644 index 0000000..8ab4e34 --- /dev/null +++ b/jastadd-mquat-base/src/main/jastadd/solvers/genetic/Checking.jrag @@ -0,0 +1,150 @@ +aspect Checking { + + syn int Solution.evaluateValidity() { + + int faults = evaluateSoftwareCompletenessa(); + + Set<Request> requestSet = new HashSet<>(); + Set<Resource> resourceSet = new HashSet<>(); + + // check assignments + Iterator<Assignment> assignmentIterator = this.assignmentIterator(); + while (assignmentIterator.hasNext()) { + Assignment assignment = assignmentIterator.next(); + faults += assignment.evaluateValidity(); + + + if (assignment.getImplementation().containingComponent() == + assignment.getRequest().getTarget().getRef()) { + requestSet.add(assignment.getRequest()); + } + if (resourceSet.contains(assignment.getResource())) { + // double usage of resources + faults++; + } + resourceSet.add(assignment.getResource()); + + } + + return faults; + } + + syn int Assignment.evaluateValidity() { + + int faults = 0; + + if (getResource() == null) { + faults++; + } + for (Clause clause : getImplementation().requirementClauses()) { + if (!clause.checkUsing(this)) { + faults++; + } + } + // if this is a "top-level" assignment, check the properties from the request + if (this.getRequest().getTarget().getRef().equals(getImplementation().containingComponent())) { + for (Clause clause : getRequest().getConstraintList()) { + if (clause.isRequiringClause() && !clause.checkUsing(this)) { + faults++; + } + } + } + return faults; + } + + syn int Solution.evaluateSoftwareValidity() { + + int faults = evaluateSoftwareCompletenessa(); + + // check assignments + Iterator<Assignment> assignmentIterator = this.assignmentIterator(); + while (assignmentIterator.hasNext()) { + faults += assignmentIterator.next().evaluateSoftwareValidity(); + } + + return faults; + } + + syn int Assignment.evaluateSoftwareValidity() { + + int faults = 0; + + for (Clause clause : getImplementation().requirementClauses()) { + if (clause.getDesignator().isSoftwareDesignator()) { + if (!clause.checkUsing(this)) { + faults++; + } + } + + } + + // if this is a "top-level" assignment, check the properties from the request + if (this.getRequest().getTarget().getRef().equals(getImplementation().containingComponent())) { + for (Clause clause : getRequest().getConstraintList()) { + if (clause.isRequiringClause() && clause.getDesignator().isSoftwareDesignator()) { + if (!clause.checkUsing(this)) { + faults++; + } + } + } + } + + return faults; + } + + syn int Solution.evaluateSoftwareCompletenessa() { + + int faults = 0; + + java.util.List<Component> targets = new java.util.ArrayList<>(); + for (Request request : this.getModel().getRequestList()) { + targets.add(request.getTarget().getRef()); + } + + for (Assignment assignment : getAssignmentList()) { + faults += assignment.evaluateSoftwareCompletenessa(); + targets.remove(assignment.getImplementation().containingComponent()); + } + + for (Component target : targets) { +// System.out.println("[SOFTWARE SOLUTION STRUCTURAL CHECK] request for component " + target.getName().getName() + " has no assignment."); + } + + return faults + targets.size(); + } + + syn int Assignment.evaluateSoftwareCompletenessa() { + int faults = 0; + + if (getRequest() == null) { + faults++; +// System.out.println("[SOFTWARE SOLUTION STRUCTURAL CHECK] assignment " + this.name() + " has no request."); + } + if (getImplementation() == null) { + faults++; +// System.out.println("[SOFTWARE SOLUTION STRUCTURAL CHECK] assignment " + this.name() + " has no implementation."); + } + + for (ComponentRequirement requirement : getImplementation().getComponentRequirementList()) { + for (Instance instance : requirement.getInstanceList()) { + boolean foundInstance = false; + for (ComponentMapping mapping : this.getComponentMappingList()) { + if (mapping.getInstance() == instance) { + if (foundInstance == true) { + faults++; +// System.out.println("[SOFTWARE SOLUTION STRUCTURAL CHECK] instance " + instance.getName().getName() + " is contained twice in the component mapping."); + } + foundInstance = true; + } + } + if (!foundInstance) { + faults++; +// System.out.println("[SOFTWARE SOLUTION STRUCTURAL CHECK] instance " + instance.getName().getName() + " is not contained in the assignment."); + } + } + } + + return faults; + } + +} diff --git a/jastadd-mquat-benchmark/build.gradle b/jastadd-mquat-benchmark/build.gradle index 173dc28..19d6281 100644 --- a/jastadd-mquat-benchmark/build.gradle +++ b/jastadd-mquat-benchmark/build.gradle @@ -15,6 +15,7 @@ dependencies { compile project(':jastadd-mquat-solver-aco') compile project(':jastadd-mquat-solver-ilp') compile project(':jastadd-mquat-solver-emfer') + compile project(':jastadd-mquat-solver-genetic') compile project(':jastadd-mquat-solver-simple') compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.8.8.1' compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.10.0' diff --git a/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/SolverFactory.java b/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/SolverFactory.java index 402cad7..cdfe604 100644 --- a/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/SolverFactory.java +++ b/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/SolverFactory.java @@ -3,6 +3,7 @@ package de.tudresden.inf.st.mquat.benchmark; import de.tudresden.inf.st.mquat.solving.BenchmarkableSolver; import de.tudresden.inf.st.mquat.solving.ilp.ILPDirectSolver; import de.tudresden.inf.st.mquat.solving.ilp.ILPExternalSolver; +import de.tudresden.inf.st.mquat.solving.genetic.GeneticSolver; import de.tudresden.inf.st.mquat.solving.simple.SimpleSolver; import ir.ac.ui.eng.ACOSolver; import uniks.EMFeRSolver; @@ -28,7 +29,8 @@ public class SolverFactory { new EMFeRSolver(), new ILPExternalSolver(), new ILPDirectSolver(), - new SimpleSolver() + new SimpleSolver(), + new GeneticSolver() ).collect(Collectors.toMap(BenchmarkableSolver::getName, Function.identity())); } return availableSolvers; diff --git a/jastadd-mquat-solver-genetic/.gitignore b/jastadd-mquat-solver-genetic/.gitignore new file mode 100644 index 0000000..3cdae3a --- /dev/null +++ b/jastadd-mquat-solver-genetic/.gitignore @@ -0,0 +1,2 @@ +build/ +log/ \ No newline at end of file diff --git a/jastadd-mquat-solver-genetic/build.gradle b/jastadd-mquat-solver-genetic/build.gradle new file mode 100644 index 0000000..4ff9f9b --- /dev/null +++ b/jastadd-mquat-solver-genetic/build.gradle @@ -0,0 +1,24 @@ + +apply plugin: 'java' + +sourceCompatibility = 1.8 + +repositories { + mavenCentral() +} + +dependencies { + compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.10.0' + compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.10.0' + compile project(':jastadd-mquat-base') + compile project(':jastadd-mquat-solver') + testCompile group: 'junit', name: 'junit', version: '4.12' + testCompile project(path: ':jastadd-mquat-solver', configuration: 'testArtifacts') + + compile group: 'org.opt4j', name: 'opt4j-core', version: '3.1.4' + compile group: 'org.opt4j', name: 'opt4j-optimizers', version: '3.1.4' + compile group: 'org.opt4j', name: 'opt4j-operators', version: '3.1.4' + compile group: 'org.opt4j', name: 'opt4j-satdecoding', version: '3.1.4' + compile group: 'org.opt4j', name: 'opt4j-viewer', version: '3.1.4' + compile group: 'org.opt4j', name: 'opt4j-benchmarks', version: '3.1.4' +} diff --git a/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/GeneticSolver.java b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/GeneticSolver.java new file mode 100644 index 0000000..bb07c44 --- /dev/null +++ b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/GeneticSolver.java @@ -0,0 +1,100 @@ +package de.tudresden.inf.st.mquat.solving.genetic; + +import de.tudresden.inf.st.mquat.jastadd.model.Root; +import de.tudresden.inf.st.mquat.jastadd.model.Solution; +import de.tudresden.inf.st.mquat.solving.BenchmarkableSolver; +import de.tudresden.inf.st.mquat.solving.Solver; +import de.tudresden.inf.st.mquat.solving.SolvingException; +import de.tudresden.inf.st.mquat.utils.StopWatch; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +public class GeneticSolver implements BenchmarkableSolver { + + private static final Logger logger = LogManager.getLogger(GeneticSolver.class); + + private Solution lastSolution; + private long lastSolvingTime; + + private int solutionCounter; + + private StopWatch stopWatch; + + private long maxSolvingTime; + private boolean timedOut; + + public GeneticSolver() { + this(Long.MAX_VALUE); + } + + public GeneticSolver(long maxSolvingTime) { + this.maxSolvingTime = maxSolvingTime; + reset(); + } + + @Override + public Solution solve(Root model) throws SolvingException { + reset(); + if (model.getNumRequest() == 0) { + return Solution.emptySolutionOf(model); + } + stopWatch = StopWatch.start(); + + List<Solution> solutions = new ArrayList<>(); + + // do some solvin' + + if (solutions.size() > 0) { + lastSolution = solutions.get(solutions.size() - 1); + } else { + lastSolution = Solution.emptySolutionOf(model); + logger.warn("Found no solution!"); + } + + lastSolvingTime = stopWatch.time(TimeUnit.MILLISECONDS); + + return lastSolution; + } + + private void reset() { + this.lastSolution = null; + this.solutionCounter = 0; + this.lastSolvingTime = 0; + this.timedOut = false; + } + + @Override + public String getName() { + return "genetic"; + } + + @Override + public long getLastSolvingTime() { + return lastSolvingTime; + } + + @Override + public double getLastObjective() { + if (lastSolution != null) { + return lastSolution.computeObjective(); + } else { + // TODO throw exception or do something reasonable + return 0d; + } + } + + @Override + public Solver setTimeout(long timeoutValue, TimeUnit timeoutUnit) { + this.maxSolvingTime = timeoutUnit.toMillis(timeoutValue); + return this; + } + + @Override + public boolean hadTimeout() { + return this.timedOut; + } +} diff --git a/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/Opt4jCreator.java b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/Opt4jCreator.java new file mode 100644 index 0000000..948c888 --- /dev/null +++ b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/Opt4jCreator.java @@ -0,0 +1,43 @@ +package de.tudresden.inf.st.mquat.solving.genetic.opt4j; + +import de.tudresden.inf.st.mquat.jastadd.model.*; +import de.tudresden.inf.st.mquat.solving.genetic.opt4j.custom.genotypes.TreeGenotype; +import de.tudresden.inf.st.mquat.solving.genetic.opt4j.custom.genotypes.TreeGenotypeNode; +import org.opt4j.core.problem.Creator; + +import java.util.Random; + +public class Opt4jCreator implements Creator<TreeGenotype> { + + public static TreeGenotypeNode<Request, Instance, Resource, Implementation> createNode(Assignment assignment, TreeGenotype<Request, Instance, Resource, Implementation> container) { + + TreeGenotypeNode<Request, Instance, Resource, Implementation> node = new TreeGenotypeNode<>(container); + node.setImpl(assignment.getImplementation()); + node.setResource(assignment.getResource()); + for (ComponentMapping subAssignment : assignment.getComponentMappingList()) { + node.getSubStructure().put(subAssignment.getInstance(), createNode(subAssignment.getAssignment(), container)); + } + + return node; + } + + public TreeGenotype<Request, Instance, Resource, Implementation> create() { + + // TODO this method create a phenotype and translates it to a genotype. this is not nice! + + Root model = Opt4jModule.getModel(); + + Solution phenotype = model.createRandomSolution(new Random()); + + TreeGenotype<Request, Instance, Resource, Implementation> genotype = new TreeGenotype<>(model.getHardwareModel().allContainers()); + + for (Assignment a : phenotype.getAssignmentList()) { + if (a.getTopLevel() && a.getImplementation().getName().getName().length() > 19) { + throw new RuntimeException(); + } + genotype.getRequestMap().put(a.getRequest(), createNode(a, genotype)); + } + + return genotype; + } +} diff --git a/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/Opt4jDecoder.java b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/Opt4jDecoder.java new file mode 100644 index 0000000..6eee40f --- /dev/null +++ b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/Opt4jDecoder.java @@ -0,0 +1,74 @@ +package de.tudresden.inf.st.mquat.solving.genetic.opt4j; + +import de.tudresden.inf.st.mquat.jastadd.model.*; +import de.tudresden.inf.st.mquat.solving.genetic.opt4j.custom.genotypes.TreeGenotype; +import de.tudresden.inf.st.mquat.solving.genetic.opt4j.custom.genotypes.TreeGenotypeNode; +import org.opt4j.core.problem.Decoder; + +import java.util.Map; + +public class Opt4jDecoder implements Decoder<TreeGenotype<Request, Instance, Resource, Implementation>, Solution> { + + + private static void populateResourceMapping(ResourceMapping mapping, ResourceRequirement requirement, + Resource resource) { + for (ResourceRequirement subRequirement : requirement.getResourceRequirementList()) { + int fittingResourceCount = 0; + for (int currentInstance = 0; currentInstance < subRequirement.getNumInstance(); currentInstance++) { + for (int currentResource = 0; currentResource < resource.getNumSubResource(); currentResource++) { + Resource subResource = resource.getSubResource(currentResource); + if (subResource.getType().getRef() == subRequirement.getResourceTypeRef().getRef()) { + if (currentInstance == fittingResourceCount) { + ResourceMapping newMapping = new ResourceMapping(); + Instance instance = subRequirement.getInstance(currentInstance); + newMapping.setInstance(instance); + newMapping.setResource(subResource); + mapping.addResourceMapping(newMapping); + populateResourceMapping(newMapping, subRequirement, subResource); + fittingResourceCount++; + } + currentInstance++; + } + } + } + } + } + + @Override + public Solution decode(TreeGenotype<Request, Instance, Resource, Implementation> genotype) { + Solution phenotype = new Solution(); + phenotype.setModel(Opt4jModule.getModel()); + for (Map.Entry<Request, TreeGenotypeNode<Request, Instance, Resource, Implementation>> e : genotype.getRequestMap() + .entrySet()) { + + phenotype.addAssignment(decodeNode(true, e.getKey(), e.getValue())); + } + + return phenotype; + } + + private Assignment decodeNode(boolean isTopLevel, Request request, TreeGenotypeNode<Request, Instance, Resource, Implementation> node) { + + Assignment assignment = new Assignment(); + + assignment.setTopLevel(isTopLevel); + assignment.setRequest(request); + assignment.setImplementation(node.getImpl()); + + // fix the resource mapping + // we assume that exactly one resource is required + Instance resourceInstance = node.getImpl().getResourceRequirement().getInstance(0); + ResourceMapping rm = new ResourceMapping(); + rm.setInstance(resourceInstance); + rm.setResource(node.getResource()); + populateResourceMapping(rm, node.getImpl().getResourceRequirement(), node.getResource()); + assignment.setResourceMapping(rm); + + for (Map.Entry<Instance, TreeGenotypeNode<Request, Instance, Resource, Implementation>> e : node.getSubStructure() + .entrySet()) { + + assignment.addComponentMapping(new ComponentMapping(e.getKey(), decodeNode(false, request, e.getValue()))); + } + return assignment; + } +} diff --git a/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/Opt4jEvaluator.java b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/Opt4jEvaluator.java new file mode 100644 index 0000000..26bfffd --- /dev/null +++ b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/Opt4jEvaluator.java @@ -0,0 +1,34 @@ +package de.tudresden.inf.st.mquat.solving.genetic.opt4j; + +import de.tudresden.inf.st.mquat.jastadd.model.Solution; +import org.opt4j.core.Objective.Sign; +import org.opt4j.core.Objectives; +import org.opt4j.core.problem.Evaluator; + +public class Opt4jEvaluator implements Evaluator<Solution> { + + @Override + public Objectives evaluate(Solution phenotype) { + Objectives objectives = new Objectives(); + objectives.add("Validity Errors", Sign.MIN, phenotype.evaluateValidity() * 1000); + objectives.add("Software Validity Errors", Sign.MIN, phenotype.evaluateSoftwareValidity() * 1000); + objectives.add("Structural Errors", Sign.MIN, phenotype.evaluateSoftwareCompletenessa() * 1000); + + double objective = phenotype.computeObjective(); + + if (phenotype.evaluateValidity() != 0) { + objective *= 10; + } + if (phenotype.evaluateSoftwareValidity() != 0) { + objective *= 10; + } + if (phenotype.evaluateSoftwareCompletenessa() != 0) { + objective *= 10; + } + + objectives.add("Energy", Sign.MIN, objective); + + return objectives; + } + +} diff --git a/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/Opt4jModule.java b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/Opt4jModule.java new file mode 100644 index 0000000..86f1ebc --- /dev/null +++ b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/Opt4jModule.java @@ -0,0 +1,75 @@ +package de.tudresden.inf.st.mquat.solving.genetic.opt4j; + +import de.tudresden.inf.st.mquat.generator.ScenarioDescription; +import de.tudresden.inf.st.mquat.jastadd.model.Root; +import de.tudresden.inf.st.mquat.solving.genetic.opt4j.custom.operator.copy.TreeCopyOperatorModule; +import de.tudresden.inf.st.mquat.solving.genetic.opt4j.custom.operator.crossover.TreeCrossoverOperatorModule; +import de.tudresden.inf.st.mquat.solving.genetic.opt4j.custom.operator.mutate.TreeMutateOperatorModule; +import org.opt4j.core.Individual; +import org.opt4j.core.optimizer.Archive; +import org.opt4j.core.problem.ProblemModule; +import org.opt4j.core.start.Opt4JTask; +import org.opt4j.optimizers.ea.EvolutionaryAlgorithmModule; +import org.opt4j.viewer.ViewerModule; + +public class Opt4jModule extends ProblemModule { + + private static Root model; + + public static Root getModel() { + return model; + } + + public static void setModel(Root model) { + Opt4jModule.model = model; + } + + public static void main(String[] args) { + + final ScenarioDescription SCENARIO_DESCRIPTION = new ScenarioDescription(1, 2, 0, 0, 0, 2, 3, 1.5, 1, 1, 0); + de.tudresden.inf.st.mquat.generator.ScenarioGenerator sc = new de.tudresden.inf.st.mquat.generator.ScenarioGenerator( + SCENARIO_DESCRIPTION); + + Opt4jModule.setModel(sc.generate()); + + EvolutionaryAlgorithmModule ea = new EvolutionaryAlgorithmModule(); + ea.setGenerations(100000); + + // set population size + ea.setAlpha(100); + + Opt4jModule testModule = new Opt4jModule(); + + TreeCrossoverOperatorModule crossover = new TreeCrossoverOperatorModule(); + TreeMutateOperatorModule mutate = new TreeMutateOperatorModule(); + TreeCopyOperatorModule copy = new TreeCopyOperatorModule(); + + // testModule.setFunction(JohannesModule.Function.dtlz); + ViewerModule viewer = new ViewerModule(); + viewer.isCloseOnStop(); + + Opt4JTask task = new Opt4JTask(false); + task.init(ea, testModule, viewer, crossover, mutate, copy); + try { + task.execute(); + Archive archive = task.getInstance(Archive.class); + for (Individual individual : archive) { + // obtain the phenotype and objective, etc. of each individual + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + task.close(); + } + } + + @Override + protected void configure() { + bindProblem(Opt4jCreator.class, Opt4jDecoder.class, Opt4jEvaluator.class); + } + + @Override + protected void config() { + } + +} diff --git a/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/genotypes/TreeGenotype.java b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/genotypes/TreeGenotype.java new file mode 100644 index 0000000..abf0112 --- /dev/null +++ b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/genotypes/TreeGenotype.java @@ -0,0 +1,59 @@ +package de.tudresden.inf.st.mquat.solving.genetic.opt4j.custom.genotypes; + +import org.opt4j.core.Genotype; + +import java.lang.reflect.Constructor; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class TreeGenotype<RqT, InT, ReT, ImT> implements Genotype { + + private List<ReT> resources; + private Map<RqT, TreeGenotypeNode<RqT, InT, ReT, ImT>> requestMap = new HashMap<>(); + + public TreeGenotype(List<ReT> resources) { + this.resources = resources; + } + + public List<ReT> getResources() { + return resources; + } + + @Override + public int size() { + // TODO recurse to find out size + return 0; + } + + @SuppressWarnings("unchecked") + @Override + public TreeGenotype<RqT, InT, ReT, ImT> newInstance() { + try { + Constructor<? extends TreeGenotype> cstr = this.getClass().getConstructor(List.class); + return (TreeGenotype<RqT, InT, ReT, ImT>) cstr.newInstance(getResources()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public Map<RqT, TreeGenotypeNode<RqT, InT, ReT, ImT>> getRequestMap() { + return requestMap; + } + + @Override + public String toString() { + return "[i=" + requestMap + "]"; + } + + public TreeGenotype<RqT, InT, ReT, ImT> deepCopy() { + TreeGenotype<RqT, InT, ReT, ImT> copy = this.newInstance(); + + for (RqT request : requestMap.keySet()) { + copy.getRequestMap().put(request, this.getRequestMap().get(request).deepCopy()); + } + + return copy; + } + +} diff --git a/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/genotypes/TreeGenotypeNode.java b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/genotypes/TreeGenotypeNode.java new file mode 100644 index 0000000..7767486 --- /dev/null +++ b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/genotypes/TreeGenotypeNode.java @@ -0,0 +1,75 @@ +package de.tudresden.inf.st.mquat.solving.genetic.opt4j.custom.genotypes; + +import java.util.*; + +public class TreeGenotypeNode<RqT, InT, ReT, ImT> { + private ImT impl; + private ReT res; + private Map<InT, TreeGenotypeNode<RqT, InT, ReT, ImT>> subNodes; + private TreeGenotype<RqT, InT, ReT, ImT> containingTreeGenotype; + + public TreeGenotypeNode(TreeGenotype genotype) { + this.containingTreeGenotype = genotype; + this.subNodes = new HashMap<>(); + } + + public ImT getImpl() { + return impl; + } + + public void setImpl(ImT i) { + this.impl = i; + } + + public TreeGenotype getContainingGenotype() { + return containingTreeGenotype; + } + + public void setContainingGenotype(TreeGenotype genotype) { + this.containingTreeGenotype = genotype; + for (TreeGenotypeNode subnode : subNodes.values()) { + subnode.setContainingGenotype(genotype); + } + } + + public ReT getResource() { + return res; + } + + public void setResource(ReT r) { + this.res = r; + } + + public Map<InT, TreeGenotypeNode<RqT, InT, ReT, ImT>> getSubStructure() { + return subNodes; + } + + @Override + public String toString() { + return "[i=" + impl + ", r=" + res + ", c=" + subNodes + "]"; + } + + public TreeGenotypeNode<RqT, InT, ReT, ImT> deepCopy() { + + TreeGenotypeNode<RqT, InT, ReT, ImT> copy = new TreeGenotypeNode<>(getContainingGenotype()); + + copy.setResource(this.getResource()); + copy.setImpl(this.getImpl()); + + for (InT instance : this.getSubStructure().keySet()) { + copy.getSubStructure().put(instance, this.getSubStructure().get(instance).deepCopy()); + } + return copy; + } + + public Collection<ReT> containedResources() { + + List<ReT> resources = new ArrayList<>(); + resources.add(this.getResource()); + for (TreeGenotypeNode subNode : subNodes.values()) { + resources.addAll(subNode.containedResources()); + } + + return resources; + } +} diff --git a/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/copy/TreeCopyOperator.java b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/copy/TreeCopyOperator.java new file mode 100644 index 0000000..979f951 --- /dev/null +++ b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/copy/TreeCopyOperator.java @@ -0,0 +1,16 @@ +package de.tudresden.inf.st.mquat.solving.genetic.opt4j.custom.operator.copy; + +import de.tudresden.inf.st.mquat.solving.genetic.opt4j.custom.genotypes.TreeGenotype; +import org.opt4j.operators.Apply; +import org.opt4j.operators.copy.Copy; + +@Apply(TreeGenotype.class) +public class TreeCopyOperator implements Copy<TreeGenotype> { + + @Override + public TreeGenotype copy(TreeGenotype genotype) { + + return genotype.deepCopy(); + } + +} diff --git a/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/copy/TreeCopyOperatorModule.java b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/copy/TreeCopyOperatorModule.java new file mode 100644 index 0000000..0b3f026 --- /dev/null +++ b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/copy/TreeCopyOperatorModule.java @@ -0,0 +1,12 @@ +package de.tudresden.inf.st.mquat.solving.genetic.opt4j.custom.operator.copy; + +import org.opt4j.operators.copy.CopyModule; + +public class TreeCopyOperatorModule extends CopyModule { + + @Override + protected void config() { + addOperator(TreeCopyOperator.class); + } + +} diff --git a/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/crossover/TreeCrossoverOperator.java b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/crossover/TreeCrossoverOperator.java new file mode 100644 index 0000000..936133c --- /dev/null +++ b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/crossover/TreeCrossoverOperator.java @@ -0,0 +1,94 @@ +package de.tudresden.inf.st.mquat.solving.genetic.opt4j.custom.operator.crossover; + +import de.tudresden.inf.st.mquat.jastadd.model.Implementation; +import de.tudresden.inf.st.mquat.jastadd.model.Instance; +import de.tudresden.inf.st.mquat.jastadd.model.Request; +import de.tudresden.inf.st.mquat.jastadd.model.Resource; +import de.tudresden.inf.st.mquat.solving.genetic.opt4j.custom.genotypes.TreeGenotype; +import de.tudresden.inf.st.mquat.solving.genetic.opt4j.custom.genotypes.TreeGenotypeNode; +import org.opt4j.operators.Apply; +import org.opt4j.operators.crossover.Crossover; +import org.opt4j.operators.crossover.Pair; + +@Apply(TreeGenotype.class) +public class TreeCrossoverOperator implements Crossover<TreeGenotype<Request, Instance, Resource, Implementation>> { + + private static final double probability = 0.5; + + @Override + public Pair<TreeGenotype<Request, Instance, Resource, Implementation>> crossover( + TreeGenotype<Request, Instance, Resource, Implementation> oldGenotype1, + TreeGenotype<Request, Instance, Resource, Implementation> oldGenotype2) { + + TreeGenotype<Request, Instance, Resource, Implementation> newGenotype1 = oldGenotype1.newInstance(); + TreeGenotype<Request, Instance, Resource, Implementation> newGenotype2 = oldGenotype2.newInstance(); + + for (Request request : oldGenotype1.getRequestMap().keySet()) { + + TreeGenotypeNode childOfOldGenotype1 = oldGenotype1.getRequestMap().get(request); + TreeGenotypeNode childOfOldGenotype2 = oldGenotype2.getRequestMap().get(request); + + Pair<TreeGenotypeNode<Request, Instance, Resource, Implementation>> crossedPair = nodeStructureCrossover(childOfOldGenotype1, newGenotype1, childOfOldGenotype2, newGenotype2); + + newGenotype1.getRequestMap().put(request, crossedPair.getFirst()); + newGenotype2.getRequestMap().put(request, crossedPair.getSecond()); + } + + return new Pair<>(newGenotype1, newGenotype2); + } + + private Pair<TreeGenotypeNode<Request, Instance, Resource, Implementation>> nodeStructureCrossover( + TreeGenotypeNode<Request, Instance, Resource, Implementation> oldNode1, + TreeGenotype<Request, Instance, Resource, Implementation> newContainer1, + TreeGenotypeNode<Request, Instance, Resource, Implementation> oldNode2, + TreeGenotype<Request, Instance, Resource, Implementation> newContainer2) { + + TreeGenotypeNode<Request, Instance, Resource, Implementation> newNode1 = new TreeGenotypeNode<>(newContainer1); + TreeGenotypeNode<Request, Instance, Resource, Implementation> newNode2 = new TreeGenotypeNode<>(newContainer2); + + // if both nodes have the same impl and resource, recurse + if (oldNode1.getImpl() == oldNode2.getImpl() && oldNode1.getResource() == oldNode2.getResource()) { + + // transfer impl and resource from old to new + newNode1.setImpl(oldNode1.getImpl()); + newNode1.setResource(oldNode1.getResource()); + newNode2.setImpl(oldNode2.getImpl()); + newNode2.setResource(oldNode2.getResource()); + + // call the crossover on all child substructures + for (Instance instance : oldNode1.getSubStructure().keySet()) { + TreeGenotypeNode childOfOldNode1 = oldNode1.getSubStructure().get(instance); + TreeGenotypeNode childOfOldNode2 = oldNode2.getSubStructure().get(instance); + Pair<TreeGenotypeNode<Request, Instance, Resource, Implementation>> crossedPair = nodeStructureCrossover(childOfOldNode1, newContainer1, childOfOldNode2, newContainer2); + + newNode1.getSubStructure().put(instance, crossedPair.getFirst()); + newNode2.getSubStructure().put(instance, crossedPair.getSecond()); + } + } else { + // TODO figure out what to swap + boolean swapImpl = true; + boolean swapResource = true; + + if (swapImpl) { + newNode1.setImpl(oldNode2.getImpl()); + newNode2.setImpl(oldNode1.getImpl()); + + // add swapped substructures + for (Instance instance : oldNode1.getSubStructure().keySet()) { + newNode2.getSubStructure().put(instance, oldNode1.getSubStructure().get(instance).deepCopy()); + } + for (Instance instance : oldNode2.getSubStructure().keySet()) { + newNode1.getSubStructure().put(instance, oldNode2.getSubStructure().get(instance).deepCopy()); + } + } + + if (swapResource) { + newNode1.setResource(oldNode2.getResource()); + newNode2.setResource(oldNode1.getResource()); + } + } + + return new Pair<>(newNode1, newNode2); + } + +} \ No newline at end of file diff --git a/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/crossover/TreeCrossoverOperatorModule.java b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/crossover/TreeCrossoverOperatorModule.java new file mode 100644 index 0000000..89ce508 --- /dev/null +++ b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/crossover/TreeCrossoverOperatorModule.java @@ -0,0 +1,21 @@ +package de.tudresden.inf.st.mquat.solving.genetic.opt4j.custom.operator.crossover; + +import org.opt4j.operators.crossover.CrossoverModule; + +public class TreeCrossoverOperatorModule extends CrossoverModule { + + @Override + protected void config() { + // TODO Auto-generated method stub + + addOperator(TreeCrossoverOperator.class); + } + +// @Override +// protected void configure() { +// // TODO Auto-generated method stub +// bind(TreeOperator.class).to(TreeOperator.class); +// } +// + +} \ No newline at end of file diff --git a/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/mutate/TreeMutateOperator.java b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/mutate/TreeMutateOperator.java new file mode 100644 index 0000000..a28f1a8 --- /dev/null +++ b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/mutate/TreeMutateOperator.java @@ -0,0 +1,83 @@ +package de.tudresden.inf.st.mquat.solving.genetic.opt4j.custom.operator.mutate; + +import com.google.inject.Inject; +import de.tudresden.inf.st.mquat.jastadd.model.*; +import de.tudresden.inf.st.mquat.solving.genetic.opt4j.Opt4jCreator; +import de.tudresden.inf.st.mquat.solving.genetic.opt4j.custom.genotypes.TreeGenotype; +import de.tudresden.inf.st.mquat.solving.genetic.opt4j.custom.genotypes.TreeGenotypeNode; +import org.opt4j.core.common.random.Rand; +import org.opt4j.operators.Apply; +import org.opt4j.operators.mutate.Mutate; + +import java.util.List; +import java.util.Random; + +@Apply(TreeGenotype.class) +public class TreeMutateOperator implements Mutate<TreeGenotype<Request, Instance, Resource, Implementation>> { + + protected final Random random; + public static double Min = 0.0d; + public static double Max = 1.0d; + + @Inject + public TreeMutateOperator(Rand random) { + this.random = random; + } + + @Override + public void mutate(TreeGenotype<Request, Instance, Resource, Implementation> genotype, double p) { + + for (Request e : genotype.getRequestMap() + .keySet()) { + + TreeGenotypeNode<Request, Instance, Resource, Implementation> node = genotype.getRequestMap().get(e); + + double randomValue = Min + (Max - Min) * this.random.nextDouble(); + + if (true) { + genotype.getRequestMap().put(e, mutateNode(e, node, p)); + } + + } + } + + private TreeGenotypeNode<Request, Instance, Resource, Implementation> mutateNode(Request request, + TreeGenotypeNode<Request, Instance, Resource, Implementation> node, double p) { + + double Min = 0; + double Max = 1; + double randomValue = Min + (Max - Min) * this.random.nextDouble(); + + if (randomValue < .5) { + + Component comp = node.getImpl().containingComponent(); + Implementation newImp = comp.getImplementation(this.random.nextInt(comp.getNumImplementation())); + + // clear substructure requirements + List<Resource> unassignedResources = node.getContainingGenotype().getResources(); + // add newly freed resources + for (TreeGenotypeNode subNode : node.getSubStructure().values()) { + unassignedResources.addAll(subNode.containedResources()); + } + node.getSubStructure().clear(); + + node.setImpl(newImp); + + for (ComponentRequirement cr : newImp.getComponentRequirementList()) { + for (Instance ci : cr.getInstanceList()) { + // create node + Assignment newAssignment = newImp.root().createRandomAssignment(false, request, cr.getComponentRef().getRef(), unassignedResources, new Random()); + node.getSubStructure().put(ci, Opt4jCreator.createNode(newAssignment, node.getContainingGenotype())); + } + } + } else { + // mutate the children + for (Instance instance : node.getSubStructure().keySet()) { + node.getSubStructure().put(instance, mutateNode(request, node.getSubStructure().get(instance), p)); + } + } + + return node; + } + +} diff --git a/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/mutate/TreeMutateOperatorModule.java b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/mutate/TreeMutateOperatorModule.java new file mode 100644 index 0000000..d23c427 --- /dev/null +++ b/jastadd-mquat-solver-genetic/src/main/java/de/tudresden/inf/st/mquat/solving/genetic/opt4j/custom/operator/mutate/TreeMutateOperatorModule.java @@ -0,0 +1,12 @@ +package de.tudresden.inf.st.mquat.solving.genetic.opt4j.custom.operator.mutate; + +import org.opt4j.operators.mutate.MutateModule; + +public class TreeMutateOperatorModule extends MutateModule { + + @Override + protected void config() { + addOperator(TreeMutateOperator.class); + } + +} diff --git a/jastadd-mquat-solver-genetic/src/test/java/de/tudresden/inf/st/mquat/solving/SimpleHandwrittenTest.java b/jastadd-mquat-solver-genetic/src/test/java/de/tudresden/inf/st/mquat/solving/SimpleHandwrittenTest.java new file mode 100644 index 0000000..380e0ad --- /dev/null +++ b/jastadd-mquat-solver-genetic/src/test/java/de/tudresden/inf/st/mquat/solving/SimpleHandwrittenTest.java @@ -0,0 +1,11 @@ +package de.tudresden.inf.st.mquat.solving; + +import de.tudresden.inf.st.mquat.solving.genetic.GeneticSolver; + +public class SimpleHandwrittenTest extends HandwrittenTestSuite { + + @Override + protected Solver getSolver() { + return new GeneticSolver(10000); + } +} diff --git a/jastadd-mquat-solver-genetic/src/test/java/de/tudresden/inf/st/mquat/solving/SimpleSolverTest.java b/jastadd-mquat-solver-genetic/src/test/java/de/tudresden/inf/st/mquat/solving/SimpleSolverTest.java new file mode 100644 index 0000000..1af1407 --- /dev/null +++ b/jastadd-mquat-solver-genetic/src/test/java/de/tudresden/inf/st/mquat/solving/SimpleSolverTest.java @@ -0,0 +1,54 @@ +package de.tudresden.inf.st.mquat.solving; + +import de.tudresden.inf.st.mquat.generator.ScenarioDescription; +import de.tudresden.inf.st.mquat.generator.ScenarioGenerator; +import de.tudresden.inf.st.mquat.jastadd.model.Root; +import de.tudresden.inf.st.mquat.jastadd.model.Solution; +import de.tudresden.inf.st.mquat.solving.genetic.GeneticSolver; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +public class SimpleSolverTest { + + private static Logger logger; + + @BeforeClass + public static void initLogger() { + logger = LogManager.getLogger(SimpleSolverTest.class); + } + + /** + * tests the genetic solver with one very genetic use case + */ + @Test + public void testSimpleSolver() throws SolvingException { + int tlc = 1; + int iac = 2; + int isd = 0; + int cac = 0; + int csd = 0; + int dep = 2; + int imp = 1; + int mod = 3; + double res = 1.5d; + int nfp = 0; + int req = 3; + int cpu = 1; + int seed = 0; + + ScenarioGenerator generator = new ScenarioGenerator(new ScenarioDescription(tlc, iac, isd, cac, csd, dep, imp, res, req, cpu, seed)); + + Root model = generator.generate(); + GeneticSolver solver = new GeneticSolver(20000); + + Solution solution = solver.solve(model); + + Assert.assertNotNull(solution); + + logger.info("the best solution is {} and has an objective of {}.", (solution.isValid() ? "valid" : "invalid"), solution.computeObjective()); + + } +} diff --git a/settings.gradle b/settings.gradle index 6eb5a59..68483c9 100644 --- a/settings.gradle +++ b/settings.gradle @@ -5,6 +5,7 @@ include ':jastadd-mquat-benchmark' include ':jastadd-mquat-solver' include ':jastadd-mquat-solver-ilp' include ':jastadd-mquat-solver-emfer' +include ':jastadd-mquat-solver-genetic' include ':jastadd-mquat-solver-simple' include 'jastadd-mquat-solver-aco' -- GitLab