Browse Source

Merge remote-tracking branch 'origin/master'

Eren Yilmaz 6 years ago
parent
commit
090cd13af7
2 changed files with 373 additions and 113 deletions
  1. 4 6
      src/animation/AnimatedAlgorithm.java
  2. 369 107
      src/bk/ConflictDetection.java

+ 4 - 6
src/animation/AnimatedAlgorithm.java

@@ -44,31 +44,29 @@ public abstract class AnimatedAlgorithm extends Thread implements AlgorithmStage
                 switch( ac.getNextAction() )
                 {
                 case FORWARD:
-                    forwardStep();
+                    if( forwardStep() == StageStatus.FINISHED )
+                        ac.setContinuous( false );
                     update();
                     break;
                 case FORWARD_OUT:
                     forwardStepOut();
-                    graph.unselectGraph();
                     update();
                     break;
                 case FORWARD_OVER:
                     forwardStepOver();
-                    graph.unselectGraph();
                     update();
                     break;
                 case BACKWARD:
-                    backwardStep();
+                    if( backwardStep() == StageStatus.FINISHED )
+                        ac.setContinuous( false );
                     update();
                     break;
                 case BACKWARD_OUT:
                     backwardStepOut();
-                    graph.unselectGraph();
                     update();
                     break;
                 case BACKWARD_OVER:
                     backwardStepOver();
-                    graph.unselectGraph();
                     update();
                     break;
                 default:

+ 369 - 107
src/bk/ConflictDetection.java

@@ -1,6 +1,6 @@
 package bk;
 
-import java.util.ArrayList;
+import java.util.Stack;
 
 import javax.swing.JTree;
 
@@ -10,164 +10,426 @@ import animation.PseudoCodeNode;
 import animation.PseudoCodeNode.CodeAction;
 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 PseudoCodeNode markNode;
-    
-    public ConflictDetection( LayeredGraphNode graph )
-    {
+    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 lines[];
+    private boolean breakPoint;
+    private boolean skip;
+
+    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;
+        breakPoint = false;
+        skip = false;
     }
-    
+
+
     @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() )
+        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++;
+            actions.push(() -> {
+                i--;
+                pseudo_line = old_line;
+                selectNodes(pseudo_line);
+            });
+            if (i <= graph.getContainedLayers().size() - 2) {
+                pseudo_line++;
+            } else {
+                for( PseudoCodeNode p : lines )
                 {
-                    ArrayList< LayeredGraphEdge > conf = e.calcEdgeCrossings();
-                    for( LayeredGraphEdge ce : conf )
-                    {
-                        if( !ce.isDummyEdge() )
-                            conflicts.add( ce );
-                    }
+                    if( p != null )
+                        p.setSelected( false );
                 }
+                return StageStatus.FINISHED;
             }
-        }
-        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 );
+            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;
             }
-            for( LayeredGraphEdge c : conflicts )
-                c.setConflicted( false, null );
-        });
-        if( status != StageStatus.FINISHED && breakPoint )
+            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);
+        if( breakPoint )
             return StageStatus.BREAKPOINT;
-        if( action == CodeAction.SKIP && status != StageStatus.FINISHED )
+        if( skip )
             return forwardStep();
-        return status;
+        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);
+        }
+        breakPoint = false;
+        skip = false;
+        for( PseudoCodeNode p : lines )
+        {
+            if( p != null )
+                p.setSelected( false );
+        }
+        markCode( lines[ next_line - 1 ] );
+    }
+    
+    private int getCodeDepth( PseudoCodeNode n )
+    {
+        if( n == lines[ 0 ] )
+            return 0;
+        return 1 + getCodeDepth( (PseudoCodeNode)n.getParent() );
     }
     
