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. --- .../.classpath | 18 + .../.gitignore | 2 + .../.project | 40 +++ .../.settings/org.eclipse.jdt.core.prefs | 2 + .../.settings/org.eclipse.m2e.core.prefs | 4 + .../META-INF/MANIFEST.MF | 17 + .../build.properties | 4 + .../input/solution1.partialinterpretation | 394 +++++++++++++++++++++ .../pom.xml | 19 + .../PartialInterpretation2Graphviz.xtend | 239 +++++++++++++ .../visualisation/pi2graphviz/Test.xtend | 24 ++ .../visualisation/pi2graphviz/.gitignore | 10 + 12 files changed, 773 insertions(+) create mode 100644 Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/.classpath create mode 100644 Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/.gitignore create mode 100644 Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/.project create mode 100644 Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/.settings/org.eclipse.jdt.core.prefs create mode 100644 Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/.settings/org.eclipse.m2e.core.prefs create mode 100644 Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/META-INF/MANIFEST.MF create mode 100644 Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/build.properties create mode 100644 Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/input/solution1.partialinterpretation create mode 100644 Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/pom.xml 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 create mode 100644 Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/xtend-gen/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/.gitignore diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/.classpath b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/.classpath new file mode 100644 index 00000000..a49f7d1e --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/.classpath @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/.gitignore b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/.gitignore new file mode 100644 index 00000000..09e3bc9b --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/target/ diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/.project b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/.project new file mode 100644 index 00000000..a52c4496 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/.project @@ -0,0 +1,40 @@ + + + hu.bme.mit.inf.dslreasoner.visualisation + + + + + + org.eclipse.xtext.ui.shared.xtextBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + org.eclipse.xtext.ui.shared.xtextNature + + diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/.settings/org.eclipse.jdt.core.prefs b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..fd9afef6 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/.settings/org.eclipse.m2e.core.prefs b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 00000000..14b697b7 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/META-INF/MANIFEST.MF b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/META-INF/MANIFEST.MF new file mode 100644 index 00000000..e7289f24 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/META-INF/MANIFEST.MF @@ -0,0 +1,17 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Visualisation +Bundle-SymbolicName: hu.bme.mit.inf.dslreasoner.visualisation +Bundle-Version: 1.0.0.qualifier +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: com.google.guava, + org.eclipse.xtext.xbase.lib, + org.eclipse.xtend.lib, + org.eclipse.xtend.lib.macro, + hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage;bundle-version="1.0.0", + hu.bme.mit.inf.dslreasoner.viatra2logic;bundle-version="1.0.0", + hu.bme.mit.inf.dslreasoner.logic.model.validation;bundle-version="0.0.1", + org.eclipse.emf.ecore.xmi;bundle-version="2.12.0" +Import-Package: org.apache.log4j;version="1.2.15" +Export-Package: hu.bme.mit.inf.dslreasoner.visualisation.pi2graphviz + diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/build.properties b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/build.properties new file mode 100644 index 00000000..41eb6ade --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/input/solution1.partialinterpretation b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/input/solution1.partialinterpretation new file mode 100644 index 00000000..b6519111 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/input/solution1.partialinterpretation @@ -0,0 +1,394 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/pom.xml b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/pom.xml new file mode 100644 index 00000000..ac745ad3 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/pom.xml @@ -0,0 +1,19 @@ + + 4.0.0 + hu.bme.mit.inf.dslreasoner.visualisation + hu.bme.mit.inf.dslreasoner.visualisation + 0.0.1-SNAPSHOT + + + guru.nidi + graphviz-java + 0.2.1 + + + org.slf4j + slf4j-nop + 1.7.25 + + + \ No newline at end of file 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 diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/xtend-gen/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/.gitignore b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/xtend-gen/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/.gitignore new file mode 100644 index 00000000..66ab25b3 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/xtend-gen/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/.gitignore @@ -0,0 +1,10 @@ +/.GraphvisVisualisation.java._trace +/.GraphvizVisualisation.java._trace +/.PartialInterpretation2Graphviz.xtendbin +/.Test.java._trace +/.Test.xtendbin +/.TypeColoringStyle.java._trace +/GraphvisVisualisation.java +/GraphvizVisualisation.java +/Test.java +/TypeColoringStyle.java -- cgit v1.2.3-54-g00ecf