From c0c5a1644cc221352b8b9b370eea6a87677ba948 Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Sat, 15 Jun 2019 20:56:47 -0400 Subject: Try fix statecode bug Modified graph width calculation to not depend on order of nodes --- .../neighbourhood/Descriptor.xtend | 188 +++++---- .../neighbourhood/NeighbourhoodOptions.xtend | 22 + ...nterpretation2NeighbourhoodRepresentation.xtend | 456 +++++++++++---------- ...ation2PairwiseNeighbourhoodRepresentation.xtend | 68 +++ ...bstractNeighborhoodBasedStateCoderFactory.xtend | 137 +++++++ .../IdentifierBasedStateCoderFactory.xtend | 4 +- .../NeighbourhoodBasedStateCoderFactory.xtend | 275 ++++--------- ...irwiseNeighbourhoodBasedStateCoderFactory.xtend | 75 ++++ .../viatrasolver/reasoner/ViatraReasoner.xtend | 9 +- .../reasoner/ViatraReasonerConfiguration.xtend | 3 +- .../dse/BestFirstStrategyForModelGeneration.java | 8 +- .../AbstractThreeValuedObjective.xtend | 71 +--- .../CompositeDirectionalThresholdObjective.xtend | 62 +++ .../DirectionalThresholdObjective.xtend | 164 ++++++++ .../reasoner/optimization/MatchCostObjective.xtend | 52 +++ .../reasoner/optimization/ObjectiveKind.java | 24 ++ .../optimization/QueryBasedObjective.xtend | 48 +++ .../optimization/ThreeValuedCostObjective.xtend | 2 +- 18 files changed, 1095 insertions(+), 573 deletions(-) create mode 100644 Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/NeighbourhoodOptions.xtend create mode 100644 Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2PairwiseNeighbourhoodRepresentation.xtend create mode 100644 Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/AbstractNeighborhoodBasedStateCoderFactory.xtend create mode 100644 Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/PairwiseNeighbourhoodBasedStateCoderFactory.xtend create mode 100644 Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CompositeDirectionalThresholdObjective.xtend create mode 100644 Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/DirectionalThresholdObjective.xtend create mode 100644 Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/MatchCostObjective.xtend create mode 100644 Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/QueryBasedObjective.xtend (limited to 'Solvers') diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/Descriptor.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/Descriptor.xtend index 41482b28..c7c1ad77 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/Descriptor.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/Descriptor.xtend @@ -4,10 +4,21 @@ import java.util.HashMap import java.util.Map import java.util.Set import org.eclipse.xtend.lib.annotations.Data +import org.eclipse.xtend2.lib.StringConcatenationClient @Data abstract class AbstractNodeDescriptor { long dataHash - + + protected def StringConcatenationClient prettyPrint() { + '''(«dataHash»)[«class.simpleName»]''' + } + + override toString() { + ''' + «prettyPrint» + ''' + } + // @Pure // @Override // override public boolean equals(Object obj) { @@ -24,34 +35,41 @@ import org.eclipse.xtend.lib.annotations.Data // } } -@Data class LocalNodeDescriptor extends AbstractNodeDescriptor{ +@Data class LocalNodeDescriptor extends AbstractNodeDescriptor { Set types String id; + new(String id, Set types) { - super(calcualteDataHash(id,types)) + super(calcualteDataHash(id, types)) this.types = types this.id = id } - + def private static calcualteDataHash(String id, Set types) { val int prime = 31; var result = 0 - if(id !== null) - result = id.hashCode(); - if(types !== null) { - result = prime * result + types.hashCode - } - return result + if (id !== null) + result = id.hashCode(); + if (types !== null) { + result = prime * result + types.hashCode + } + return result } - + override hashCode() { return this.dataHash.hashCode } - + + override protected prettyPrint() { + '''(«dataHash»)[«IF id !== null»id = "«id»"«IF types === null || !types.empty», «ENDIF»«ENDIF»«IF types === null»TYPES = null«ELSE»«FOR type : types SEPARATOR ", "»«type»«ENDFOR»«ENDIF»]''' + } + override toString() { - return class.name + this.dataHash + ''' + «prettyPrint» + ''' } - + // @Pure // @Override // override public boolean equals(Object obj) { @@ -66,7 +84,6 @@ import org.eclipse.xtend.lib.annotations.Data // return false; // return true; // } - // @Pure // override public boolean equals(Object obj) { // if (this === obj) @@ -97,49 +114,70 @@ import org.eclipse.xtend.lib.annotations.Data String type } -@Data class FurtherNodeDescriptor extends AbstractNodeDescriptor{ - - NodeRep previousRepresentation - Map,Integer> incomingEdges - Map,Integer> outgoingEdges - - new( - NodeRep previousRepresentation, - Map,Integer> incomingEdges, - Map,Integer> outgoingEdges) - { - super(calculateDataHash(previousRepresentation,incomingEdges,outgoingEdges)) - this.previousRepresentation = previousRepresentation - this.incomingEdges = new HashMap(incomingEdges) - this.outgoingEdges = new HashMap(outgoingEdges) - } - - static def private int calculateDataHash( - NodeRep previousRepresentation, - Map,Integer> incomingEdges, - Map,Integer> outgoingEdges) - { - val int prime = 31; - var int result = previousRepresentation.hashCode; - if(incomingEdges !== null) - result = prime * result + incomingEdges.hashCode(); - if(outgoingEdges !== null) - result = prime * result + outgoingEdges.hashCode(); - return result; - } - - override hashCode() { - return this.dataHash.hashCode +@Data class FurtherNodeDescriptor extends AbstractNodeDescriptor { + + NodeRep previousRepresentation + Map, Integer> incomingEdges + Map, Integer> outgoingEdges + + new(NodeRep previousRepresentation, Map, Integer> incomingEdges, + Map, Integer> outgoingEdges) { + super(calculateDataHash(previousRepresentation, incomingEdges, outgoingEdges)) + this.previousRepresentation = previousRepresentation + this.incomingEdges = new HashMap(incomingEdges) + this.outgoingEdges = new HashMap(outgoingEdges) } - + + static def private int calculateDataHash(NodeRep previousRepresentation, + Map, Integer> incomingEdges, Map, Integer> outgoingEdges) { + val int prime = 31; + var int result = previousRepresentation.hashCode; + if (incomingEdges !== null) + result = prime * result + incomingEdges.hashCode(); + if (outgoingEdges !== null) + result = prime * result + outgoingEdges.hashCode(); + return result; + } + + override hashCode() { + return this.dataHash.hashCode + } + + override prettyPrint() { + ''' + («dataHash»)[ + PREV = «previousRepresentation?.prettyPrint» + «IF incomingEdges === null» + IN null + «ELSE» + «FOR edge : incomingEdges.entrySet» + IN «edge.value» «edge.key.type» = «edge.key.from.prettyPrint» + «ENDFOR» + «ENDIF» + «IF outgoingEdges === null» + OUT null + «ELSE» + «FOR edge : outgoingEdges.entrySet» + OUT «edge.value» «edge.key.type» = «edge.key.to.prettyPrint» + «ENDFOR» + «ENDIF» + ]''' + } + + private def StringConcatenationClient prettyPrint(NodeRep rep) { + if (rep instanceof AbstractNodeDescriptor) { + rep.prettyPrint + } else { + '''«rep»''' + } + } + override toString() { - return class.name + dataHash -// return '''[«previousRepresentation»,(«FOR -// in: incomingEdges.entrySet»(«in.key.type.name»=«in.key.from»,«in.value»)«ENDFOR»),(«FOR -// out: outgoingEdges.entrySet»(«out.key.type.name»=«out.key.to»,«out.value»)«ENDFOR»),«FOR -// att: attributeValues»(«att.type.name»=«att.value»)«ENDFOR»]''' + ''' + «prettyPrint» + ''' } - + // @Pure // @Override // override public boolean equals(Object obj) { @@ -154,7 +192,6 @@ import org.eclipse.xtend.lib.annotations.Data // return false; // return true; // } - // @Pure // override public boolean equals(Object obj) { // if (this === obj) @@ -191,24 +228,23 @@ import org.eclipse.xtend.lib.annotations.Data // return true; // } } - /* -@Data -class ModelDescriptor { - int dataHash - int unknownElements - Map knownElements - - public new(Map knownElements, int unknownElements) { - this.dataHash = calculateDataHash(knownElements,unknownElements) - this.unknownElements = unknownElements - this.knownElements = knownElements - } - - def private static calculateDataHash(Map knownElements, int unknownElements) - { - val int prime = 31; - return knownElements.hashCode * prime + unknownElements.hashCode - } -} -*/ \ No newline at end of file + * @Data + * class ModelDescriptor { + * int dataHash + * int unknownElements + * Map knownElements + * + * public new(Map knownElements, int unknownElements) { + * this.dataHash = calculateDataHash(knownElements,unknownElements) + * this.unknownElements = unknownElements + * this.knownElements = knownElements + * } + * + * def private static calculateDataHash(Map knownElements, int unknownElements) + * { + * val int prime = 31; + * return knownElements.hashCode * prime + unknownElements.hashCode + * } + * } + */ diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/NeighbourhoodOptions.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/NeighbourhoodOptions.xtend new file mode 100644 index 00000000..efc89803 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/NeighbourhoodOptions.xtend @@ -0,0 +1,22 @@ +package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood + +import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration +import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration +import java.util.Set +import org.eclipse.xtend.lib.annotations.Data + +@Data +class NeighbourhoodOptions { + public static val FixPointRage = -1 + public static val GraphWidthRange = -2 + public static val FullParallels = Integer.MAX_VALUE + public static val MaxNumbers = Integer.MAX_VALUE + + public static val DEFAULT = new NeighbourhoodOptions(GraphWidthRange, FullParallels, MaxNumbers, null, null) + + val int range + val int parallels + val int maxNumber + val Set relevantTypes + val Set relevantRelations +} diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2NeighbourhoodRepresentation.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2NeighbourhoodRepresentation.xtend index 6dc40705..54b0f54a 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2NeighbourhoodRepresentation.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2NeighbourhoodRepresentation.xtend @@ -4,32 +4,34 @@ import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.BinaryElementRelationLink +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialPrimitiveInterpretation +import java.util.ArrayList import java.util.HashMap import java.util.HashSet -import java.util.LinkedList import java.util.List import java.util.Map import java.util.Set import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* -import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialPrimitiveInterpretation -import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation -abstract class PartialInterpretation2NeighbourhoodRepresentation { - private val boolean deepRepresentation - private val boolean mergeSimilarNeighbourhood +abstract class PartialInterpretation2NeighbourhoodRepresentation { + val boolean deepRepresentation + val boolean mergeSimilarNeighbourhood protected new(boolean deeprepresentation, boolean mergeSimilarNeighbourhood) { this.deepRepresentation = deeprepresentation this.mergeSimilarNeighbourhood = mergeSimilarNeighbourhood } - - public static val FixPointRage = -1 - public static val GraphWidthRange = -2 - public static val FullParallels = Integer.MAX_VALUE - public static val MaxNumbers = Integer.MAX_VALUE - + + public static val FixPointRage = NeighbourhoodOptions.FixPointRage + public static val GraphWidthRange = NeighbourhoodOptions.GraphWidthRange + public static val FullParallels = NeighbourhoodOptions.FullParallels + public static val MaxNumbers = NeighbourhoodOptions.MaxNumbers + + static val FOCUSED_ELEMENT_NAME = "<>" + /** * Creates a neighbourhood representation with traces * @param model The model to be represented. @@ -37,10 +39,15 @@ abstract class PartialInterpretation2NeighbourhoodRepresentation relevantTypes, Set relevantRelations) - { + def createRepresentation(PartialInterpretation model, int range, int parallels, int maxNumber, + Set relevantTypes, Set relevantRelations) { + createRepresentationWithFocus(model, range, parallels, maxNumber, relevantTypes, relevantRelations, null) + } + + def createRepresentationWithFocus(PartialInterpretation model, NeighbourhoodOptions options, + DefinedElement focusedElement) { + createRepresentationWithFocus(model, options.range, options.parallels, options.maxNumber, options.relevantTypes, + options.relevantRelations, focusedElement) + } + + def createRepresentationWithFocus(PartialInterpretation model, int range, int parallels, int maxNumber, + Set relevantTypes, Set relevantRelations, DefinedElement focusedElement) { val Map> types = new HashMap - fillTypes(model,types,relevantTypes) + fillTypes(model, types, relevantTypes) val Map>> IncomingRelations = new HashMap; val Map>> OutgoingRelations = new HashMap; - fillReferences(model,IncomingRelations,OutgoingRelations,relevantRelations) - - val res = doRecursiveNeighbourCalculation(model,types,IncomingRelations,OutgoingRelations,range,parallels,maxNumber); - + fillReferences(model, IncomingRelations, OutgoingRelations, relevantRelations) + + val res = doRecursiveNeighbourCalculation(model, types, IncomingRelations, OutgoingRelations, range, parallels, + maxNumber, focusedElement); + return res; } - + def private isRelevant(TypeDeclaration t, Set relevantTypes) { - if(relevantTypes === null) { + if (relevantTypes === null) { return true } else { return relevantTypes.contains(t) } } + def private isRelevant(RelationDeclaration r, Set relevantRelations) { - if(relevantRelations === null) { + if (relevantRelations === null) { return true } else { return relevantRelations.contains(r) } } + /** - * Gets the largest + * Gets the minimal neighbourhood size such that every reachable node appears in the shape of every other at least once. */ def private getWidth(Map> types, Map>> IncomingRelations, - Map>> OutgoingRelations) - { - val elements = types.keySet - val Map> reachable = new HashMap - for(element : elements) { + Map>> OutgoingRelations) { + val elements = types.keySet + var Map> reachable = new HashMap + var Map> newReachable = new HashMap + for (element : elements) { val set = new HashSet set.add(element) - reachable.put(element,set) + reachable.put(element, new HashSet) + newReachable.put(element, set) } - + var int width = 0 var boolean newAdded do { + var tmp = reachable + reachable = newReachable + newReachable = tmp newAdded = false - for(element : elements) { + for (element : elements) { val elementNeigbours = element.lookup(reachable) - val size = elementNeigbours.size - for(incoming : element.lookup(IncomingRelations)) { - elementNeigbours.addAll(incoming.from.lookup(reachable)) + val newElementNeigbours = element.lookup(newReachable) + newElementNeigbours.addAll(elementNeigbours) + for (incoming : element.lookup(IncomingRelations)) { + newElementNeigbours.addAll(incoming.from.lookup(reachable)) } - for(outgoing : element.lookup(OutgoingRelations)) { - elementNeigbours.addAll(outgoing.to.lookup(reachable)) + for (outgoing : element.lookup(OutgoingRelations)) { + newElementNeigbours.addAll(outgoing.to.lookup(reachable)) } - newAdded = newAdded || (elementNeigbours.size > size) + newAdded = newAdded || (newElementNeigbours.size > elementNeigbours.size) } - - width +=1 - } while(newAdded) + + width += 1 + } while (newAdded) return width } - + /** * Creates a neighbourhood representation with traces * @param model The model to be represented. @@ -122,68 +145,71 @@ abstract class PartialInterpretation2NeighbourhoodRepresentation doRecursiveNeighbourCalculation( - PartialInterpretation model, - Map> types, + def private NeighbourhoodWithTraces doRecursiveNeighbourCalculation( + PartialInterpretation model, Map> types, Map>> IncomingRelations, - Map>> OutgoingRelations, - int range, int parallels, int maxNumber) - { - if(range == 0){ - val r = calculateLocalNodeDescriptors(model,types,maxNumber) - val res = this.createLocalRepresentation(r.value,r.key) - if(res.modelRepresentation === null) { + Map>> OutgoingRelations, int range, int parallels, + int maxNumber, DefinedElement focusedElement) { + if (range == 0) { + val r = calculateLocalNodeDescriptors(model, types, maxNumber, focusedElement) + val res = this.createLocalRepresentation(r.value, r.key) + if (res.modelRepresentation === null) { throw new IllegalArgumentException('''Model representation is null''') - } else if(res.nodeRepresentations === null || res.nodeRepresentations.empty) { + } else if (res.nodeRepresentations === null || res.nodeRepresentations.empty) { throw new IllegalArgumentException('''No node representation''') - } else if(res.previousRepresentation !== null) { + } else if (res.previousRepresentation !== null) { throw new IllegalArgumentException('''The previous representation of the first neighbourhood have to be null''') - } else return res - } else if(range > 0) { - val previous = doRecursiveNeighbourCalculation(model,types,IncomingRelations,OutgoingRelations,range-1,parallels,maxNumber) - val r = calculateFurtherNodeDescriptors(model,previous,IncomingRelations,OutgoingRelations,parallels,maxNumber) - //println('''Level «range» finished.''') - val res = createFurtherRepresentation(r.key,r.value,previous,deepRepresentation) - if(res.modelRepresentation === null) { + } else + return res + } else if (range > 0) { + val previous = doRecursiveNeighbourCalculation(model, types, IncomingRelations, OutgoingRelations, + range - 1, parallels, maxNumber, focusedElement) + val r = calculateFurtherNodeDescriptors(model, previous, IncomingRelations, OutgoingRelations, parallels, + maxNumber) + // println('''Level «range» finished.''') + val res = createFurtherRepresentation(r.key, r.value, previous, deepRepresentation) + if (res.modelRepresentation === null) { throw new IllegalArgumentException('''Model representation is null''') - } else if(res.nodeRepresentations === null || res.nodeRepresentations.empty) { + } else if (res.nodeRepresentations === null || res.nodeRepresentations.empty) { throw new IllegalArgumentException('''No node representation''') - } else if(res.previousRepresentation === null && deepRepresentation) { + } else if (res.previousRepresentation === null && deepRepresentation) { throw new IllegalArgumentException('''Need previous representations''') - } else return res + } else + return res } else if (range == FixPointRage) { - return refineUntilFixpoint(model,types,IncomingRelations,OutgoingRelations,parallels,maxNumber) + return refineUntilFixpoint(model, types, IncomingRelations, OutgoingRelations, parallels, maxNumber, + focusedElement) } else if (range == GraphWidthRange) { - val width = this.getWidth(types,IncomingRelations,OutgoingRelations) - //println(width) - return doRecursiveNeighbourCalculation(model,types,IncomingRelations,OutgoingRelations,width,parallels,maxNumber) + val width = this.getWidth(types, IncomingRelations, OutgoingRelations) + // println(width) + return doRecursiveNeighbourCalculation(model, types, IncomingRelations, OutgoingRelations, width, parallels, + maxNumber, focusedElement) } } - - def private refineUntilFixpoint( - PartialInterpretation model, - Map> types, + + def private refineUntilFixpoint(PartialInterpretation model, Map> types, Map>> IncomingRelations, - Map>> OutgoingRelations, - int parallels, int maxNumbers) - { + Map>> OutgoingRelations, int parallels, int maxNumbers, + DefinedElement focusedElement) { var lastRange = 0 - val last = calculateLocalNodeDescriptors(model,types,maxNumbers) - var lastRepresentation = this.createLocalRepresentation(last.value,last.key) - //println('''Level 0 finished.''') + val last = calculateLocalNodeDescriptors(model, types, maxNumbers, focusedElement) + var lastRepresentation = this.createLocalRepresentation(last.value, last.key) + // println('''Level 0 finished.''') var boolean hasRefined do { - val nextRange = lastRange+1 - val next = calculateFurtherNodeDescriptors(model,lastRepresentation,IncomingRelations,OutgoingRelations,parallels,maxNumbers) - val nextRepresentation = createFurtherRepresentation(next.key,next.value,lastRepresentation,deepRepresentation) - - val previousNumberOfTypes =lastRepresentation.nodeRepresentations.values.toSet.size + val nextRange = lastRange + 1 + val next = calculateFurtherNodeDescriptors(model, lastRepresentation, IncomingRelations, OutgoingRelations, + parallels, maxNumbers) + val nextRepresentation = createFurtherRepresentation(next.key, next.value, lastRepresentation, + deepRepresentation) + + val previousNumberOfTypes = lastRepresentation.nodeRepresentations.values.toSet.size val nextNumberOfTypes = nextRepresentation.nodeRepresentations.values.toSet.size - hasRefined = nextNumberOfTypes > previousNumberOfTypes - + hasRefined = nextNumberOfTypes > previousNumberOfTypes + lastRange = nextRange lastRepresentation = nextRepresentation - + // if(hasRefined) { // println('''Level «nextRange» is calculated, number of types is refined: «previousNumberOfTypes» -> «nextNumberOfTypes»''') // } else { @@ -192,211 +218,219 @@ abstract class PartialInterpretation2NeighbourhoodRepresentation> node2Type, Set relevantTypes) { - for(element : model.elements) { + + def private fillTypes(PartialInterpretation model, Map> node2Type, + Set relevantTypes) { + for (element : model.elements) { node2Type.put(element, new HashSet) } - + // for(typeDefinition : model.problem.types.filter(TypeDefinition)) { // // Dont need // } - for(typeInterpretation : model.partialtypeinterpratation) { - if(typeInterpretation instanceof PartialPrimitiveInterpretation) { - - } else if(typeInterpretation instanceof PartialComplexTypeInterpretation) { + for (typeInterpretation : model.partialtypeinterpratation) { + if (typeInterpretation instanceof PartialPrimitiveInterpretation) { + } else if (typeInterpretation instanceof PartialComplexTypeInterpretation) { val type = typeInterpretation.interpretationOf - if(type.isRelevant(relevantTypes)) { - for(element : typeInterpretation.elements) { + if (type.isRelevant(relevantTypes)) { + for (element : typeInterpretation.elements) { element.lookup(node2Type).add(type.name) } } } } } - + /** * Indexes the references */ def private fillReferences(PartialInterpretation model, Map>> IncomingRelations, Map>> OutgoingRelations, - Set relevantRelations) - { - for(object : model.elements) { - IncomingRelations.put(object,new LinkedList) - OutgoingRelations.put(object,new LinkedList) + Set relevantRelations) { + for (object : model.elements) { + IncomingRelations.put(object, new ArrayList) + OutgoingRelations.put(object, new ArrayList) } - for(relationInterpretation : model.partialrelationinterpretation) { + for (relationInterpretation : model.partialrelationinterpretation) { val type = relationInterpretation.interpretationOf - if(type.isRelevant(relevantRelations)) { - for(link : relationInterpretation.relationlinks) { - if(link instanceof BinaryElementRelationLink) { - OutgoingRelations.get(link.param1) += new OutgoingRelation(link.param2,type.name) - IncomingRelations.get(link.param2) += new IncomingRelation(link.param1,type.name) - } else throw new UnsupportedOperationException + if (type.isRelevant(relevantRelations)) { + for (link : relationInterpretation.relationlinks) { + if (link instanceof BinaryElementRelationLink) { + OutgoingRelations.get(link.param1) += new OutgoingRelation(link.param2, type.name) + IncomingRelations.get(link.param2) += new IncomingRelation(link.param1, type.name) + } else + throw new UnsupportedOperationException } } } } - + /** * Creates a local representation of the objects (aka zero range neighbourhood) */ - def abstract protected NeighbourhoodWithTraces createLocalRepresentation( + def abstract protected NeighbourhoodWithTraces createLocalRepresentation( Map node2Representation, Map representation2Amount ) - + /** * Creates a */ - def abstract protected NeighbourhoodWithTraces createFurtherRepresentation( + def abstract protected NeighbourhoodWithTraces createFurtherRepresentation( Map, Integer> nodeDescriptors, Map> node2Representation, - NeighbourhoodWithTraces previous, + NeighbourhoodWithTraces previous, boolean deepRepresentation ) - + def private addOne(int original, int max) { if(original == Integer.MAX_VALUE) return Integer.MAX_VALUE - if(original +1 > max) return Integer.MAX_VALUE - else return original+1 + if(original + 1 > max) return Integer.MAX_VALUE else return original + 1 } - + private def calculateIncomingEdges(Map>> IncomingRelations, - DefinedElement object, Map previousNodeRepresentations, int parallel) - { + DefinedElement object, Map previousNodeRepresentations, + int parallel) { val Map, Integer> res = new HashMap for (incomingConcreteEdge : IncomingRelations.get(object)) { val IncomingRelation e = new IncomingRelation( previousNodeRepresentations.get(incomingConcreteEdge.from), incomingConcreteEdge.type) if (res.containsKey(e)) { - res.put(e, addOne(res.get(e),parallel)) + res.put(e, addOne(res.get(e), parallel)) } else { res.put(e, 1) } } return res } - - private def calcuateOutgoingEdges(Map>> OutgoingRelations, - DefinedElement object, Map previousNodeRepresentations, int parallel) - { - val Map,Integer> res= new HashMap - for(outgoingConcreteEdge : OutgoingRelations.get(object)) { - val OutgoingRelation e = - new OutgoingRelation( - previousNodeRepresentations.get(outgoingConcreteEdge.to), - outgoingConcreteEdge.type) - if(res.containsKey(e)) { - res.put(e,addOne(res.get(e),parallel)) + + private def calcuateOutgoingEdges(Map>> OutgoingRelations, + DefinedElement object, Map previousNodeRepresentations, + int parallel) { + val Map, Integer> res = new HashMap + for (outgoingConcreteEdge : OutgoingRelations.get(object)) { + val OutgoingRelation e = new OutgoingRelation( + previousNodeRepresentations.get(outgoingConcreteEdge.to), outgoingConcreteEdge.type) + if (res.containsKey(e)) { + res.put(e, addOne(res.get(e), parallel)) } else { - res.put(e,1) + res.put(e, 1) } } return res; } - + /*def private void addOrCreate_Set(Map> map, KEY key, VALUE value) { - var Set s; - if(map.containsKey(key)) { - s = map.get(key); - } else { - s = new HashSet - map.put(key,s) - } - s.add(value) - }*/ - - - private def calculateFurtherNodeDescriptors( - PartialInterpretation model, + * var Set s; + * if(map.containsKey(key)) { + * s = map.get(key); + * } else { + * s = new HashSet + * map.put(key,s) + * } + * s.add(value) + }*/ + private def calculateFurtherNodeDescriptors(PartialInterpretation model, NeighbourhoodWithTraces previous, Map>> IncomingRelations, - Map>> OutgoingRelations, - int parallels, int maxNumber) - { + Map>> OutgoingRelations, int parallels, int maxNumber) { val previousNodeRepresentations = previous.nodeRepresentations - val node2Representation = new HashMap> - val Map,Integer> descriptor2Number = - if(this.mergeSimilarNeighbourhood){ new HashMap } else { null } - val Map,FurtherNodeDescriptor> uniqueDescription = - if(this.mergeSimilarNeighbourhood){ new HashMap } else { null } - - for(object: model.elements) { - val incomingEdges = this.calculateIncomingEdges(IncomingRelations, object, previousNodeRepresentations,parallels) - val outgoingEdges = this.calcuateOutgoingEdges(OutgoingRelations,object, previousNodeRepresentations,parallels) - + val node2Representation = new HashMap> + val Map, Integer> descriptor2Number = if (this. + mergeSimilarNeighbourhood) { + new HashMap + } else { + null + } + val Map, FurtherNodeDescriptor> uniqueDescription = if (this. + mergeSimilarNeighbourhood) { + new HashMap + } else { + null + } + + for (object : model.elements) { + val incomingEdges = this.calculateIncomingEdges(IncomingRelations, object, previousNodeRepresentations, + parallels) + val outgoingEdges = this.calcuateOutgoingEdges(OutgoingRelations, object, previousNodeRepresentations, + parallels) + val previousType = previousNodeRepresentations.get(object) - - if(previousType === null) { + + if (previousType === null) { println("Error in state coder") } - - val nodeDescriptor = new FurtherNodeDescriptor( - previousType, - incomingEdges, - outgoingEdges) - - if(this.mergeSimilarNeighbourhood) { - if(descriptor2Number.containsKey(nodeDescriptor)) { + + val nodeDescriptor = new FurtherNodeDescriptor(previousType, incomingEdges, outgoingEdges) + + if (this.mergeSimilarNeighbourhood) { + if (descriptor2Number.containsKey(nodeDescriptor)) { descriptor2Number.put( nodeDescriptor, - addOne(descriptor2Number.get(nodeDescriptor),maxNumber) + addOne(descriptor2Number.get(nodeDescriptor), maxNumber) ) - node2Representation.put(object,uniqueDescription.get(nodeDescriptor)) + node2Representation.put(object, uniqueDescription.get(nodeDescriptor)) } else { - descriptor2Number.put(nodeDescriptor,if(1>maxNumber){Integer.MAX_VALUE}else{1}) - uniqueDescription.put(nodeDescriptor,nodeDescriptor) - node2Representation.put(object,nodeDescriptor) + descriptor2Number.put(nodeDescriptor, if (1 > maxNumber) { + Integer.MAX_VALUE + } else { + 1 + }) + uniqueDescription.put(nodeDescriptor, nodeDescriptor) + node2Representation.put(object, nodeDescriptor) } } else { - node2Representation.put(object,nodeDescriptor) + node2Representation.put(object, nodeDescriptor) } } - + return descriptor2Number -> node2Representation } - - private def calculateLocalNodeDescriptors( - PartialInterpretation model, - Map> types, - int maxNumber) - { + + private def calculateLocalNodeDescriptors(PartialInterpretation model, Map> types, + int maxNumber, DefinedElement focusedElement) { val Map node2Representation = new HashMap - val Map representation2Amount = - if(mergeSimilarNeighbourhood){ new HashMap } else { null } - val Map uniqueRepresentation = - if(this.mergeSimilarNeighbourhood){ new HashMap } else { null } - - for(element : model.elements) { - var newDescriptor = new LocalNodeDescriptor(element.name,element.lookup(types)) - if(this.mergeSimilarNeighbourhood){ - if(uniqueRepresentation.containsKey(newDescriptor)) { + val Map representation2Amount = if (mergeSimilarNeighbourhood) { + new HashMap + } else { + null + } + val Map uniqueRepresentation = if (this.mergeSimilarNeighbourhood) { + new HashMap + } else { + null + } + + for (element : model.elements) { + val name = if(element == focusedElement) FOCUSED_ELEMENT_NAME else element.name + var newDescriptor = new LocalNodeDescriptor(name, element.lookup(types)) + if (this.mergeSimilarNeighbourhood) { + if (uniqueRepresentation.containsKey(newDescriptor)) { newDescriptor = newDescriptor.lookup(uniqueRepresentation) - node2Representation.put(element,newDescriptor) + node2Representation.put(element, newDescriptor) representation2Amount.put( newDescriptor, - addOne(newDescriptor.lookup(representation2Amount),maxNumber) + addOne(newDescriptor.lookup(representation2Amount), maxNumber) ) } else { - uniqueRepresentation.put(newDescriptor,newDescriptor) - node2Representation.put(element,newDescriptor) - representation2Amount.put(newDescriptor, if(1>maxNumber){Integer.MAX_VALUE}else{1}) + uniqueRepresentation.put(newDescriptor, newDescriptor) + node2Representation.put(element, newDescriptor) + representation2Amount.put(newDescriptor, if (1 > maxNumber) { + Integer.MAX_VALUE + } else { + 1 + }) } } else { - node2Representation.put(element,newDescriptor) + node2Representation.put(element, newDescriptor) } } - + return representation2Amount -> node2Representation } -} \ No newline at end of file +} diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2PairwiseNeighbourhoodRepresentation.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2PairwiseNeighbourhoodRepresentation.xtend new file mode 100644 index 00000000..c10457b0 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2PairwiseNeighbourhoodRepresentation.xtend @@ -0,0 +1,68 @@ +package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood + +import com.google.common.collect.Maps +import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation +import java.util.HashMap +import java.util.Map +import org.eclipse.xtend.lib.annotations.Data +import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor + +@Data +class PairwiseNeighbourhoodRepresentation { + val Map modelRepresentation + val Map basicNodeRepresentations + val Map> pairwiseNodeRepresentations + + def getBasicRepresentation(DefinedElement a) { + basicNodeRepresentations.get(a) + } + + def getPairwiseRepresentation(DefinedElement a, DefinedElement b) { + pairwiseNodeRepresentations.get(a).get(b) + } +} + +@FinalFieldsConstructor +class PartialInterpretation2PairwiseNeighbourhoodRepresentation { + val PartialInterpretation2NeighbourhoodRepresentation, BasicNodeRepresentation> basicNeighbourhoodRepresenter + + def createRepresentation(PartialInterpretation model, NeighbourhoodOptions options) { + val basicRepresentation = basicNeighbourhoodRepresenter.createRepresentation(model, options) + val basicModelRepresentation = basicRepresentation.modelRepresentation + val basicNodeRepresentations = basicRepresentation.nodeRepresentations + val pairwiseNodeRepresentations = Maps.newHashMapWithExpectedSize(basicNodeRepresentations.size) + val modelRepresentation = new HashMap + for (nodeWithBasicRepresentation : basicNodeRepresentations.entrySet) { + val node = nodeWithBasicRepresentation.key + val basicNodeRepresentation = nodeWithBasicRepresentation.value + val count = basicModelRepresentation.get(basicNodeRepresentation) + if (count == 1) { + pairwiseNodeRepresentations.put(node, basicNodeRepresentations) + modelRepresentation.put(basicNodeRepresentation, count) + } else { + val neighbourhoodRepresentation = basicNeighbourhoodRepresenter. + createRepresentationWithFocus(model, options, node) + pairwiseNodeRepresentations.put(node, neighbourhoodRepresentation.nodeRepresentations) + modelRepresentation.compute(neighbourhoodRepresentation.modelRepresentation) [ key, value | + if (value === null) { + if (1 > options.maxNumber) { + Integer.MAX_VALUE + } else { + 1 + } + } else { + addOne(value, options.maxNumber) + } + ] + } + } + new PairwiseNeighbourhoodRepresentation(modelRepresentation, basicNodeRepresentations, + pairwiseNodeRepresentations) + } + + def private addOne(int original, int max) { + if(original == Integer.MAX_VALUE) return Integer.MAX_VALUE + if(original + 1 > max) return Integer.MAX_VALUE else return original + 1 + } +} diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/AbstractNeighborhoodBasedStateCoderFactory.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/AbstractNeighborhoodBasedStateCoderFactory.xtend new file mode 100644 index 00000000..089880b1 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/AbstractNeighborhoodBasedStateCoderFactory.xtend @@ -0,0 +1,137 @@ +package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder + +import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.NeighbourhoodOptions +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialPrimitiveInterpretation +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRelationInterpretation +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage +import java.util.LinkedList +import java.util.List +import org.eclipse.emf.common.notify.Notifier +import org.eclipse.emf.ecore.EClass +import org.eclipse.emf.ecore.EObject +import org.eclipse.emf.ecore.EStructuralFeature +import org.eclipse.viatra.dse.statecode.IStateCoder +import org.eclipse.viatra.dse.statecode.IStateCoderFactory +import org.eclipse.viatra.query.runtime.api.IPatternMatch +import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine +import org.eclipse.viatra.query.runtime.base.api.FeatureListener +import org.eclipse.viatra.query.runtime.base.api.IndexingLevel +import org.eclipse.viatra.query.runtime.base.api.InstanceListener +import org.eclipse.viatra.query.runtime.emf.EMFBaseIndexWrapper +import org.eclipse.viatra.query.runtime.emf.EMFScope +import org.eclipse.xtend.lib.annotations.Accessors + +abstract class AbstractNeighbourhoodBasedStateCoderFactory implements IStateCoderFactory { + val List statecoders = new LinkedList + + val NeighbourhoodOptions options + + protected new() { + this(NeighbourhoodOptions.DEFAULT) + } + + protected new(NeighbourhoodOptions options) { + this.options = options + } + + synchronized override createStateCoder() { + val res = doCreateStateCoder(options) + statecoders += res + return res + } + + protected def AbstractNeighbourhoodBasedPartialInterpretationStateCoder doCreateStateCoder( + NeighbourhoodOptions options) + + def getSumStatecoderRuntime() { + statecoders.map[statecoderRuntime].reduce[p1, p2|p1 + p2] + } +} + +abstract class AbstractNeighbourhoodBasedPartialInterpretationStateCoder implements IStateCoder { + val NeighbourhoodOptions options + + var PartialInterpretation target + + protected new(NeighbourhoodOptions options) { + this.options = options + } + + @Accessors(PUBLIC_GETTER) var long statecoderRuntime = 0 + + synchronized private def refreshStateCodes() { + if (refreshNeeded) { + val startTime = System.nanoTime + doRefreshStateCodes(target, options) + statecoderRuntime += (System.nanoTime - startTime) + } + } + + protected def boolean isRefreshNeeded() + + protected def void doRefreshStateCodes(PartialInterpretation target, NeighbourhoodOptions options) + + synchronized override createActivationCode(IPatternMatch match) { + refreshStateCodes + val startTime = System.nanoTime + val code = doCreateActivationCode(match) + statecoderRuntime += (System.nanoTime - startTime) + code + } + + protected def Object doCreateActivationCode(IPatternMatch match) + + synchronized override createStateCode() { + refreshStateCodes + doCreateStateCode + } + + protected def Object doCreateStateCode() + + override init(Notifier notifier) { + this.target = notifier as PartialInterpretation + val queryEngine = ViatraQueryEngine.on(new EMFScope(notifier)) + val baseIndex = queryEngine.getBaseIndex() as EMFBaseIndexWrapper + val navigationHelper = baseIndex.getNavigationHelper(); + + val classes = PartialinterpretationPackage.eINSTANCE.EClassifiers.filter(EClass).toSet + val features = classes.map[it.EAllStructuralFeatures].flatten.toSet + navigationHelper.registerObservedTypes(classes, null, features, IndexingLevel.FULL); + + navigationHelper.addFeatureListener(features, new FeatureListener() { + override void featureInserted(EObject host, EStructuralFeature feature, Object value) { invalidate } + + override void featureDeleted(EObject host, EStructuralFeature feature, Object value) { invalidate } + }) + navigationHelper.addInstanceListener(classes, new InstanceListener() { + override void instanceInserted(EClass clazz, EObject instance) { invalidate } + + override void instanceDeleted(EClass clazz, EObject instance) { invalidate } + }) + } + + synchronized def invalidate() { + doInvalidate + } + + protected def void doInvalidate() + + def protected getFallbackCode(Object o) { + switch (o) { + PartialInterpretation, + LogicProblem: + null + PartialRelationInterpretation: + o.interpretationOf.name + PartialPrimitiveInterpretation: + o.class.simpleName.hashCode + PartialComplexTypeInterpretation: + o.interpretationOf.name.hashCode + default: + throw new UnsupportedOperationException('''Unsupported type: «o.class.simpleName»''') + } + } +} diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/IdentifierBasedStateCoderFactory.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/IdentifierBasedStateCoderFactory.xtend index f55a501a..c7b8ee37 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/IdentifierBasedStateCoderFactory.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/IdentifierBasedStateCoderFactory.xtend @@ -62,13 +62,13 @@ class IdentifierBasedStateCode { int numberOfNewElement SortedSet relationStatecoders - private static val comparator = new Comparator() { + static val comparator = new Comparator() { override compare(RelationStatecoder o1, RelationStatecoder o2) { o1.relationName.compareTo(o2.relationName) } } - public new(int numberOfNewElements) { + new(int numberOfNewElements) { this.numberOfNewElement = numberOfNewElements this.relationStatecoders = new TreeSet(comparator) } diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/NeighbourhoodBasedStateCoderFactory.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/NeighbourhoodBasedStateCoderFactory.xtend index a86bcd1f..4ff39999 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/NeighbourhoodBasedStateCoderFactory.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/NeighbourhoodBasedStateCoderFactory.xtend @@ -1,223 +1,86 @@ package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder +import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.AbstractNodeDescriptor +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.NeighbourhoodOptions import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2ImmutableTypeLattice import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation -import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage import java.util.ArrayList -import java.util.LinkedList -import java.util.List import java.util.Map -import org.eclipse.emf.common.notify.Notifier -import org.eclipse.emf.ecore.EClass -import org.eclipse.emf.ecore.EObject -import org.eclipse.emf.ecore.EStructuralFeature -import org.eclipse.viatra.dse.statecode.IStateCoder -import org.eclipse.viatra.dse.statecode.IStateCoderFactory import org.eclipse.viatra.query.runtime.api.IPatternMatch -import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine -import org.eclipse.viatra.query.runtime.base.api.FeatureListener -import org.eclipse.viatra.query.runtime.base.api.IndexingLevel -import org.eclipse.viatra.query.runtime.base.api.InstanceListener -import org.eclipse.viatra.query.runtime.emf.EMFBaseIndexWrapper -import org.eclipse.viatra.query.runtime.emf.EMFScope -import org.eclipse.xtend.lib.annotations.Accessors -import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement -import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem -import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialTypeInterpratation -import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRelationInterpretation -import java.util.Set -import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration -import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration -import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2NeighbourhoodRepresentation -import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation -import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialPrimitiveInterpretation - -class NeighbourhoodBasedStateCoderFactory implements IStateCoderFactory { - val List statecoders = new LinkedList - - val int range - val int parallels - val int maxNumber - val Set relevantTypes - val Set relevantRelations - - public new() { - this.range = PartialInterpretation2NeighbourhoodRepresentation::GraphWidthRange - this.parallels = PartialInterpretation2NeighbourhoodRepresentation::FullParallels - this.maxNumber = PartialInterpretation2NeighbourhoodRepresentation::MaxNumbers - this.relevantTypes = null - this.relevantRelations = null + +class NeighbourhoodBasedStateCoderFactory extends AbstractNeighbourhoodBasedStateCoderFactory { + new() { } - - public new(int range, int parallels, int maxNumber, Set relevantTypes, Set relevantRelations) { - this.range = range - this.parallels = parallels - this.maxNumber = maxNumber - this.relevantTypes = relevantTypes - this.relevantRelations = relevantRelations + + new(NeighbourhoodOptions options) { + super(options) + } + + override protected doCreateStateCoder(NeighbourhoodOptions options) { + new NeighbourhoodBasedPartialInterpretationStateCoder(options) } - - synchronized override createStateCoder() { - val res = new NeighbourhoodBasedPartialInterpretationStateCoder(statecoders.size, - range,parallels,maxNumber,relevantTypes,relevantRelations) - statecoders += res - return res - } - def getSumStatecoderRuntime() { - statecoders.map[statecoderRuntime].reduce[p1, p2|p1+p2] - } + } -class NeighbourhoodBasedPartialInterpretationStateCoder implements IStateCoder{ - val int id; - val int range - val int parallels - val int maxNumber - val Set relevantTypes - val Set relevantRelations - - val calculator = - new PartialInterpretation2ImmutableTypeLattice - var PartialInterpretation target - - private var Map nodeRepresentations = null - private var Map modelRepresentation = null - - /*public new(int id) { - this.id = id - this.range = PartialInterpretation2NeighbourhoodRepresentation::FixPointRage - this.parallels = PartialInterpretation2NeighbourhoodRepresentation::FullParallels - this.maxNumber = maxNumber = PartialInterpretation2NeighbourhoodRepresentation::MaxNumbers - this.relevantTypes = relevantTypes - this.relevantRelations = relevantRelations - }*/ - - public new(int id, int range, int parallels, int maxNumber, Set relevantTypes, Set relevantRelations) { - this.id = id - this.range = range - this.parallels = parallels - this.maxNumber = maxNumber - this.relevantTypes = relevantTypes - this.relevantRelations = relevantRelations +class NeighbourhoodBasedPartialInterpretationStateCoder extends AbstractNeighbourhoodBasedPartialInterpretationStateCoder { + val calculator = new PartialInterpretation2ImmutableTypeLattice + + var Map nodeRepresentations = null + var Map modelRepresentation = null + + new(NeighbourhoodOptions options) { + super(options) } - - @Accessors(PUBLIC_GETTER) var long statecoderRuntime = 0 - -// val range = -1 -// val par = Integer.MAX_VALUE - //val deeprepresentation = false - - ///////// - // Caching version - ///////// - synchronized private def refreshStateCodes() { - if(this.nodeRepresentations === null || this.modelRepresentation === null) { - val startTime = System.nanoTime - //relevantObjects.forEach[println(it)] - val code = calculator.createRepresentation(target,range,parallels,maxNumber,relevantTypes,relevantRelations) - this.modelRepresentation = code.modelRepresentation - this.nodeRepresentations = code.nodeRepresentations - statecoderRuntime += (System.nanoTime - startTime) - } - } - synchronized override createActivationCode(IPatternMatch match) { - refreshStateCodes - - val startTime = System.nanoTime - val size = match.specification.parameters.size - val res = new ArrayList(size) - var int index = 0 - var int equivalenceHash = 0 - val prime = 31 - - while(index < size) { - res.add(getCode(match.get(index))) - index++ - for(var i = 0; i(res->equivalenceHash).hashCode - } - - - def private getCode(Object o) { - if(o instanceof DefinedElement) { - this.nodeRepresentations.get(o) - } else if(o instanceof PartialInterpretation || o instanceof LogicProblem) { - return null - } else if(o instanceof PartialRelationInterpretation) { - return o.interpretationOf.name - } else if(o instanceof PartialTypeInterpratation) { - if(o instanceof PartialPrimitiveInterpretation) { - o.class.simpleName.hashCode - } else if (o instanceof PartialComplexTypeInterpretation){ - return o.interpretationOf.name.hashCode - } else { - throw new UnsupportedOperationException('''Unsupported type: «o.class.simpleName»''') + + override protected isRefreshNeeded() { + nodeRepresentations === null || modelRepresentation === null + } + + override doRefreshStateCodes(PartialInterpretation target, NeighbourhoodOptions options) { + val code = calculator.createRepresentation(target, options) + modelRepresentation = code.modelRepresentation + nodeRepresentations = code.nodeRepresentations + } + + override doCreateActivationCode(IPatternMatch match) { + val size = match.specification.parameters.size + val res = new ArrayList(size) + var int index = 0 + var int equivalenceHash = 0 + val prime = 31 + + while (index < size) { + res.add(getCode(match.get(index))) + index++ + for (var i = 0; i < index; i++) { + val number = if (match.get(index) === match.get(i)) { + 1 + } else { + 0 + } + equivalenceHash = prime * equivalenceHash + number } - } else { - throw new UnsupportedOperationException('''Unsupported type: «o.class.simpleName»''') } - } - - synchronized override createStateCode() { - refreshStateCodes - return this.modelRepresentation.hashCode - } - ///////// - // Caching version - ///////// - - ///////// - // Recalculating version - ///////// -// synchronized override createActivationCode(IPatternMatch match) { -// val nodes = calculator.createRepresentation(getRelevantObjects().toList,range,par).nodeRepresentations -// val res = match.toArray.map[objectInMatch | -// nodes.get(objectInMatch) -// ] -// return res -// } -// -// override createStateCode() { -// return this.calculator.createRepresentation(getRelevantObjects().toList,range,par).modelRepresentation -// } - ///////// - // Recalculating version - ///////// - - override init(Notifier notifier) { - this.target = notifier as PartialInterpretation - val queryEngine = ViatraQueryEngine.on(new EMFScope(notifier)) - val baseIndex = queryEngine.getBaseIndex() as EMFBaseIndexWrapper - val navigationHelper = baseIndex.getNavigationHelper(); - - val classes = PartialinterpretationPackage.eINSTANCE.EClassifiers.filter(EClass).toSet - val features = classes.map[it.EAllStructuralFeatures].flatten.toSet - navigationHelper.registerObservedTypes( - classes, - null, - features, - IndexingLevel.FULL); - - - navigationHelper.addFeatureListener(features, new FeatureListener() { - override public void featureInserted(EObject host, EStructuralFeature feature, Object value) { invalidate } - override public void featureDeleted(EObject host, EStructuralFeature feature, Object value) { invalidate } - }); - navigationHelper.addInstanceListener(classes, new InstanceListener() { - override public void instanceInserted(EClass clazz, EObject instance) { invalidate } - override public void instanceDeleted(EClass clazz, EObject instance) { invalidate } - }); - } - - synchronized def public invalidate() { - this.nodeRepresentations = null - this.modelRepresentation = null + + match.specification.fullyQualifiedName -> (res -> equivalenceHash).hashCode + } + + def private getCode(Object o) { + switch (o) { + DefinedElement: + nodeRepresentations.get(o) + default: + getFallbackCode(o) + } + } + + override doCreateStateCode() { + modelRepresentation.hashCode + } + + override doInvalidate() { + nodeRepresentations = null + modelRepresentation = null } } diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/PairwiseNeighbourhoodBasedStateCoderFactory.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/PairwiseNeighbourhoodBasedStateCoderFactory.xtend new file mode 100644 index 00000000..84e798f2 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/PairwiseNeighbourhoodBasedStateCoderFactory.xtend @@ -0,0 +1,75 @@ +package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder + +import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.AbstractNodeDescriptor +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.NeighbourhoodOptions +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PairwiseNeighbourhoodRepresentation +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2ImmutableTypeLattice +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2PairwiseNeighbourhoodRepresentation +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation +import java.util.ArrayList +import org.eclipse.viatra.query.runtime.api.IPatternMatch + +class PairwiseNeighbourhoodBasedStateCoderFactory extends AbstractNeighbourhoodBasedStateCoderFactory { + new() { + } + + new(NeighbourhoodOptions options) { + super(options) + } + + override protected doCreateStateCoder(NeighbourhoodOptions options) { + new PairwiseNeighbourhoodBasedPartialInterpretationStateCoder(options) + } +} + +class PairwiseNeighbourhoodBasedPartialInterpretationStateCoder extends AbstractNeighbourhoodBasedPartialInterpretationStateCoder { + val calculator = new PartialInterpretation2PairwiseNeighbourhoodRepresentation( + new PartialInterpretation2ImmutableTypeLattice) + var PairwiseNeighbourhoodRepresentation representation + + new(NeighbourhoodOptions options) { + super(options) + } + + override protected isRefreshNeeded() { + representation === null + } + + override protected doRefreshStateCodes(PartialInterpretation target, NeighbourhoodOptions options) { + representation = calculator.createRepresentation(target, options) + } + + override protected doCreateActivationCode(IPatternMatch match) { + val size = match.specification.parameters.size + val res = new ArrayList(size * size) + for (var int i = 0; i < size; i++) { + val a = match.get(i) + for (var int j = 0; j < size; j++) { + val b = match.get(j) + res.add(getPairwiseRepresentation(a, b)) + } + } + match.specification.fullyQualifiedName -> res.hashCode + } + + private def getPairwiseRepresentation(Object a, Object b) { + if (b instanceof DefinedElement) { + if (a instanceof DefinedElement) { + representation.getPairwiseRepresentation(a, b) + } else { + representation.getBasicRepresentation(b) + } + } else { + getFallbackCode(b) + } + } + + override protected doCreateStateCode() { + representation.modelRepresentation.hashCode + } + + override protected doInvalidate() { + representation = null + } +} diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend index edcca676..701eb054 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend @@ -16,8 +16,9 @@ import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ScopePropagator import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.PartialInterpretationInitialiser import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.AbstractNeighbourhoodBasedStateCoderFactory import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.IdentifierBasedStateCoderFactory -import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.NeighbourhoodBasedStateCoderFactory +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.PairwiseNeighbourhoodBasedStateCoderFactory import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.BestFirstStrategyForModelGeneration import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.DiversityChecker import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.LoggerSolutionFoundHandler @@ -49,7 +50,7 @@ class ViatraReasoner extends LogicReasoner { ReasonerWorkspace workspace) throws LogicReasonerException { val viatraConfig = configuration.asConfig - if (viatraConfig.debugConfiguration.logging) { + if (viatraConfig.documentationLevel == DocumentationLevel.FULL) { DesignSpaceExplorer.turnOnLogging(DseLoggingLevel.VERBOSE_FULL) } else { DesignSpaceExplorer.turnOnLogging(DseLoggingLevel.WARN) @@ -139,7 +140,7 @@ class ViatraReasoner extends LogicReasoner { dse.setInitialModel(emptySolution, false) val IStateCoderFactory statecoder = if (viatraConfig.stateCoderStrategy == StateCoderStrategy.Neighbourhood) { - new NeighbourhoodBasedStateCoderFactory + new PairwiseNeighbourhoodBasedStateCoderFactory } else { new IdentifierBasedStateCoderFactory } @@ -239,7 +240,7 @@ class ViatraReasoner extends LogicReasoner { } } - private def dispatch long runtime(NeighbourhoodBasedStateCoderFactory sc) { + private def dispatch long runtime(AbstractNeighbourhoodBasedStateCoderFactory sc) { sc.sumStatecoderRuntime } diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasonerConfiguration.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasonerConfiguration.xtend index e6aee20c..99decdd9 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasonerConfiguration.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasonerConfiguration.xtend @@ -64,8 +64,7 @@ class DiversityDescriptor { } class DebugConfiguration { - public var logging = false - public var PartialInterpretationVisualiser partialInterpretatioVisualiser = null; + public var PartialInterpretationVisualiser partialInterpretatioVisualiser = null public var partalInterpretationVisualisationFrequency = 1 } diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BestFirstStrategyForModelGeneration.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BestFirstStrategyForModelGeneration.java index 077fea21..144e7484 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BestFirstStrategyForModelGeneration.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BestFirstStrategyForModelGeneration.java @@ -20,8 +20,8 @@ import java.util.List; import java.util.PriorityQueue; import java.util.Random; -import org.apache.log4j.Level; import org.apache.log4j.Logger; +import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; import org.eclipse.viatra.dse.base.ThreadContext; @@ -254,6 +254,7 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { activationIds = new ArrayList(context.getUntraversedActivationIds()); Collections.shuffle(activationIds); } catch (NullPointerException e) { + logger.warn("Unexpected state code: " + context.getDesignSpaceManager().getCurrentState()); numberOfStatecoderFail++; activationIds = Collections.emptyList(); } @@ -295,7 +296,10 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { int id = ++numberOfPrintedModel; if (id % configuration.debugConfiguration.partalInterpretationVisualisationFrequency == 0) { PartialInterpretationVisualisation visualisation = partialInterpretatioVisualiser.visualiseConcretization(p); - visualisation.writeToFile(workspace, String.format("state%09d.png", id)); + logger.debug("Visualizing state: " + id + " (" + context.getDesignSpaceManager().getCurrentState() + ")"); + String name = String.format("state%09d", id); + visualisation.writeToFile(workspace, name + ".png"); + workspace.writeModel((EObject) context.getModel(), name + ".xmi"); } } } diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/AbstractThreeValuedObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/AbstractThreeValuedObjective.xtend index 241bef2a..cd911ab5 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/AbstractThreeValuedObjective.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/AbstractThreeValuedObjective.xtend @@ -1,60 +1,10 @@ package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization -import java.util.Comparator import org.eclipse.viatra.dse.base.ThreadContext -import org.eclipse.xtend.lib.annotations.Accessors -import org.eclipse.xtend.lib.annotations.Data - -abstract class ObjectiveThreshold { - public static val NO_THRESHOLD = new hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveThreshold { - override isHard() { - false - } - - override satisfiesThreshold(double cost, Comparator comparator) { - true - } - } - - private new() { - } - - def boolean isHard() { - true - } - - def boolean satisfiesThreshold(double cost, Comparator comparator) - - @Data - static class Exclusive extends ObjectiveThreshold { - val double threshold - - override satisfiesThreshold(double cost, Comparator comparator) { - comparator.compare(threshold, cost) > 0 - } - } - - @Data - static class Inclusive extends ObjectiveThreshold { - val double threshold - - override satisfiesThreshold(double cost, Comparator comparator) { - comparator.compare(threshold, cost) >= 0 - } - } -} - -abstract class AbstractThreeValuedObjective implements IThreeValuedObjective { - @Accessors val String name - @Accessors ObjectiveKind kind - @Accessors ObjectiveThreshold threshold - @Accessors int level +abstract class AbstractThreeValuedObjective extends DirectionalThresholdObjective implements IThreeValuedObjective { protected new(String name, ObjectiveKind kind, ObjectiveThreshold threshold, int level) { - this.name = name - this.kind = kind - this.threshold = threshold - this.level = level + super(name, kind, threshold, level) } abstract def double getLowestPossibleFitness(ThreadContext threadContext) @@ -82,21 +32,4 @@ abstract class AbstractThreeValuedObjective implements IThreeValuedObjective { throw new IllegalStateException("Unknown three valued objective kind: " + kind) } } - - override isHardObjective() { - threshold.hard - } - - override satisifiesHardObjective(Double fitness) { - threshold.satisfiesThreshold(fitness, comparator) - } - - override getComparator() { - kind.comparator - } - - override setComparator(Comparator comparator) { - kind = ObjectiveKind.fromComparator(comparator) - } - } diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CompositeDirectionalThresholdObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CompositeDirectionalThresholdObjective.xtend new file mode 100644 index 00000000..0aa442f5 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CompositeDirectionalThresholdObjective.xtend @@ -0,0 +1,62 @@ +package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization + +import com.google.common.collect.ImmutableList +import java.util.Collection +import org.eclipse.viatra.dse.base.ThreadContext + +class CompositeDirectionalThresholdObjective extends DirectionalThresholdObjective { + val Collection objectives + + new(String name, Collection objectives) { + this(name, objectives, getKind(objectives), getThreshold(objectives), getLevel(objectives)) + } + + new(String name, DirectionalThresholdObjective... objectives) { + this(name, objectives as Collection) + } + + protected new(String name, Iterable objectives, ObjectiveKind kind, + ObjectiveThreshold threshold, int level) { + super(name, kind, threshold, level) + this.objectives = ImmutableList.copyOf(objectives) + } + + override createNew() { + new CompositeDirectionalThresholdObjective(name, objectives.map[createNew as DirectionalThresholdObjective], + kind, threshold, level) + } + + override init(ThreadContext context) { + for (objective : objectives) { + objective.init(context) + } + } + + override protected getRawFitness(ThreadContext context) { + var double fitness = 0 + for (objective : objectives) { + fitness += objective.getFitness(context) + } + fitness + } + + private static def getKind(Collection objectives) { + val kinds = objectives.map[kind].toSet + if (kinds.size != 1) { + throw new IllegalArgumentException("Passed objectives must have the same kind") + } + kinds.head + } + + private static def getThreshold(Collection objectives) { + objectives.map[threshold].reduce[a, b|a.merge(b)] + } + + private static def int getLevel(Collection objectives) { + val levels = objectives.map[level].toSet + if (levels.size != 1) { + throw new IllegalArgumentException("Passed objectives must have the same level") + } + levels.head + } +} diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/DirectionalThresholdObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/DirectionalThresholdObjective.xtend new file mode 100644 index 00000000..376e3d1a --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/DirectionalThresholdObjective.xtend @@ -0,0 +1,164 @@ +package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization + +import java.util.Comparator +import org.eclipse.viatra.dse.base.ThreadContext +import org.eclipse.viatra.dse.objectives.IObjective +import org.eclipse.xtend.lib.annotations.Accessors +import org.eclipse.xtend.lib.annotations.Data +import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor + +abstract class ObjectiveThreshold { + public static val NO_THRESHOLD = new ObjectiveThreshold { + override isHard() { + false + } + + override satisfiesThreshold(double cost, Comparator comparator) { + true + } + + override protected postProcessSatisfactoryCost(double cost, ObjectiveKind kind) { + cost + } + + override ObjectiveThreshold merge(ObjectiveThreshold other) { + if (other == NO_THRESHOLD) { + NO_THRESHOLD + } else { + throw new IllegalArgumentException("Merged thresholds must have the same type") + } + } + } + + private new() { + } + + def boolean isHard() { + true + } + + def boolean satisfiesThreshold(double cost, ObjectiveKind kind) { + satisfiesThreshold(cost, kind.comparator) + } + + def boolean satisfiesThreshold(double cost, Comparator comparator) + + def double postProcessCost(double cost, ObjectiveKind kind) { + if (satisfiesThreshold(cost, kind)) { + postProcessSatisfactoryCost(cost, kind) + } else { + cost + } + } + + protected def double postProcessSatisfactoryCost(double cost, ObjectiveKind kind) + + def ObjectiveThreshold merge(ObjectiveThreshold other) + + @Data + static class Exclusive extends ObjectiveThreshold { + static val EPSILON = 0.1 + + val double threshold + val boolean clampToThreshold + + @FinalFieldsConstructor + new() { + } + + new(double threshold) { + this(threshold, true) + } + + override satisfiesThreshold(double cost, Comparator comparator) { + comparator.compare(threshold, cost) < 0 + } + + override protected postProcessSatisfactoryCost(double cost, ObjectiveKind kind) { + if (clampToThreshold) { + threshold + Math.signum(kind.satisfiedValue) * EPSILON + } else { + cost + } + } + + override ObjectiveThreshold merge(ObjectiveThreshold other) { + if (other instanceof Exclusive) { + new Exclusive(threshold + other.threshold) + } else { + throw new IllegalArgumentException("Merged thresholds must have the same type") + } + } + } + + @Data + static class Inclusive extends ObjectiveThreshold { + val double threshold + val boolean clampToThreshold + + @FinalFieldsConstructor + new() { + } + + new(double threshold) { + this(threshold, true) + } + + override satisfiesThreshold(double cost, Comparator comparator) { + comparator.compare(threshold, cost) <= 0 + } + + override protected postProcessSatisfactoryCost(double cost, ObjectiveKind kind) { + if (clampToThreshold) { + threshold + } else { + cost + } + } + + override ObjectiveThreshold merge(ObjectiveThreshold other) { + if (other instanceof Inclusive) { + new Inclusive(threshold + other.threshold) + } else { + throw new IllegalArgumentException("Merged thresholds must have the same type") + } + } + } +} + +abstract class DirectionalThresholdObjective implements IObjective { + @Accessors val String name + @Accessors ObjectiveKind kind + @Accessors ObjectiveThreshold threshold + @Accessors int level + + protected new(String name, ObjectiveKind kind, ObjectiveThreshold threshold, int level) { + this.name = name + this.kind = kind + this.threshold = threshold + this.level = level + } + + override isHardObjective() { + threshold.hard + } + + override satisifiesHardObjective(Double fitness) { + threshold.satisfiesThreshold(fitness, comparator) + } + + override getComparator() { + kind.comparator + } + + override setComparator(Comparator comparator) { + kind = ObjectiveKind.fromComparator(comparator) + } + + override getFitness(ThreadContext context) { + val fitness = getRawFitness(context) + threshold.postProcessCost(fitness, kind) + } + + protected def double getRawFitness(ThreadContext context) +} diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/MatchCostObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/MatchCostObjective.xtend new file mode 100644 index 00000000..a0c6a2c1 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/MatchCostObjective.xtend @@ -0,0 +1,52 @@ +package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization + +import com.google.common.collect.ImmutableList +import java.util.Collection +import org.eclipse.viatra.dse.base.ThreadContext +import org.eclipse.viatra.query.runtime.api.IPatternMatch +import org.eclipse.viatra.query.runtime.api.IQuerySpecification +import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher +import org.eclipse.xtend.lib.annotations.Data + +@Data +class MatchCostElement { + val IQuerySpecification> querySpecification + val double weight +} + +class MatchCostObjective extends DirectionalThresholdObjective { + val Collection costElements + Collection matchers + + new(String name, Collection costElements, ObjectiveKind kind, ObjectiveThreshold threshold, + int level) { + super(name, kind, threshold, level) + this.costElements = costElements + } + + override createNew() { + new MatchCostObjective(name, costElements, kind, threshold, level) + } + + override init(ThreadContext context) { + val queryEngine = context.queryEngine + matchers = ImmutableList.copyOf(costElements.map [ + val matcher = querySpecification.getMatcher(queryEngine) + new CostElementMatcher(matcher, weight) + ]) + } + + override protected getRawFitness(ThreadContext context) { + var double cost = 0 + for (it : matchers) { + cost += weight * matcher.countMatches + } + cost + } + + @Data + private static class CostElementMatcher { + val ViatraQueryMatcher matcher + val double weight + } +} diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ObjectiveKind.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ObjectiveKind.java index f65428fe..cbbaaafd 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ObjectiveKind.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ObjectiveKind.java @@ -12,6 +12,16 @@ public enum ObjectiveKind { return Comparators.LOWER_IS_BETTER; } + @Override + public double getInvalidValue() { + return Double.POSITIVE_INFINITY; + } + + @Override + public double getSatisfiedValue() { + return Double.NEGATIVE_INFINITY; + } + }, HIGHER_IS_BETTER { @@ -20,10 +30,24 @@ public enum ObjectiveKind { return Comparators.HIGHER_IS_BETTER; } + @Override + public double getInvalidValue() { + return Double.NEGATIVE_INFINITY; + } + + @Override + public double getSatisfiedValue() { + return Double.POSITIVE_INFINITY; + } + }; public abstract Comparator getComparator(); + public abstract double getInvalidValue(); + + public abstract double getSatisfiedValue(); + public static ObjectiveKind fromComparator(Comparator comparator) { if (Comparators.LOWER_IS_BETTER.equals(comparator)) { return ObjectiveKind.LOWER_IS_BETTER; diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/QueryBasedObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/QueryBasedObjective.xtend new file mode 100644 index 00000000..d355f5be --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/QueryBasedObjective.xtend @@ -0,0 +1,48 @@ +package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization + +import org.eclipse.viatra.dse.base.ThreadContext +import org.eclipse.viatra.query.runtime.api.IPatternMatch +import org.eclipse.viatra.query.runtime.api.IQuerySpecification +import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher + +class QueryBasedObjective extends DirectionalThresholdObjective { + val IQuerySpecification> querySpecification + ViatraQueryMatcher matcher + + new(IQuerySpecification> querySpecification, + ObjectiveKind kind, ObjectiveThreshold threshold, int level) { + super(querySpecification.simpleName + " objective", kind, threshold, level) + if (querySpecification.parameters.size != 1) { + throw new IllegalArgumentException("Objective query must have a single parameter") + } + this.querySpecification = querySpecification + } + + override createNew() { + new QueryBasedObjective(querySpecification, kind, threshold, level) + } + + override init(ThreadContext context) { + matcher = querySpecification.getMatcher(context.queryEngine) + } + + override protected getRawFitness(ThreadContext context) { + val iterator = matcher.allMatches.iterator + if (!iterator.hasNext) { + return invalidValue + } + val value = iterator.next.get(0) + if (iterator.hasNext) { + throw new IllegalStateException("Multiple matches for objective query") + } + if (value instanceof Number) { + value.doubleValue + } else { + throw new IllegalStateException("Objective value is not an instance of Number") + } + } + + private def getInvalidValue() { + kind.invalidValue + } +} diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ThreeValuedCostObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ThreeValuedCostObjective.xtend index e2585c83..0a6fd55b 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ThreeValuedCostObjective.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ThreeValuedCostObjective.xtend @@ -42,7 +42,7 @@ class ThreeValuedCostObjective extends AbstractThreeValuedObjective { ]) } - override getFitness(ThreadContext context) { + override getRawFitness(ThreadContext context) { var int cost = 0 for (matcher : matchers) { cost += matcher.weight * matcher.currentMatcher.countMatches -- cgit v1.2.3-54-g00ecf