From b4927437a3487ecc61c48d1351d18b7a38c5b154 Mon Sep 17 00:00:00 2001 From: OszkarSemerath Date: Wed, 12 Jul 2017 15:40:33 +0200 Subject: Graphviz based visualisation for the concretizations of partial models. --- .../PartialInterpretation2Graphviz.xtend | 239 +++++++++++++++++++++ .../visualisation/pi2graphviz/Test.xtend | 24 +++ 2 files changed, 263 insertions(+) create mode 100644 Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/src/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/PartialInterpretation2Graphviz.xtend create mode 100644 Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/src/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/Test.xtend (limited to 'Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/src/hu/bme') diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/src/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/PartialInterpretation2Graphviz.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/src/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/PartialInterpretation2Graphviz.xtend new file mode 100644 index 00000000..a4baeadb --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/src/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/PartialInterpretation2Graphviz.xtend @@ -0,0 +1,239 @@ +package hu.bme.mit.inf.dslreasoner.visualisation.pi2graphviz + +import guru.nidi.graphviz.attribute.Arrow +import guru.nidi.graphviz.attribute.Color +import guru.nidi.graphviz.attribute.Shape +import guru.nidi.graphviz.attribute.Style +import guru.nidi.graphviz.engine.Format +import guru.nidi.graphviz.engine.Graphviz +import guru.nidi.graphviz.model.Graph +import guru.nidi.graphviz.model.Label +import guru.nidi.graphviz.model.Node +import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement +import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation +import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type +import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDefinition +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.BinaryElementRelationLink +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualisation +import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualiser +import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace +import java.io.File +import java.util.HashMap +import java.util.HashSet +import java.util.LinkedList +import java.util.Random +import java.util.Set + +import static guru.nidi.graphviz.model.Factory.* +import static guru.nidi.graphviz.attribute.Records.*; + +import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* +import guru.nidi.graphviz.engine.Engine +import guru.nidi.graphviz.attribute.Records +import guru.nidi.graphviz.attribute.Attributes +import java.util.List + +class GraphvizVisualisation implements PartialInterpretationVisualiser { + + val TypeColoringStyle typeColoringStyle = TypeColoringStyle::AVERAGE; + val smallFontSize=9 + val keywords = #{"class","reference","literal","enum"} + + override visualiseConcretization(PartialInterpretation partialInterpretation) { + visualisePartialInterpretation(partialInterpretation,true) + } + + override visualisePartialSolution(PartialInterpretation partialInterpretation) { + visualisePartialInterpretation(partialInterpretation,false) + } + + def private visualisePartialInterpretation(PartialInterpretation partialInterpretation, boolean concretizationOnly) { + val problem = partialInterpretation.problem + + // Elements of the partial solutions + val oldElements = problem.elements + val newElements = partialInterpretation.newElements + //val prototypeElements = #[partialInterpretation.openWorldElementPrototype] + val allElements = problem.elements + partialInterpretation.newElements + + // Indexing types + val mustTypes = new HashMap> + val mayTypes = new HashMap> + for(element : allElements) { + mustTypes.put(element,new HashSet) + mayTypes.put(element,new HashSet) + } + for(typeDefinition: problem.types.filter(TypeDefinition)) { + for(element : typeDefinition.elements) { + mustTypes.get(element)+=typeDefinition + } + } + for(partialTypeInterpretations: partialInterpretation.partialtypeinterpratation) { + for(element : partialTypeInterpretations.elements) { + mustTypes.get(element)+=partialTypeInterpretations.interpretationOf + } + } + + // Indexing references + + // Drawing the nodes + val elements2Node = new HashMap + val elements2ID = new HashMap + for(oldElemenetIndex : 0.. mustTypes, Set mayTypes) { + var tableStyle = ''' CELLSPACING="0" BORDER="2" CELLBORDER="0" CELLPADDING="1" STYLE="ROUNDED"''' + if(typeColoringStyle==TypeColoringStyle::AVERAGE) { + tableStyle += ''' BGCOLOR="#«typePredicateColor(mustTypes).toBackgroundColorString»"''' + } + val mainLabel = if(element.name !== null) { + val parts = element.name.split("\\s+") + textWithSubSup(parts.getOrNull(0),parts.getOrNull(1),parts.getOrNull(2),null) + } else { + val parts = ID.split("\\s+") + textWithSubSup(parts.get(0),parts.get(1),parts.getOrNull(2),null) + } + val label = Label.html( + ''''''+ + '''«mainLabel»'''+ + '''«FOR mustTypeName : mustTypes.map[it.name].sort»«typePredicateDescription(mustTypeName,true)»«ENDFOR»'''+ + '''«FOR mayTypeName : mayTypes.map[it.name].sort»«typePredicateDescription(mayTypeName,false)»«ENDFOR»'''+ + '''''') + + val node = node(ID).with(label).with( + Shape.NONE, + Attributes.attr("margin","0") + ) + return node + } + + protected def drawEdge(BinaryElementRelationLink link, Relation relation, Node to, boolean isContainemnt) { + val nameSegments = relation.name.split("\\s+") + var l = to(to).with(Label.html(textWithSubSup(nameSegments.getOrNull(0),nameSegments.getOrNull(1),nameSegments.getOrNull(2),null))) + if(isContainemnt) { + l = l.with(Style.BOLD) + } + return l + } + + private def getOrNull(List list, int index) { + if(list.size>index) return list.get(index) + else return null + } + + def private textWithSubSup(String text, String sub, String sup, String after) { + val actualText = text + val actualSub = if(sub===null) {" "} else {sub.checkAndHighlightKeyword} + val actualSup = if(sup==null) {" "} else {sup.checkAndHighlightKeyword} + val actualAfter = if(after === null) {""} else { + '''«after»''' + } + return + ''''''+ + '''«actualAfter»'''+ + ''''''+ + '''
«actualText»«actualSup»
«actualSub»
''' + } + def checkAndHighlightKeyword(String word) { + if(keywords.contains(word)) { + return '''«word»''' + } else { + word + } + } + def typePredicateDescription(String typeName, boolean must) + { + val value = if(must){'''1'''} else{'''½'''} + val backgroundColor = if(this.typeColoringStyle == TypeColoringStyle.FLAG) { + ''' BGCOLOR="#«typeName.typePredicateColor.toBackgroundColorString»"''' + } else { + "" + } + val typeNameSegments = typeName.split("\\s+") + return '''«textWithSubSup(typeNameSegments.getOrNull(0),typeNameSegments.getOrNull(1),typeNameSegments.getOrNull(2),null)» = «value» ''' + } + def toBackgroundColorString(List backgroundColor) { + '''«Integer.toHexString(backgroundColor.get(0))»«Integer.toHexString(backgroundColor.get(1))»«Integer.toHexString(backgroundColor.get(2))»''' + } + protected def typePredicateColor(Set types) { types.averageColor } + protected def typePredicateColor(String name) { + val Random random = new Random(name.hashCode+1) + val rangePicker = [|random.nextInt(128)+128] + return #[rangePicker.apply(), rangePicker.apply(), rangePicker.apply()] + } + private def averageColor(Set types) { + if(types.empty) { + return #[256,256,256] + } else { + val typeColors = types.filter[!it.isIsAbstract].map[typePredicateColor(it.name)] + return #[ + typeColors.map[get(0)].average, + typeColors.map[get(1)].average, + typeColors.map[get(2)].average + ] + } + } + private def average(Iterable doubles) { return doubles.reduce[p1, p2|p1+p2]/doubles.size } + + + + +} + +enum TypeColoringStyle { + FLAG, AVERAGE +} + +class GraphvisVisualisation implements PartialInterpretationVisualisation { + val private Graph graph + + public new(Graph graph) { + this.graph = graph + } + + override writeToFile(ReasonerWorkspace workspace, String name) { + val path = '''«workspace.workspaceURI.toFileString»/«name».png''' + Graphviz.fromGraph(graph)//.engine(Engine::NEATO) + .render(Format.PNG).toFile(new File(path)); + } + +} diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/src/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/Test.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/src/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/Test.xtend new file mode 100644 index 00000000..75187c26 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/src/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/Test.xtend @@ -0,0 +1,24 @@ +package hu.bme.mit.inf.dslreasoner.visualisation.pi2graphviz + +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.workspace.FileSystemWorkspace +import org.eclipse.emf.ecore.resource.Resource +import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl + +class Test { + def static void main(String[] args) { + val workspace = new FileSystemWorkspace("input/","") + + PartialinterpretationPackage.eINSTANCE.eClass + Resource.Factory.Registry.INSTANCE.extensionToFactoryMap.put("*",new XMIResourceFactoryImpl) + + val model = workspace.readModel(PartialInterpretation,"solution1.partialinterpretation") + println("loaded") + val translator = new GraphvizVisualisation + val visualisation = translator.visualiseConcretization(model) + println("visualised") + visualisation.writeToFile(workspace,"output") + println("saved") + } +} \ No newline at end of file -- cgit v1.2.3-54-g00ecf