/**
  * Scale weights in the graph
  *
  * @param g {@link BipartiteGraph}
  * @param c2 first {@link EdgeArray}
  * @param c1 second {@link EdgeArray}
  * @param f value
  * @return <code>true</code> is none of the edges properties in the two array are equal
  */
 private boolean scaleWeights(final BipartiteGraph g, final EdgeArray c2, EdgeArray c1, double f) {
   Edge e;
   double C = 0;
   Iterator<Edge> edgesIterator = g.getEdgesIterator();
   while (edgesIterator.hasNext()) {
     e = (Edge) edgesIterator.next();
     C = Math.max(C, fabs((((Double) c2.getEdgeProperty(e)).doubleValue())));
   }
   double S = computeS(f, C);
   boolean noScaling = true;
   edgesIterator = g.getEdgesIterator();
   while (edgesIterator.hasNext()) {
     e = (Edge) edgesIterator.next();
     c1.setEdgeProperty(
         e, new Double(scaleWeight(((Double) c2.getEdgeProperty(e)).doubleValue(), S)));
     if (((Double) c2.getEdgeProperty(e)).doubleValue()
         != ((Double) c1.getEdgeProperty(e)).doubleValue()) noScaling = false;
   }
   return noScaling;
 }
  /**
   * Run the algorithm
   *
   * @return an {@link EdgesSet}
   */
  public EdgesSet runAlgorithm() {
    EdgesSet result = new EdgesSet(g.getEdgesSet().getVc());
    // for all nodes(v,G) pot[v] = 0;
    // this will be done by giving pot:= VertexArray(g,new Double(0))
    if (g.getEdgesSet().isEmpty()) return new EdgesSet(g.getEdgesSet().getVc());
    // check that all edges are directed from A to B
    // this should be a precondition also
    VertexArray free = new VertexArray(g, new Boolean(true));
    VertexArray pred = new VertexArray(g, null);
    VertexArray dist = new VertexArray(g, new Double(0));
    VertexPQ PQ = new VertexPQ(g);

    switch (heuristic) {
      case NAIVE_HEURISTIC:
        Double C = new Double(0);
        Iterator<Edge> edgesIterator = g.getEdgesIterator();
        while (edgesIterator.hasNext()) {
          Edge e = edgesIterator.next();
          Double edgeC = (Double) c.getEdgeProperty(e);
          if (edgeC.compareTo(C) == 1) // bigger than...
          C = edgeC;
        }
        Iterator<Vertex> leftVertexesIterator = g.getLeftVertexSetIterator();
        while (leftVertexesIterator.hasNext()) {
          pot.setVertexProperty(leftVertexesIterator.next(), C);
        }
        break;
      case SIMPLE_HEURISTIC:
        Iterator<Vertex> leftVertexesIterator1 = g.getLeftVertexSetIterator();
        while (leftVertexesIterator1.hasNext()) {
          Vertex a = leftVertexesIterator1.next();
          Edge eMax = null;
          double C_max = 0;
          Iterator<Edge> vertexAdjEdgesIterator =
              GraphUtilities.getVertexAdjEdges(g, a).getMembers().iterator();
          while (vertexAdjEdgesIterator.hasNext()) {
            Edge e = vertexAdjEdgesIterator.next();
            if (((Double) c.getEdgeProperty(e)).doubleValue() > C_max) {
              eMax = e;
              C_max = ((Double) c.getEdgeProperty(e)).doubleValue();
            }
          }
          pot.setVertexProperty(a, new Double(C_max));
          Vertex b;
          if (eMax != null
              && ((Boolean)
                      free.getVertexProperty((b = GraphUtilities.getEdgeTargetVertex(g, eMax))))
                  .booleanValue()) {
            eMax.turnOverEdgeDirection();
            free.setVertexProperty(a, new Boolean(false));
            free.setVertexProperty(b, new Boolean(false));
          }
        }
        break;
      default:
        // REFINED_HEURISTIC
        mwbmHeuristic(g, c, pot, free);
        break;
    }
    Iterator<Vertex> leftVertexesIterator = g.getLeftVertexSetIterator();
    while (leftVertexesIterator.hasNext()) {
      Vertex a = leftVertexesIterator.next();
      if (((Boolean) free.getVertexProperty(a)).booleanValue())
        augment(g, a, c, pot, free, pred, dist, PQ);
    }
    Iterator<Vertex> rightVertexesIterator = g.getRightVertexSetIterator();
    while (rightVertexesIterator.hasNext()) {
      Vertex b = rightVertexesIterator.next();
      Iterator<Edge> outEdgesIterator =
          GraphUtilities.getVertexOutEdges(g, b).getMembers().iterator();
      while (outEdgesIterator.hasNext()) {
        result.addMember(outEdgesIterator.next());
      }
    }
    result.turnOverEdges(false);
    return result;
  }