Browse Source

Merge branch 'BKConflictDetection' of https://koljastrohm-games.com:3000/GraphDrawer/NodeShuffler into BKConflictDetection

Kolja Strohm 6 years ago
parent
commit
00f1c5e5e6
2 changed files with 299 additions and 105 deletions
  1. 255 101
      src/bk/ConflictDetection.java
  2. 44 4
      src/graph/LayeredGraphNode.java

+ 255 - 101
src/bk/ConflictDetection.java

@@ -1,6 +1,7 @@
 package bk;
 
 import java.util.ArrayList;
+import java.util.Stack;
 
 import javax.swing.JTree;
 
@@ -8,134 +9,258 @@ import animation.AlgorithmStage;
 import animation.BackwardAction;
 import animation.PseudoCodeNode;
 import animation.PseudoCodeNode.CodeAction;
+import bk.ExtremalLayoutCalc.LayoutType;
 import graph.LayeredGraphEdge;
 import graph.LayeredGraphNode;
+import lib.TextLayoutHelper;
 
+/**
+ * the preprocessing stage of the bk node placement algorithm
+ * 
+ * @author kolja and eren
+ *
+ */
 public class ConflictDetection implements AlgorithmStage {
 
     private LayeredGraphNode graph;
-    private ArrayList< BackwardAction > actions;
-    
+    private Stack<BackwardAction> actions;
+
     private int i;
     private int l1;
+    private int k0;
+    private int k1;
+    private int l;
+    private int k;
+    private int hidden_k;
+    /**
+     * line number in Carstens' pseudocode listing 3.1
+     */
+    private int pseudo_line;
     private PseudoCodeNode markNode;
-    
-    public ConflictDetection( LayeredGraphNode graph )
-    {
+
+    public ConflictDetection(LayeredGraphNode graph) {
         this.graph = graph;
-        actions = new ArrayList<>();
-        i = 1;
-        l1 = 0;
+        actions = new Stack<>();
+        i = 0; // will be increased before first iteration
+        l1 = -1; // will be increased before first iteration
+        k0 = 0;
+        k1 = 0;
+        l = 0;
+        k = 0;
+        hidden_k = 0;
+        pseudo_line = 1;
     }
-    
+
+
     @Override
     public StageStatus forwardStep() {
-        int oldI = i;
-        int oldL1 = l1;
-        ((PseudoCodeNode)markNode.getParent()).setSelected( true );
-        CodeAction action = markNode.setSelected( true );
-        boolean breakPoint = action == CodeAction.STOP;
-        if( i + 1 >= graph.getContainedLayers().size() - 1 )
-        {
-            ((PseudoCodeNode)markNode.getParent()).setSelected( false );
-            markNode.setSelected( false );
-            return StageStatus.FINISHED;
-        }
-        LayeredGraphNode curr = graph.getContainedLayers().get( i + 1 ).get( l1 );
-        curr.setSelected( null );
-        ArrayList< LayeredGraphEdge > edges = curr.getIncomingEdges();
-        LayeredGraphEdge dummyEdge = null;
-        for( LayeredGraphEdge e : edges )
-        {
-            if( e.isDummyEdge() )
-            {
-                dummyEdge = e;
-                break;
-            }
-        }
-        ArrayList< LayeredGraphEdge > conflicts = new ArrayList<>();
-        if( dummyEdge != null )
-        {
-            for( LayeredGraphEdge e : edges )
-            {
-                if( e.isDummyEdge() )
-                {
-                    ArrayList< LayeredGraphEdge > conf = e.calcEdgeCrossings();
-                    for( LayeredGraphEdge ce : conf )
-                    {
-                        if( !ce.isDummyEdge() )
-                            conflicts.add( ce );
-                    }
-                }
-            }
-        }
-        for( LayeredGraphEdge c : conflicts )
-            c.setConflicted( true, null );
-        StageStatus status =  calcNextStatus();
-        actions.add( 0, ()->{
-            i = oldI;
-            l1 = oldL1;
-            if( i + 1 < graph.getContainedLayers().size() - 1 && l1 > 0 )
-            {
-                LayeredGraphNode layde = graph.getContainedLayers().get( i + 1 ).get( l1 - 1 );
-                layde.setSelected( null );
-            }
-            for( LayeredGraphEdge c : conflicts )
-                c.setConflicted( false, null );
-        });
-        if( status != StageStatus.FINISHED && breakPoint )
-            return StageStatus.BREAKPOINT;
-        if( action == CodeAction.SKIP && status != StageStatus.FINISHED )
-            return forwardStep();
-        return status;
-    }
-    
-    private StageStatus calcNextStatus()
-    {
-        l1++;
-        if( l1 >= graph.getContainedLayers().get( i + 1 ).size() )
-        {
+        int old_line = pseudo_line;
+        int old_k = k;
+        int old_k0 = k0;
+        int old_k1 = k1;
+        int old_l = l;
+        int old_l1 = l1;
+        int old_hidden_k = hidden_k;
+
+        switch (pseudo_line) {
+        case 1:
             i++;
-            if( i >= graph.getContainedLayers().size() - 2 )
-            {
+            actions.push(() -> {
                 i--;
-                l1--;
-                ((PseudoCodeNode)markNode.getParent()).setSelected( false );
-                markNode.setSelected( false );
+                pseudo_line = old_line;
+                selectNodes(pseudo_line);
+            });
+            if (i <= graph.getContainedLayers().size() - 2) {
+                pseudo_line++;
+            } else {
                 return StageStatus.FINISHED;
             }
-            l1 = 0;
+            break;
+        case 2:
+            k0 = 0;
+            l = 0;
+            l1 = -1; // will be increased before first iteration
+            pseudo_line++;
+            actions.push(() -> {
+                pseudo_line = old_line;
+                k0 = old_k0;
+                l = old_l;
+                l1 = old_l1;
+                selectNodes(pseudo_line);
+            });
+            break;
+        case 3:
+            l1++;
+            actions.push(() -> {
+                l1--;
+                pseudo_line = old_line;
+                selectNodes(pseudo_line);
+            });
+            if (l1 < graph.getContainedLayers().get(i + 1).size()) {
+                pseudo_line += 1;
+            } else {
+                pseudo_line = 1;
+            }
+            break;
+        case 4:
+            actions.push(() -> {
+                pseudo_line = old_line;
+                selectNodes(pseudo_line);
+            });
+            if (graph.getContainedLayers().get(i + 1).size() == l1 || incidentToInnerSegmentBetweenLiPlusOneAndLi()) {
+                pseudo_line++;
+            } else {
+                pseudo_line = 3;
+            }
+            break;
+        case 5:
+            actions.push(() -> {
+                k1 = old_k1;
+                pseudo_line = old_line;
+                selectNodes(pseudo_line);
+            });
+            k1 = graph.getContainedLayers().get(i).size() - 1;
+            pseudo_line++;
+            break;
+        case 6:
+            actions.push(() -> {
+                pseudo_line = old_line;
+                selectNodes(pseudo_line);
+            });
+            if (incidentToInnerSegmentBetweenLiPlusOneAndLi()) {
+                pseudo_line++;
+            } else {
+                pseudo_line = 9;
+            }
+            break;
+        case 7:
+            actions.push(() -> {
+                k1 = old_k1;
+                pseudo_line = old_line;
+                selectNodes(pseudo_line);
+            });
+            k1 = graph.getContainedLayers().get(i).indexOf(
+                    graph.getContainedLayers().get(i + 1).get(l1).getSortedIncomingEdges().get(0).getSources().get(0));
+            pseudo_line = 9;
+            break;
+        case 9:
+            actions.push(() -> {
+                hidden_k = old_hidden_k;
+                pseudo_line = old_line;
+                selectNodes(pseudo_line);
+            });
+            if (l <= l1) {
+                pseudo_line++;
+                hidden_k = 0; // will not be increased before first iteration
+                k = graph.getContainedLayers().get(i).indexOf(graph.getContainedLayers().get(i + 1).get(l)
+                        .getSortedIncomingEdges().get(hidden_k).getSources().get(0));
+            } else {
+                pseudo_line = 15;
+            }
+            break;
+        case 10:
+            actions.push(() -> {
+                k = old_k;
+                pseudo_line = old_line;
+                selectNodes(pseudo_line);
+            });
+            if (hidden_k < graph.getContainedLayers().get(i + 1).get(l).getSortedIncomingEdges().size()) {
+                k = graph.getContainedLayers().get(i).indexOf(graph.getContainedLayers().get(i + 1).get(l)
+                        .getSortedIncomingEdges().get(hidden_k).getSources().get(0));
+                pseudo_line++;
+            } else {
+                pseudo_line = 13;
+            }
+            break;
+        case 11:
+            actions.push(() -> {
+                hidden_k--;
+                graph.getContainedLayers().get(i + 1).get(l).getSortedIncomingEdges().get(hidden_k).setConflicted(false,
+                        null);
+                pseudo_line = old_line;
+                selectNodes(pseudo_line);
+            });
+            if (k < k0 || k > k1) {
+                graph.getContainedLayers().get(i + 1).get(l).getSortedIncomingEdges().get(hidden_k).setConflicted(true,
+                        null);
+            }
+            hidden_k++;
+            pseudo_line = 10;
+            break;
+        case 13:
+            actions.push(() -> {
+                l--;
+                pseudo_line = old_line;
+                selectNodes(pseudo_line);
+            });
+            l++;
+            pseudo_line = 9;
+            break;
+        case 15:
+            actions.push(() -> {
+                k0 = old_k0;
+                pseudo_line = old_line;
+                selectNodes(pseudo_line);
+            });
+            k0 = k1;
+            pseudo_line = 3;
+            break;
         }
+
+        selectNodes(pseudo_line);
+
         return StageStatus.UNFINISHED;
     }
 
+    private void selectNodes(int next_line) {
+        if (next_line >= 3 && l < graph.getContainedLayers().get(i + 1).size()) {
+            graph.getContainedLayers().get(i + 1).get(l).setSelected(null);
+        }
+
+        if (next_line >= 4) {
+            graph.getContainedLayers().get(i + 1).get(l1).setSelected(null);
+        }
+
+        if (next_line >= 3) {
+            graph.getContainedLayers().get(i).get(k0).setSelected(null);
+        }
+
+        if (next_line >= 6) {
+            graph.getContainedLayers().get(i).get(k1).setSelected(null);
+        }
+
+        if (next_line == 10 || next_line == 11) {
+            graph.getContainedLayers().get(i).get(k).setSelected(null);
+        }
+    }
+
     @Override
     public StageStatus backwardStep() {
-        ((PseudoCodeNode)markNode.getParent()).setSelected( true );
-        CodeAction action = markNode.setSelected( true );
+        ((PseudoCodeNode) markNode.getParent()).setSelected(true);
+        CodeAction action = markNode.setSelected(true);
         boolean breakPoint = action == CodeAction.STOP;
-        if( actions.size() == 0 )
-        {
-            ((PseudoCodeNode)markNode.getParent()).setSelected( false );
-            markNode.setSelected( false );
+        if (actions.size() == 0) {
+            ((PseudoCodeNode) markNode.getParent()).setSelected(false);
+            markNode.setSelected(false);
             return StageStatus.FINISHED;
         }
-        actions.get( 0 ).reverse();
-        actions.remove( 0 );
-        if( breakPoint )
+        actions.pop().reverse();
+        if (breakPoint)
             return StageStatus.BREAKPOINT;
-        if( action == CodeAction.SKIP )
+        if (action == CodeAction.SKIP)
             return backwardStep();
         return StageStatus.UNFINISHED;
     }
 
     @Override
-    public PseudoCodeNode createPseudocodeTree( JTree tree ) {
-        PseudoCodeNode root = new PseudoCodeNode( "Preprocessing (mark type 1 conflicts)", tree );
-        PseudoCodeNode loopNode = new PseudoCodeNode( "Loop through all nodes...", tree );
-        markNode = new PseudoCodeNode( "If non-inner segment crosses an inner segment whose target is this node, mark the non-inner segment as conflicted", tree );
-        loopNode.add( markNode );
-        root.add( loopNode );
+    public PseudoCodeNode createPseudocodeTree(JTree tree) {
+        PseudoCodeNode root = new PseudoCodeNode("Preprocessing (mark type 1 conflicts)", tree);
+        PseudoCodeNode loopNode = new PseudoCodeNode("Loop through all nodes...", tree);
+        markNode = new PseudoCodeNode(
+                "If non-inner segment crosses an inner segment whose target is this node, mark the non-inner segment as conflicted",
+                tree);
+        loopNode.add(markNode);
+        root.add(loopNode);
         return root;
     }
 
@@ -147,7 +272,7 @@ public class ConflictDetection implements AlgorithmStage {
     @Override
     public StageStatus forwardStepOut() {
         StageStatus status = StageStatus.UNFINISHED;
-        while( status == StageStatus.UNFINISHED )
+        while (status == StageStatus.UNFINISHED)
             status = forwardStep();
         return status;
     }
@@ -160,14 +285,43 @@ public class ConflictDetection implements AlgorithmStage {
     @Override
     public StageStatus backwardStepOut() {
         StageStatus status = StageStatus.UNFINISHED;
-        while( status == StageStatus.UNFINISHED )
+        while (status == StageStatus.UNFINISHED)
             status = backwardStep();
         return status;
     }
 
     @Override
-    public String getDebugString()
-    {
-        return "";
+    public String getDebugString() {
+        String info = "| i  | l  | l1 | k0 | k1 | k  |\n";
+        info +=       "|----|----|----|----|----|----|\n";
+        info += "|" + TextLayoutHelper.strToLen( "" + i, 4 ) + 
+                "|" + TextLayoutHelper.strToLen( "" + l, 4 ) + 
+                "|" + TextLayoutHelper.strToLen( "" + l1, 4 ) + 
+                "|" + TextLayoutHelper.strToLen( "" + k0, 4 ) + 
+                "|" + TextLayoutHelper.strToLen( "" + k1, 4 ) + 
+                "|" + TextLayoutHelper.strToLen( "" + k, 4 ) + "|\n";
+//        if( insideSubgraph && vIndex < graph.getContainedNodes().size() )
+//        {
+//            info += "Subgraph of " + graph.getContainedNodes().get( vIndex ).getName() + ":\n";
+//            String tmp = subgraphAlgs.get( vIndex ).getDebugString();
+//            info += tmp;
+//            return info;
+//        }
+        return info;
+    }
+
+    /**
+     * part of line 4 and 6 in the pseudocode
+     * 
+     * @return
+     */
+    private boolean incidentToInnerSegmentBetweenLiPlusOneAndLi() {
+        LayeredGraphNode curr = graph.getContainedLayers().get(i + 1).get(l1);
+        for (LayeredGraphEdge e : curr.getIncomingEdges()) {
+            if (e.isDummyEdge()) {
+                return true;
+            }
+        }
+        return false;
     }
 }

+ 44 - 4
src/graph/LayeredGraphNode.java

@@ -25,7 +25,8 @@ public interface LayeredGraphNode {
   public ElkNode getOriginalNode();
 
   /**
-   * set the shift of this node in the given layout to the given value
+   * set the shift of this node to the given value in the given layout
+   * or in all layouts if the argument is null.
    * 
    * @param shift
    *          the value to set to
@@ -45,6 +46,7 @@ public interface LayeredGraphNode {
 
   /**
    * set the sink of this node in the given layout
+   * or in all layouts if the argument is null.
    * 
    * @param sink
    *          the sink
@@ -63,7 +65,7 @@ public interface LayeredGraphNode {
   public LayeredGraphNode getSink(LayoutType layout);
 
   /**
-   * checks if the x coordinate of the node is defined
+   * checks if the x coordinate of the node is defined in the given layout
    * 
    * @param layout
    *          the layout
@@ -73,6 +75,7 @@ public interface LayeredGraphNode {
 
   /**
    * sets the align-attribute (the next node in the block) in the given layout
+   * or in all layouts if the argument is null.
    * 
    * @param align
    *          the next node in the block
@@ -92,7 +95,8 @@ public interface LayeredGraphNode {
 
   /**
    * sets the root node of this node in the given layout which identifies the
-   * block that it belongs to
+   * block that it belongs to 
+   * or in all layouts if the argument is null.
    * 
    * @param root
    *          the new root node
@@ -128,6 +132,7 @@ public interface LayeredGraphNode {
 
   /**
    * set the display color of this node in the given layout
+   * or in all layouts if the argument is null.
    * 
    * @param c
    *          the color
@@ -136,16 +141,51 @@ public interface LayeredGraphNode {
    */
   public void setColor(Color c, LayoutType layout);
 
+  /**
+   * check the display color of this node in the given layout.
+   * @param layout the layout
+   * @return the color
+   */
   public Color getColor(LayoutType layout);
+  
+  /**
+   * check the color of this nodes class in the given layout
+   * or in all layouts if the argument is null.
+   * @param layout the layout
+   * @return the color
+   */
   public Color getClassColor( LayoutType layout );
-  public void setSelected(LayoutType layoutType);
+  
+  /**
+   * mark the node as "selected" in the given layout
+   * or in all layouts if the argument is null.
+   * @param layout
+   */
+  public void setSelected(LayoutType layout);
 
+  /**
+   * checks if the node is selected in the given layout
+   * @param layout
+   * @return
+   */
   public boolean isSelected(LayoutType layout);
 
+  /**
+   * sets whether this node is a dummy node
+   * @param dummy is it?
+   */
   public void setDummyNode(boolean dummy);
 
+
+  /**
+   * checks whether this node is a dummy node
+   * @param dummy is it?
+   */
   public boolean isDummyNode();
 
+  /**
+   * unselects the subgraph of this node
+   */
   public void unselectGraph();
 
   /**