-    private StageStatus calcNextStatus()
+    private void markCode( PseudoCodeNode n )
     {
-        l1++;
-        if( l1 >= graph.getContainedLayers().get( i + 1 ).size() )
+        if( !n.hasSelectedSubnode() )
         {
-            i++;
-            if( i >= graph.getContainedLayers().size() - 2 )
-            {
-                i--;
-                l1--;
-                ((PseudoCodeNode)markNode.getParent()).setSelected( false );
-                markNode.setSelected( false );
-                return StageStatus.FINISHED;
-            }
-            l1 = 0;
+            CodeAction action = n.setSelected( true );
+            breakPoint |= action == CodeAction.STOP;
+            skip |= action == CodeAction.SKIP;
         }
-        return StageStatus.UNFINISHED;
+        else
+        {
+            CodeAction action = n.setSelected( true );
+            skip |= action == CodeAction.SKIP;
+        }
+        if( n == lines[ 0 ] )
+            return;
+        markCode( (PseudoCodeNode)n.getParent() );
     }
 
     @Override
     public StageStatus backwardStep() {
-        ((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) {
+            for( PseudoCodeNode p : lines )
+            {
+                if( p != null )
+                    p.setSelected( false );
+            }
             return StageStatus.FINISHED;
         }
-        actions.get( 0 ).reverse();
-        actions.remove( 0 );
+        actions.pop().reverse();
         if( breakPoint )
             return StageStatus.BREAKPOINT;
-        if( action == CodeAction.SKIP )
-            return backwardStep();
+        if( skip )
+            return forwardStep();
         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);
+        lines = new PseudoCodeNode[15];
+        lines[ 0 ] = new PseudoCodeNode( "for i=1 to |L|-2 do", tree );
+        lines[ 1 ] = new PseudoCodeNode( "k0 = 0; l = 0;", tree );
+        lines[ 0 ].add( lines[ 1 ] );
+        lines[ 2 ] = new PseudoCodeNode( "for l1=0 to |L[i+1]|-1 do", tree );
+        lines[ 0 ].add( lines[ 2 ] );
+        lines[ 3 ] = 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", tree );
+        lines[ 2 ].add( lines[ 3 ] );
+        lines[ 4 ] = new PseudoCodeNode( "k1 = |Li|-1;", tree );
+        lines[ 3 ].add( lines[ 4 ] );
+        lines[ 5 ] = new PseudoCodeNode( "if L[i+1][l1] incident to inner segment between L[i+1] and L[i] then", tree );
+        lines[ 3 ].add( lines[ 5 ] );
+        lines[ 6 ] = new PseudoCodeNode( "k1 = pos(pred(L[i+1][l1])[0]);", tree );
+        lines[ 5 ].add( lines[ 6 ] );
+        lines[ 8 ] = new PseudoCodeNode( "while l <= l1 do", tree );
+        lines[ 3 ].add( lines[ 8 ] );
+        lines[ 9 ] = new PseudoCodeNode( "foreach v in pred(L[i+1][l]) do", tree );
+        lines[ 8 ].add( lines[ 9 ] );
+        lines[ 10 ] = new PseudoCodeNode( "if k < k0 or k > k1 then mark segment (v,L[i+1][l]);", tree );
+        lines[ 9 ].add( lines[ 10 ] );
+        lines[ 12 ] = new PseudoCodeNode( "l = l+1;", tree );
+        lines[ 8 ].add( lines[ 12 ] );
+        lines[ 14 ] = new PseudoCodeNode( "k0 = k1;", tree );
+        lines[ 3 ].add( lines[ 14 ] );
+        root.add( lines[ 0 ] );
         return root;
     }
 
     @Override
     public StageStatus forwardStepOver() {
-        return forwardStep();
+        int depth = getCodeDepth( lines[ pseudo_line - 1 ] );
+        do
+        {
+            switch( forwardStep() )
+            {
+            case BREAKPOINT:
+                return StageStatus.BREAKPOINT;
+            case FINISHED:
+                return StageStatus.FINISHED;
+            case UNFINISHED:
+                break;
+            }
+        } while( depth < getCodeDepth( lines[ pseudo_line - 1 ] ) );
+        return StageStatus.UNFINISHED;
     }
 
     @Override
     public StageStatus forwardStepOut() {
-        StageStatus status = StageStatus.UNFINISHED;
-        while( status == StageStatus.UNFINISHED )
-            status = forwardStep();
-        return status;
+        int depth = getCodeDepth( lines[ pseudo_line - 1 ] );
+        do
+        {
+            switch( forwardStep() )
+            {
+            case BREAKPOINT:
+                return StageStatus.BREAKPOINT;
+            case FINISHED:
+                return StageStatus.FINISHED;
+            case UNFINISHED:
+                break;
+            }
+        } while( depth <= getCodeDepth( lines[ pseudo_line - 1 ] ) );
+        return StageStatus.UNFINISHED;
     }
 
     @Override
     public StageStatus backwardStepOver() {
-        return backwardStep();
+        int depth = getCodeDepth( lines[ pseudo_line - 1 ] );
+        do
+        {
+            switch( backwardStep() )
+            {
+            case BREAKPOINT:
+                return StageStatus.BREAKPOINT;
+            case FINISHED:
+                return StageStatus.FINISHED;
+            case UNFINISHED:
+                break;
+            }
+        } while( depth < getCodeDepth( lines[ pseudo_line - 1 ] ) );
+        return StageStatus.UNFINISHED;
     }
 
     @Override
     public StageStatus backwardStepOut() {
-        StageStatus status = StageStatus.UNFINISHED;
-        while( status == StageStatus.UNFINISHED )
-            status = backwardStep();
-        return status;
+        int depth = getCodeDepth( lines[ pseudo_line - 1 ] );
+        do
+        {
+            switch( backwardStep() )
+            {
+            case BREAKPOINT:
+                return StageStatus.BREAKPOINT;
+            case FINISHED:
+                return StageStatus.FINISHED;
+            case UNFINISHED:
+                break;
+            }
+        } while( depth <= getCodeDepth( lines[ pseudo_line - 1 ] ) );
+        return StageStatus.UNFINISHED;
     }
 
     @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;
     }
 }