Пример #1
0
 private static WorkVertex getBfsPred(WorkVertex v) {
   return (WorkVertex) v.getData();
 }
Пример #2
0
  /**
   * @param maxSize Must be != 0.
   * @return True if must stop, false otherwise.
   */
  private static boolean computeShortestCycles_onScc(
      ArrayList<InterfaceVertex> scc, int maxSize, InterfaceVertexCollProcessor processor) {

    if (maxSize == 0) {
      throw new AssertionError();
    }

    /*
     * Dealing with SCCs of size 1 (and with cycles of size 1 along with that),
     * early, before creating a work graph, because it's the common case for
     * graphs with no or few cycles.
     */

    for (InterfaceVertex v : scc) {
      // Might have vertices outside the SCC as successors,
      // so need to use contains(...).
      if (v.successors().contains(v)) {
        // Has itself as successor.
        if (processOneBackingVertexCycle(v, processor)) {
          return true;
        }
      }
    }

    if ((scc.size() == 1) || (maxSize == 1)) {
      // No need to go further here.
      return false;
    }

    /*
     * Using a work graph, not so much to have predecessors (which could
     * easily be computed by iterating on successors of each vertex), than
     * not to have edges dangling outside the SCC, and to be able to remove
     * cycles of size 1, to make things simpler.
     */

    final ArrayList<WorkVertex> workScc = WorkGraphUtilz.newWorkGraphAsArrayList(scc);

    // Removing elementary circuits (already processed if any).
    for (WorkVertex v : workScc) {
      WorkGraphUtilz.removeEdge(v, v);
    }

    /*
     *
     */

    final ArrayList<WorkVertex> bfsPredCleanupList = new ArrayList<WorkVertex>();

    // Sets initially never empty, since we are in an SCC of size > 1,
    // and mapping is removed when set gets empty, to help memory.
    final Map<WorkVertex, Set<WorkVertex>> predToVisitSetByVertex =
        new HashMap<WorkVertex, Set<WorkVertex>>();
    for (WorkVertex v : workScc) {
      predToVisitSetByVertex.put(v, new HashSet<WorkVertex>(v.predecessors()));
    }

    if (MUST_SORT_VERTICES) {
      SortUtils.sort(workScc, WORK_VERTEX_COMPARATOR);
    }

    /*
     * name_in_paper/name_in_code:
     *
     * parent: predecessor (parent/child more suited to tree-like graphs)
     * x: x (vertex)
     * A: predToVisitSet (set of vertices)
     * Q: queue (FIFO of vertices)
     * p: v (vertex)
     * y: succ (Vertex)
     * c: cycle
     * B: v.successors() (set of vertices)
     */

    for (WorkVertex x : workScc) {

      final Set<WorkVertex> predToVisitSet = predToVisitSetByVertex.get(x);
      if (predToVisitSet == null) {
        // Corresponding cycles already taken care of.
        continue;
      }

      resetAndClear(bfsPredCleanupList);

      setBfsPredWithCleanup(x, TOMBSTONE, bfsPredCleanupList);

      final LinkedList<WorkVertex> queue = new LinkedList<WorkVertex>();

      push(queue, x);

      while (predToVisitSet.size() != 0) {
        // Queue must not be empty, as long as we work on a SCC.
        final WorkVertex v = pop(queue);

        for (WorkVertex succ : v.successors()) {

          /*
           * Modif/paper: simpler conditional code.
           */

          if (getBfsPred(succ) == null) {
            // Not yet "visited" nor enqueued.

            setBfsPredWithCleanup(succ, v, bfsPredCleanupList);

            push(queue, succ);
          }

          if (removeAndCleanupIfEmpty(
              predToVisitSet,
              succ,
              //
              predToVisitSetByVertex,
              x)) {

            /*
             * Found a new cycle.
             */

            final ArrayList<WorkVertex> cycle = newReversedCycle(workScc.size(), succ);

            final boolean smallEnoughForProcess = (maxSize < 0) || (cycle.size() <= maxSize);
            if (smallEnoughForProcess) {

              dereverse(cycle);

              if (processCycle(cycle, processor)) {
                return true;
              }

              /*
               * Modif/paper: removal of already covered edges.
               */

              removeCycleEdges(predToVisitSetByVertex, cycle);
            }
          }
        }
      }
    }

    return false;
  }
Пример #3
0
 private static void setBfsPred(WorkVertex v, WorkVertex bfsPred) {
   v.setData(bfsPred);
 }
Пример #4
0
 // @Override
 public int compare(WorkVertex v1, WorkVertex v2) {
   final int n1 = v1.successors().size();
   final int n2 = v2.successors().size();
   // No overflow since both >= 0.
   return n1 - n2;
 }