ConflictDetection.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. package bk;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import javax.swing.JTree;
  5. import bk.LayoutType;
  6. import codeline.CodeLine;
  7. import codeline.Comment;
  8. import codeline.DeclareVariable;
  9. import codeline.ForEachLoop;
  10. import codeline.ForLoop;
  11. import codeline.FunctionCall;
  12. import codeline.FunctionDefinition;
  13. import codeline.IfLoop;
  14. import codeline.SetVariable;
  15. import codeline.WhileLoop;
  16. import graph.LayeredGraphEdge;
  17. import graph.LayeredGraphNode;
  18. import lib.TextLayoutHelper;
  19. import processor.ControlFlow;
  20. import processor.Memory;
  21. import processor.PseudoCodeNode;
  22. import processor.Memory.ReadOnlyMemory;
  23. import processor.Memory.Visibility;
  24. /**
  25. * the preprocessing stage of the bk node placement algorithm
  26. *
  27. * @author kolja and eren
  28. *
  29. */
  30. public class ConflictDetection {
  31. /**
  32. * return a debug string containing a table of variables and their values
  33. * @param m the memory which contains the variables
  34. * @return the table
  35. */
  36. public static String buildDebugString( Memory m ) {
  37. if( m.isSomewhereDefined( "l", Visibility.LOCAL ) && m.isSomewhereDefined( "i", Visibility.LOCAL ) &&
  38. m.<Integer>read( "l", Visibility.LOCAL ) < m.<LayeredGraphNode>read( "graph", Visibility.LOCAL).getContainedLayers().get( m.<Integer>read( "i", Visibility.LOCAL ) + 1 ).size() )
  39. m.<LayeredGraphNode>read( "graph", Visibility.LOCAL).getContainedLayers().get(m.<Integer>read( "i", Visibility.LOCAL ) + 1).get(m.<Integer>read( "l", Visibility.LOCAL )).setSelected(null);
  40. if( m.isSomewhereDefined( "i", Visibility.LOCAL ) && m.isSomewhereDefined( "l1", Visibility.LOCAL ) &&
  41. m.<Integer>read( "l1", Visibility.LOCAL ) < m.<LayeredGraphNode>read( "graph", Visibility.LOCAL).getContainedLayers().get(m.<Integer>read( "i", Visibility.LOCAL ) + 1).size() ) {
  42. m.<LayeredGraphNode>read( "graph", Visibility.LOCAL).getContainedLayers().get(m.<Integer>read( "i", Visibility.LOCAL ) + 1).get(m.<Integer>read( "l1", Visibility.LOCAL )).setSelected(null);
  43. }
  44. if( m.isSomewhereDefined( "i", Visibility.LOCAL ) && m.isSomewhereDefined( "k0", Visibility.LOCAL ) &&
  45. m.<Integer>read( "k0", Visibility.LOCAL ) < m.<LayeredGraphNode>read( "graph", Visibility.LOCAL).getContainedLayers().get(m.read( "i", Visibility.LOCAL )).size()) {
  46. m.<LayeredGraphNode>read( "graph", Visibility.LOCAL).getContainedLayers().get(m.read( "i", Visibility.LOCAL )).get(m.<Integer>read( "k0", Visibility.LOCAL )).setSelected(null);
  47. }
  48. if( m.isSomewhereDefined( "i", Visibility.LOCAL ) && m.isSomewhereDefined( "k1", Visibility.LOCAL ) &&
  49. m.<Integer>read( "k1", Visibility.LOCAL ) < m.<LayeredGraphNode>read( "graph", Visibility.LOCAL).getContainedLayers().get(m.read( "i", Visibility.LOCAL )).size() ) {
  50. m.<LayeredGraphNode>read( "graph", Visibility.LOCAL).getContainedLayers().get(m.read( "i", Visibility.LOCAL )).get(m.<Integer>read( "k1", Visibility.LOCAL )).setSelected(null);
  51. }
  52. if( m.isSomewhereDefined( "n", Visibility.LOCAL ) )
  53. {
  54. m.<LayeredGraphNode>read( "n", Visibility.LOCAL ).setSelected( null );
  55. }
  56. String info = "| i | l | l1 | k0 | k1 | v | n |\n";
  57. info += "|----|----|----|----|----|-----|-----|\n";
  58. String i = "null";
  59. String l = "null";
  60. String l1 = "null";
  61. String k0 = "null";
  62. String k1 = "null";
  63. String v = "null";
  64. String n = "null";
  65. if( m.isSomewhereDefined( "i", Visibility.LOCAL ) )
  66. i = "" + m.<Integer>read( "i", Visibility.LOCAL );
  67. if( m.isSomewhereDefined( "l", Visibility.LOCAL ) )
  68. l = "" + m.<Integer>read( "l", Visibility.LOCAL );
  69. if( m.isSomewhereDefined( "l1", Visibility.LOCAL ) )
  70. l1 = "" + m.<Integer>read( "l1", Visibility.LOCAL );
  71. if( m.isSomewhereDefined( "k0", Visibility.LOCAL ) )
  72. k0 = "" + m.<Integer>read( "k0", Visibility.LOCAL );
  73. if( m.isSomewhereDefined( "k1", Visibility.LOCAL ) )
  74. k1 = "" + m.<Integer>read( "k1", Visibility.LOCAL );
  75. if( m.isSomewhereDefined( "v", Visibility.LOCAL ) && m.<LayeredGraphEdge>read( "v", Visibility.LOCAL ).getSources().get( 0 ).toString() != null )
  76. v = "" + m.<LayeredGraphEdge>read( "v", Visibility.LOCAL ).getSources().get( 0 ).toString();
  77. if( m.isSomewhereDefined( "n", Visibility.LOCAL ) && m.<LayeredGraphNode>read( "n", Visibility.LOCAL ).toString() != null )
  78. n = "" + m.<LayeredGraphNode>read( "n", Visibility.LOCAL ).toString();
  79. info += "|" + TextLayoutHelper.strToLen( i, 4 ) +
  80. "|" + TextLayoutHelper.strToLen( l, 4 ) +
  81. "|" + TextLayoutHelper.strToLen( l1, 4 ) +
  82. "|" + TextLayoutHelper.strToLen( k0, 4 ) +
  83. "|" + TextLayoutHelper.strToLen( k1, 4 ) +
  84. "|" + TextLayoutHelper.strToLen( v, 5 ) +
  85. "|" + TextLayoutHelper.strToLen( n, 5 ) + "|\n";
  86. return info;
  87. }
  88. /**
  89. * creates the pseudo code for the conflict detection stage
  90. * @param tree the tree where the code will be displayed
  91. * @return the code
  92. */
  93. public static PseudoCodeNode mark_conflicts(JTree tree) {
  94. String[] vars = { "i", "L", "k0", "l", "l1", "k1", "v", "graph", "n" };
  95. String[] params = { "graph" };
  96. // Erstelle die mark Conflicts Funktion
  97. PseudoCodeNode root = new PseudoCodeNode( "function mark_conflicts( graph )", vars, tree, new FunctionDefinition( params ) );
  98. PseudoCodeNode text = new PseudoCodeNode( "-- mark conflicts in subgraphs --", vars, tree, new Comment() );
  99. root.add( text );
  100. // Für jeden Knoten im Graphen
  101. PseudoCodeNode foreach = new PseudoCodeNode( "foreach n in graph.getContainedNodes() do", vars, tree, new ForEachLoop<LayeredGraphNode>( "n" ) {
  102. @Override
  103. protected List<LayeredGraphNode> list(ReadOnlyMemory m) {
  104. return m.<LayeredGraphNode>read( "graph", Visibility.LOCAL ).getContainedNodes();
  105. }
  106. } );
  107. root.add( foreach );
  108. // Falls der Knoten einen Subgraphen hat
  109. PseudoCodeNode ifNode = new PseudoCodeNode( "if n has subgraph then", vars, tree, new IfLoop() {
  110. @Override
  111. protected boolean condition(ReadOnlyMemory m) {
  112. return m.<LayeredGraphNode>read( "n", Visibility.LOCAL ).getContainedLayers().size() > 0;
  113. }
  114. } );
  115. foreach.add( ifNode );
  116. // Rufe die Funktion rekursiv für den Subgraphen auf
  117. PseudoCodeNode call = new PseudoCodeNode( "call mark_conflicts( n );", vars, tree, new FunctionCall( root, new String[]{ "n" } ) );
  118. ifNode.add( call );
  119. text = new PseudoCodeNode( "-- mark conflicts in graph --", vars, tree, new Comment() );
  120. root.add( text );
  121. // Speichere die Layer in einer lokalen Variable
  122. PseudoCodeNode init = new PseudoCodeNode( "L = graph.getContainedLayers();", vars, tree, new DeclareVariable<ArrayList<ArrayList<LayeredGraphNode>>>( "L" ) {
  123. @Override
  124. protected ArrayList<ArrayList<LayeredGraphNode>> value(ReadOnlyMemory m) {
  125. return m.<LayeredGraphNode>read( "graph", Visibility.LOCAL ).getContainedLayers();
  126. }
  127. } );
  128. root.add( init );
  129. // Für jeden Layerindex vom 2. bis zum vorletzten (nur hier können innere Segmente auftreten)
  130. PseudoCodeNode outerLoop = new PseudoCodeNode( "for i=1 to |L|-2 do", vars, tree, new ForLoop( "i" ) {
  131. @Override
  132. protected int minimum( ReadOnlyMemory m ) {
  133. return 1;
  134. }
  135. @Override
  136. protected int maximum( ReadOnlyMemory m ) {
  137. return m.<ArrayList<ArrayList<LayeredGraphNode>>>read( "L", Visibility.LOCAL ).size() - 2;
  138. }
  139. } );
  140. root.add( outerLoop );
  141. // Initialisiere lokale Variablen
  142. PseudoCodeNode line = new PseudoCodeNode( "k0 = 0; l = 0;", vars, tree, new CodeLine() {
  143. @Override
  144. public ControlFlow runForward(Memory m) {
  145. m.declare( "k0", 0, Visibility.LOCAL ); // deklariere die Variablen im aktuellen Stack Frame
  146. m.declare( "l", 0, Visibility.LOCAL );
  147. actions.push( (Memory mem) -> { // Merkt sich die Rückgängig-mach-Aktion
  148. mem.undeclare( "k0", Visibility.LOCAL );
  149. mem.undeclare( "l", Visibility.LOCAL );
  150. } );
  151. return new ControlFlow( ControlFlow.STEP_OVER );
  152. }
  153. } );
  154. outerLoop.add( line );
  155. // Für eine genauere Beschreibung des Algoritmus zum markieren von Konflikten siehe Karstens Paper (link in Dokumentation)
  156. PseudoCodeNode innerLoop = new PseudoCodeNode( "for l1=0 to |L[i+1]|-1 do", vars, tree, new ForLoop( "l1" ) {
  157. @Override
  158. protected int minimum(ReadOnlyMemory m) {
  159. return 0;
  160. }
  161. @Override
  162. protected int maximum(ReadOnlyMemory m) {
  163. return m.<ArrayList<ArrayList<LayeredGraphNode>>>read( "L", Visibility.LOCAL ).get( m.<Integer>read( "i", Visibility.LOCAL ) + 1 ).size() - 1;
  164. }
  165. } );
  166. outerLoop.add( innerLoop );
  167. ifNode = new PseudoCodeNode( "if l1==|L[i+1]|-1 or L[i+1][l1] incident to inner segment between L[i+1] and L[i] then", vars, tree, new IfLoop() {
  168. @Override
  169. protected boolean condition(ReadOnlyMemory m) {
  170. return m.<Integer>read( "l1", Visibility.LOCAL ) == m.<LayeredGraphNode>read( "graph", Visibility.LOCAL ).getContainedLayers().get( m.<Integer>read( "i", Visibility.LOCAL ) + 1).size() - 1 ||
  171. incidentToInnerSegmentBetweenLiPlusOneAndLi( m );
  172. }
  173. } );
  174. innerLoop.add( ifNode );
  175. line = new PseudoCodeNode( "k1 = |L[i]|-1;", vars, tree, new DeclareVariable<Integer>( "k1" ) {
  176. @Override
  177. protected Integer value(ReadOnlyMemory m) {
  178. return (int)m.<ArrayList<ArrayList<LayeredGraphNode>>>read( "L", Visibility.LOCAL ).get( m.read( "i", Visibility.LOCAL ) ).size() - 1;
  179. }
  180. } );
  181. ifNode.add( line );
  182. PseudoCodeNode innerIfNode = new PseudoCodeNode( "if L[i+1][l1] incident to inner segment between L[i+1] and L[i] then", vars, tree, new IfLoop() {
  183. @Override
  184. protected boolean condition(ReadOnlyMemory m) {
  185. return incidentToInnerSegmentBetweenLiPlusOneAndLi( m ); // Prüfe ob ein inneres Segment da ist
  186. }
  187. } );
  188. ifNode.add( innerIfNode );
  189. line = new PseudoCodeNode( "k1 = pos(pred(L[i+1][l1])[0]);", vars, tree, new SetVariable<Integer>( "k1" ) {
  190. @Override
  191. protected Integer value(ReadOnlyMemory m) {
  192. return (int)m.<LayeredGraphNode>read( "graph", Visibility.LOCAL ).getContainedLayers().get( m.read( "i", Visibility.LOCAL ) ).indexOf(
  193. m.<LayeredGraphNode>read( "graph", Visibility.LOCAL ).getContainedLayers().get( m.<Integer>read( "i", Visibility.LOCAL ) + 1 ).get( m.read( "l1", Visibility.LOCAL ) ).getSortedIncomingEdges().get( 0 ).getSources().get( 0 ) );
  194. }
  195. } );
  196. innerIfNode.add( line );
  197. PseudoCodeNode whileLoop = new PseudoCodeNode( "while l <= l1 do", vars, tree, new WhileLoop() {
  198. @Override
  199. protected boolean condition( ReadOnlyMemory m ) {
  200. return m.<Integer>read( "l", Visibility.LOCAL ) <= m.<Integer>read( "l1", Visibility.LOCAL );
  201. }
  202. } );
  203. ifNode.add( whileLoop );
  204. foreach = new PseudoCodeNode( "foreach v in pred(L[i+1][l]) do", vars, tree, new ForEachLoop<LayeredGraphEdge>( "v" ) {
  205. @Override
  206. protected List<LayeredGraphEdge> list(ReadOnlyMemory m) {
  207. return m.<LayeredGraphNode>read( "graph", Visibility.LOCAL ).getContainedLayers().get( m.<Integer>read( "i", Visibility.LOCAL ) + 1 ).get( m.read( "l", Visibility.LOCAL ) ).getIncomingEdges();
  208. }
  209. } );
  210. whileLoop.add( foreach );
  211. innerIfNode = new PseudoCodeNode( "if pos(v) < k0 or pos(v) > k1 then", vars, tree, new IfLoop() {
  212. @Override
  213. protected boolean condition(ReadOnlyMemory m) {
  214. int k = m.<LayeredGraphNode>read( "graph", Visibility.LOCAL ).getContainedLayers().get( m.read( "i", Visibility.LOCAL ) ).indexOf( m.<LayeredGraphEdge>read( "v", Visibility.LOCAL ).getSources().get( 0 ) );
  215. return k < m.<Integer>read( "k0", Visibility.LOCAL ) || k > m.<Integer>read( "k1", Visibility.LOCAL );
  216. }
  217. } );
  218. foreach.add( innerIfNode );
  219. line = new PseudoCodeNode( "mark segment (v,L[i+1][l]);", vars, tree, new CodeLine() {
  220. @Override
  221. public ControlFlow runForward(Memory m) {
  222. LayeredGraphEdge e = m.read( "v", Visibility.LOCAL );
  223. boolean old = e.isConflicted( LayoutType.LEFTMOST_UPPER );
  224. e.setConflicted( true, null ); // Markiere die Kante als Konflicted
  225. actions.add( (Memory mem) -> {
  226. e.setConflicted( old, null ); // Rückwärts
  227. });
  228. return new ControlFlow( ControlFlow.STEP_OVER );
  229. }
  230. } );
  231. innerIfNode.add( line );
  232. line = new PseudoCodeNode( "l = l+1;", vars, tree, new SetVariable<Integer>( "l" ) {
  233. @Override
  234. protected Integer value(ReadOnlyMemory m) {
  235. return (int)m.<Integer>read( "l", Visibility.LOCAL ) + 1;
  236. }
  237. } );
  238. whileLoop.add( line );
  239. line = new PseudoCodeNode( "k0 = k1;", vars, tree, new SetVariable<Integer>( "k0" ) {
  240. @Override
  241. protected Integer value(ReadOnlyMemory m) {
  242. return (int)m.<Integer>read( "k1", Visibility.LOCAL );
  243. }
  244. } );
  245. ifNode.add( line );
  246. return root;
  247. }
  248. // Sucht nach Inneren Segmenten
  249. private static boolean incidentToInnerSegmentBetweenLiPlusOneAndLi( ReadOnlyMemory m ) {
  250. LayeredGraphNode curr = m.<LayeredGraphNode>read( "graph", Visibility.LOCAL ).getContainedLayers().get( m.<Integer>read( "i", Visibility.LOCAL ) + 1 ).get( m.read( "l1", Visibility.LOCAL ) );
  251. for (LayeredGraphEdge e : curr.getIncomingEdges()) {
  252. if (e.isDummyEdge()) {
  253. return true;
  254. }
  255. }
  256. return false;
  257. }
  258. }