/** * Derive the split components of this palm tree. This method is taken from the paper of Gutwenger * and Mutzel "A linear time implementation of SPQR trees". * * @param v */ public List<SplitComponent> determineSplitComponents() { try { this.preparePathSearch(); this.tStackPushEos(); // System.out.println("NEW NUMBERS: " + NEWNUM); // System.out.println("ND: " + ND); // System.out.println("LOW1:" + LOWPT1); // System.out.println("LOW2:" + LOWPT2); // System.out.println("ORD ADJ: " + ADJ); // System.out.println("--------------------------"); this.pathSearch(this.m_start); SplitComponent newCmp = new SplitComponent(); if (ESTACK.size() == 1) newCmp.setType(ComponentType.TRIVIAL); else if (ESTACK.size() >= 4) newCmp.setType(ComponentType.TRICONNECTED); else newCmp.setType(ComponentType.POLYGON); while (!ESTACK.empty()) { newCmp.add(ESTACK.pop()); } // System.err.println("COMP: " + newCmp); // this.splitComponents.add(newCmp); this.splitComponents.addAll(graph.getMultipleEdgeBonds()); // System.err.println("\n\nALL COMPONENTS: "); // System.err.println(this.splitComponents); // System.err.println("\n\n"); } catch (Exception e) { e.printStackTrace(); } return this.splitComponents; }
/** * Derive the split components of this palm tree. This method is taken from the paper of Gutwenger * and Mutzel "A linear time implementation of SPQR trees". UPDATE: This is more taken from the * OGDF C++ implementation since the paper hides a lot of necessary information. * * @param v the start node */ private void pathSearch(Node v) { // System.err.println("BEGIN pS(" + v + ");" ); int vnum = NEWNUM.get(v); int wnum; int y = 0; int a, b; IterableAdjacencyList adj = ADJ.get(v); adj.reset(); Node w; int outv = adj.size(); while (adj.hasNext()) { Edge e = adj.next(); // System.err.println("CURRENT EDGE: " + e); w = e.getTarget(); wnum = NEWNUM.get(w); if (TYPE.get(e).equals(ArcType.TREE)) { if (START.get(e)) { y = 0; if (tStackGetTopA() > LOWPT1.get(w)) { do { y = Math.max(y, tStackGetTopH()); b = tStackGetTopB(); TSTACK.pop(); } while (tStackGetTopA() > LOWPT1.get(w)); Triple t = new Triple(Math.max(y, wnum + ND.get(w) - 1), LOWPT1.get(w), b); TSTACK.push(t); // System.err.println("TSTACK push 1: " + t); } else { Triple t = new Triple(wnum + ND.get(w) - 1, LOWPT1.get(w), vnum); TSTACK.push(t); // System.err.println("TSTACK push 2: " + t); } tStackPushEos(); } pathSearch(w); ESTACK.push(TREE_ARC.get(w)); // System.err.println("TSTACK: " + TSTACK); // System.err.println("CURRENT VNUM: " + vnum); // System.err.println("DEG(w): " + DEGREE.get(w)); // check for type 2 pairs while (vnum != 1 && ((tStackGetTopA() == vnum) || (DEGREE.get(w) == 2 && NEWNUM.get(firstChild(w)) > wnum))) { a = tStackGetTopA(); b = tStackGetTopB(); Edge eVirt = null; if (a == vnum && FATHER.get(NODEAT[b]) == NODEAT[a]) { TSTACK.pop(); } else { Edge e_ab = null; Node x = null; // System.err.println("W: " + w); // System.err.println("DEG(W): " + DEGREE.get(w) ); if (DEGREE.get(w) == 2 && NEWNUM.get(firstChild(w)) > wnum) { // System.err.println("FOUND type-2 pair " + v + " , " + // firstChild(w)); // System.err.println("ESTACK: " + ESTACK); Edge e1 = ESTACK.pop(); Edge e2 = ESTACK.pop(); ADJ.get(e2.getSource()).remove(e2); ADJ.get(e1.getSource()).remove(e1); x = e2.getTarget(); // System.err.println("X:" + x); decrementDegree(x); decrementDegree(v); eVirt = new Edge(0, v, x); eVirt.setVirtual(true); SplitComponent sc = new SplitComponent(); sc.add(e1); sc.add(e2); sc.add(eVirt); sc.setType(ComponentType.POLYGON); splitComponents.add(sc); // System.err.println("COMP1: " + sc); // System.err.println("ESTACK: " + ESTACK); if (!ESTACK.empty() && ESTACK.peek().getSource() == x && ESTACK.peek().getTarget() == v) { e_ab = ESTACK.pop(); ADJ.get(x).remove(e_ab); delHigh(e_ab); } } else { // System.err.println("ESTACK: " + ESTACK); // System.err.println("FOUND type-2 pair " + NODEAT[a] + " // , " + NODEAT[b]); int h = TSTACK.peek().h; TSTACK.pop(); SplitComponent sc = new SplitComponent(); while (true) { Edge xy = ESTACK.peek(); x = xy.getSource(); if (!(a <= NEWNUM.get(x) && NEWNUM.get(x) <= h && a <= NEWNUM.get(xy.getTarget()) && NEWNUM.get(xy.getTarget()) <= h)) { break; } if ((NEWNUM.get(x) == a && NEWNUM.get(xy.getTarget()) == b) || (NEWNUM.get(xy.getTarget()) == a && NEWNUM.get(x) == b)) { e_ab = ESTACK.pop(); ADJ.get(e_ab.getSource()).remove(e_ab); delHigh(e_ab); } else { Edge eh = ESTACK.pop(); if (e != eh) { ADJ.get(eh.getSource()).remove(eh); delHigh(eh); } sc.add(eh); decrementDegree(x); decrementDegree(xy.getTarget()); } } eVirt = new Edge(0, NODEAT[a], NODEAT[b]); eVirt.setVirtual(true); sc.add(eVirt); sc.finishTriconnectedOrPolygon(); splitComponents.add(sc); // System.err.println("COMP2: " + sc); x = NODEAT[b]; } if (e_ab != null) { SplitComponent sc = new SplitComponent(); sc.setType(ComponentType.BOND); sc.add(e_ab); sc.add(eVirt); eVirt = new Edge(0, v, x); eVirt.setVirtual(true); sc.add(eVirt); splitComponents.add(sc); // System.err.println("COMP: " + sc); decrementDegree(x); decrementDegree(v); } ESTACK.push(eVirt); adj.insert(eVirt); START.put(eVirt, START.get(e)); incrementDegree(x); incrementDegree(v); FATHER.put(x, v); TREE_ARC.put(x, eVirt); TYPE.put(eVirt, ArcType.TREE); w = x; wnum = NEWNUM.get(w); } } // check for type 1 pair if (LOWPT2.get(w) >= vnum && LOWPT1.get(w) < vnum && (FATHER.get(v) != m_start || outv >= 2)) { // System.err.println( "Found type-1 pair( " + v + "," + NODEAT[ // LOWPT1.get(w) ] + ")"); SplitComponent c = new SplitComponent(); Edge xy = null; int xnum, ynum; // System.err.println("ESTACK: " + ESTACK); while (!ESTACK.isEmpty()) { xy = ESTACK.peek(); xnum = NEWNUM.get(xy.getSource()); ynum = NEWNUM.get(xy.getTarget()); if (!((wnum <= xnum && xnum < wnum + ND.get(w)) || (wnum <= ynum && ynum < wnum + ND.get(w)))) { break; } ESTACK.pop(); c.add(xy); delHigh(xy); decrementDegree(xy.getSource()); ADJ.get(xy.getSource()).remove(xy); this.graphCopy.edges.remove(xy); decrementDegree(xy.getTarget()); } Edge eVirt = new Edge(0, v, NODEAT[LOWPT1.get(w)]); eVirt.setVirtual(true); this.graphCopy.addEdge(eVirt); c.add(eVirt); c.finishTriconnectedOrPolygon(); splitComponents.add(c); // System.err.println("COMP: " + c); // System.out.println("STACK HERE: " + ESTACK); if ( /*!ESTACK.isEmpty() && */ (xy.getSource() == v && xy.getTarget() == NODEAT[LOWPT1.get(w)]) || (xy.getTarget() == v && xy.getSource() == NODEAT[LOWPT1.get(w)])) { SplitComponent sc = new SplitComponent(); sc.setType(ComponentType.BOND); Edge eh = ESTACK.pop(); if (eh != e) { ADJ.get(eh.getSource()).remove(eh); } sc.add(eh); ADJ.get(eh.getSource()).remove(eh); this.graphCopy.edges.remove(eh); decrementDegree(eh.getSource()); decrementDegree(eh.getTarget()); sc.add(eVirt); eVirt = new Edge(0, v, NODEAT[LOWPT1.get(w)]); eVirt.setVirtual(true); // BLOCK IN OGDF left out --> m_IN_HIGH sc.add(eVirt); splitComponents.add(sc); // System.err.println("COMP: " + sc ); } if ((NODEAT[LOWPT1.get(w)] != FATHER.get(v))) { ESTACK.push(eVirt); adj.insert(eVirt); START.put(eVirt, false); TYPE.put(eVirt, ArcType.FROND); if (high(NODEAT[LOWPT1.get(w)]) < vnum) HIGHPT.get(NODEAT[LOWPT1.get(w)]).add(0, vnum); incrementDegree(v); incrementDegree(NODEAT[LOWPT1.get(w)]); } else { adj.remove(e); // BLOCK from OGDF --> Adj.del(it); SplitComponent sc = new SplitComponent(); sc.setType(ComponentType.BOND); sc.add(eVirt); Edge eh = TREE_ARC.get(v); sc.add(eh); splitComponents.add(sc); ADJ.get(eh.getSource()).remove(eh); eVirt = new Edge(0, NODEAT[LOWPT1.get(w)], v); eVirt.setVirtual(true); sc.add(eVirt); // System.err.println("COMP: " + sc); TYPE.put(eVirt, ArcType.TREE); // System.out.println("INSERT HERE into " + eh.getSource() + // "TARGET: " + eh.getTarget()); ADJ.get(eh.getSource()).insert(eVirt); TREE_ARC.put(v, eVirt); START.put(eVirt, START.get(eh)); } } if (START.get(e)) { while (tStackNotEos()) { TSTACK.pop(); } TSTACK.pop(); } while (tStackNotEos() && tStackGetTopA() != vnum && tStackGetTopB() != vnum && high(v) > tStackGetTopH()) { TSTACK.pop(); } outv--; } else { // frond arc // System.err.println("TSTACK 2: " + TSTACK); if (START.get(e)) { y = 0; if (tStackGetTopA() > LOWPT1.get(w)) { do { y = Math.max(y, tStackGetTopH()); b = tStackGetTopB(); TSTACK.pop(); } while (tStackGetTopA() > LOWPT1.get(w)); Triple t = new Triple(y, wnum, b); TSTACK.push(t); // System.err.println("TSTACK push3: " + t); } else { Triple t = new Triple(vnum, wnum, vnum); TSTACK.push(new Triple(vnum, wnum, vnum)); // System.err.println("TSTACK push4: " + t); } // tStackPushEos(); } // BLOCK FROM PAPER left out --> if ( w = parent(v) ) ESTACK.push(e); } } // System.err.println("END pS(" + v + ");" ); }