private WeightedMultigraph<Vertex, LabeledWeightedEdge> step1() {

    logger.debug("<enter");

    WeightedMultigraph<Vertex, LabeledWeightedEdge> g =
        new WeightedMultigraph<Vertex, LabeledWeightedEdge>(LabeledWeightedEdge.class);

    for (int i = 0; i < steinerNodes.size(); i++) {
      g.addVertex(steinerNodes.get(i));
    }

    BellmanFordShortestPath<Vertex, LabeledWeightedEdge> path;

    for (int i = 0; i < steinerNodes.size(); i++) {
      path =
          new BellmanFordShortestPath<Vertex, LabeledWeightedEdge>(this.graph, steinerNodes.get(i));

      for (int j = 0; j < steinerNodes.size(); j++) {

        if (i == j) continue;

        if (g.containsEdge(steinerNodes.get(i), steinerNodes.get(j))) continue;

        String id = "e" + String.valueOf(i) + String.valueOf(j);
        LabeledWeightedEdge e = new LabeledWeightedEdge(id, new URI(id, null, null), null);
        g.addEdge(steinerNodes.get(i), steinerNodes.get(j), e);
        g.setEdgeWeight(e, path.getCost(steinerNodes.get(j)));
      }
    }

    logger.debug("exit>");

    return g;
  }
  private void runAlgorithm() {

    logger.debug("<enter");

    WeightedMultigraph<Vertex, LabeledWeightedEdge> g1 = step1();
    //		GraphUtil.printGraph(g1);
    //		GraphUtil.printGraphSimple(g1);

    if (g1.vertexSet().size() < 2) {
      this.tree = g1;
      return;
    }

    WeightedMultigraph<Vertex, LabeledWeightedEdge> g2 = step2(g1);
    //		GraphUtil.printGraph(g2);
    //		GraphUtil.printGraphSimple(g2);

    WeightedMultigraph<Vertex, LabeledWeightedEdge> g3 = step3(g2);
    //		GraphUtil.printGraph(g3);
    //		GraphUtil.printGraphSimple(g3);

    WeightedMultigraph<Vertex, LabeledWeightedEdge> g4 = step4(g3);
    //		GraphUtil.printGraph(g4);
    //		GraphUtil.printGraphSimple(g4);

    WeightedMultigraph<Vertex, LabeledWeightedEdge> g5 = step5(g4);
    //		GraphUtil.printGraph(g5);
    //		GraphUtil.printGraphSimple(g5);

    this.tree = g5;
    logger.debug("exit>");
  }
  private WeightedMultigraph<Vertex, LabeledWeightedEdge> step2(
      WeightedMultigraph<Vertex, LabeledWeightedEdge> g1) {

    logger.debug("<enter");

    KruskalMinimumSpanningTree<Vertex, LabeledWeightedEdge> mst =
        new KruskalMinimumSpanningTree<Vertex, LabeledWeightedEdge>(g1);

    //    	System.out.println("Total MST Cost: " + mst.getSpanningTreeCost());

    Set<LabeledWeightedEdge> edges = mst.getEdgeSet();

    WeightedMultigraph<Vertex, LabeledWeightedEdge> g2 =
        new WeightedMultigraph<Vertex, LabeledWeightedEdge>(LabeledWeightedEdge.class);

    List<LabeledWeightedEdge> edgesSortedByLabel = new ArrayList<LabeledWeightedEdge>();

    for (LabeledWeightedEdge e : edges) edgesSortedByLabel.add(e);

    Collections.sort(edgesSortedByLabel, new EdgeComparatorByLabel());

    for (LabeledWeightedEdge edge : edgesSortedByLabel) {

      //			//just for test, forcing to select another equal minimal spanning tree
      //			if (g1.getEdgeSource(edge).getLabel().equalsIgnoreCase("v1") &&
      //					g1.getEdgeTarget(edge).getLabel().equalsIgnoreCase("v3") ) {
      //				Vertex v2 = steinerNodes.get(1);
      //				g2.addVertex(g1.getEdgeTarget(edge));
      //				g2.addVertex(v2);
      //				LabeledWeightedEdge e = new LabeledWeightedEdge("e");
      //				g2.setEdgeWeight(e, g1.getEdgeWeight(edge));
      //				g2.addEdge(g1.getEdgeTarget(edge), v2, e);
      //			} else
      {
        g2.addVertex(edge.getSource());
        g2.addVertex(edge.getTarget());
        g2.addEdge(edge.getSource(), edge.getTarget(), edge);
      }
    }

    logger.debug("exit>");

    return g2;
  }
  private WeightedMultigraph<Vertex, LabeledWeightedEdge> step5(
      WeightedMultigraph<Vertex, LabeledWeightedEdge> g4) {

    logger.debug("<enter");

    WeightedMultigraph<Vertex, LabeledWeightedEdge> g5 = g4;

    List<Vertex> nonSteinerLeaves = new ArrayList<Vertex>();

    Set<Vertex> vertexSet = g4.vertexSet();
    for (Vertex vertex : vertexSet) {
      if (g5.degreeOf(vertex) == 1 && steinerNodes.indexOf(vertex) == -1) {
        nonSteinerLeaves.add(vertex);
      }
    }

    Vertex source, target;
    for (int i = 0; i < nonSteinerLeaves.size(); i++) {
      source = nonSteinerLeaves.get(i);
      do {
        LabeledWeightedEdge e = g5.edgesOf(source).toArray(new LabeledWeightedEdge[0])[0];
        target = this.graph.getEdgeTarget(e);

        // this should not happen, but just in case of ...
        if (target.equals(source)) target = e.getSource();

        g5.removeVertex(source);
        source = target;
      } while (g5.degreeOf(source) == 1 && steinerNodes.indexOf(source) == -1);
    }

    logger.debug("exit>");

    return g5;
  }
  private WeightedMultigraph<Vertex, LabeledWeightedEdge> step3(
      WeightedMultigraph<Vertex, LabeledWeightedEdge> g2) {

    logger.debug("<enter");

    WeightedMultigraph<Vertex, LabeledWeightedEdge> g3 =
        new WeightedMultigraph<Vertex, LabeledWeightedEdge>(LabeledWeightedEdge.class);

    Set<LabeledWeightedEdge> edges = g2.edgeSet();
    DijkstraShortestPath<Vertex, LabeledWeightedEdge> path;

    Vertex source, target;

    for (LabeledWeightedEdge edge : edges) {
      source = edge.getSource();
      target = edge.getTarget();

      path = new DijkstraShortestPath<Vertex, LabeledWeightedEdge>(this.graph, source, target);
      List<LabeledWeightedEdge> pathEdges = path.getPathEdgeList();

      if (pathEdges == null) continue;

      for (int i = 0; i < pathEdges.size(); i++) {

        if (g3.edgeSet().contains(pathEdges.get(i))) continue;

        source = pathEdges.get(i).getSource();
        target = pathEdges.get(i).getTarget();

        if (!g3.vertexSet().contains(source)) g3.addVertex(source);

        if (!g3.vertexSet().contains(target)) g3.addVertex(target);

        g3.addEdge(source, target, pathEdges.get(i));
      }
    }

    logger.debug("exit>");

    return g3;
  }
  public EdgeBetweennessGraph(WeightedMultigraph<String, DefaultWeightedEdge> originalGraph) {
    super(DefaultWeightedEdge.class); // Constructor inherented from parent class

    // 1. Initialize the edge betweenness digraph
    // 1.1. Add vertices
    for (String thisVertex : originalGraph.vertexSet()) this.addVertex(thisVertex);
    // 1.2. Add edges
    for (DefaultWeightedEdge thisEdge : originalGraph.edgeSet()) {
      DefaultWeightedEdge newEdge = new DefaultWeightedEdge();
      String sendingName = originalGraph.getEdgeSource(thisEdge);
      String receivingName = originalGraph.getEdgeTarget(thisEdge);
      this.addEdge(sendingName, receivingName, newEdge);
      this.setEdgeWeight(newEdge, 0.0);
    }
    // 1.3. Create corresponding unweighted graph
    // 1.3.1. Add vertices
    WeightedMultigraph<String, DefaultWeightedEdge> originalUnweightedGraph =
        new WeightedMultigraph<String, DefaultWeightedEdge>(DefaultWeightedEdge.class);
    for (String thisVertex : originalGraph.vertexSet())
      originalUnweightedGraph.addVertex(thisVertex);
    // 1.3.2. Add edges
    for (DefaultWeightedEdge thisEdge : originalGraph.edgeSet()) {
      DefaultWeightedEdge newEdge = new DefaultWeightedEdge();
      String sendingName = originalGraph.getEdgeSource(thisEdge);
      String receivingName = originalGraph.getEdgeTarget(thisEdge);
      originalUnweightedGraph.addEdge(sendingName, receivingName, newEdge);
      originalUnweightedGraph.setEdgeWeight(newEdge, 1.0);
    }

    for (String thisVertex : this.vertexSet()) {
      // 2. Create shortest-path graph for every vertex by Dijkstra algorithm
      Multigraph<String, DefaultEdge> shortestPathDigraph =
          DijkstraAlgorithm(originalUnweightedGraph, thisVertex);

      // 3. Calculate the contribution of current vertex's shortest-path graph to final edge
      // betweenness (Newman algorithm)
      SimpleWeightedGraph<String, DefaultWeightedEdge> edgeBetweennessDigraph =
          NewmanAlgorithm(shortestPathDigraph, thisVertex);

      // 4. Update final edge betweenness digraph with current vertex's shortest-path graph
      if (edgeBetweennessDigraph != null)
        for (DefaultWeightedEdge thisEdge : edgeBetweennessDigraph.edgeSet()) {
          String sourceVertex = edgeBetweennessDigraph.getEdgeSource(thisEdge);
          String targetVertex = edgeBetweennessDigraph.getEdgeTarget(thisEdge);
          double betweennessWeight = edgeBetweennessDigraph.getEdgeWeight(thisEdge);
          DefaultWeightedEdge edgeInWholeGraph = this.getEdge(sourceVertex, targetVertex);
          double newWeight = this.getEdgeWeight(edgeInWholeGraph) + betweennessWeight;
          this.setEdgeWeight(edgeInWholeGraph, newWeight);
        }
    }

    // 5. Revise the edge betweenness digraph with the original active power digraph
    for (DefaultWeightedEdge thisEdge : this.edgeSet()) {
      String sourceVertex = this.getEdgeSource(thisEdge);
      String targetVertex = this.getEdgeTarget(thisEdge);
      double betweennessWeight = this.getEdgeWeight(thisEdge);
      DefaultWeightedEdge edgeInWholeGraph = originalGraph.getEdge(sourceVertex, targetVertex);
      double newWeight = betweennessWeight / originalGraph.getEdgeWeight(edgeInWholeGraph);
      this.setEdgeWeight(thisEdge, newWeight);
      //			System.out.println("Final edge betweenness between " + sourceVertex + " and " +
      // targetVertex + ": " + newWeight);
    }
  }
  // Create shortest-path graph for every vertex by depth-first traversal algorithm
  private Multigraph<String, DefaultEdge> DijkstraAlgorithm(
      WeightedMultigraph<String, DefaultWeightedEdge> originalGraph, String thisVertex) {

    // 1. Simplify the multi-graph of the active power flow into a simple graph
    SimpleWeightedGraph<String, DefaultWeightedEdge> originalSimpleGraph =
        new SimpleWeightedGraph<String, DefaultWeightedEdge>(DefaultWeightedEdge.class);
    for (String curVertex : originalGraph.vertexSet()) originalSimpleGraph.addVertex(curVertex);
    for (DefaultWeightedEdge curEdge : originalGraph.edgeSet()) {
      String sourceVertex = originalGraph.getEdgeSource(curEdge);
      String targetVertex = originalGraph.getEdgeTarget(curEdge);
      if (originalSimpleGraph.containsEdge(sourceVertex, targetVertex)) {
        DefaultWeightedEdge modifiedEdge = originalSimpleGraph.getEdge(sourceVertex, targetVertex);
        double newEdgeWeight =
            originalSimpleGraph.getEdgeWeight(modifiedEdge) + originalGraph.getEdgeWeight(curEdge);
        originalSimpleGraph.setEdgeWeight(modifiedEdge, newEdgeWeight);
      } else {
        DefaultWeightedEdge newEdge = new DefaultWeightedEdge();
        originalSimpleGraph.addEdge(sourceVertex, targetVertex, newEdge);
        originalSimpleGraph.setEdgeWeight(newEdge, originalGraph.getEdgeWeight(curEdge));
      }
    }
    // Issue (2010/10/25): Maybe larger amount of active power transfer still means weaker
    // relationship between the two terminal buses of a certain branch,
    // thus originalSimpleGraph other than inverseGraph should be used here.
    // Use the inverse of active power to build a new weighted directed graph (the larger the active
    // power is, the close the two buses will be)
    //		SimpleDirectedWeightedGraph<String, DefaultWeightedEdge> inverseGraph =
    //			new SimpleDirectedWeightedGraph<String, DefaultWeightedEdge>(DefaultWeightedEdge.class);
    //		for (String curVertex : originalSimpleGraph.vertexSet())
    //			inverseGraph.addVertex(curVertex);
    //		for (DefaultWeightedEdge curEdge : originalSimpleGraph.edgeSet()) {
    //			String sourceVertex = originalSimpleGraph.getEdgeSource(curEdge);
    //			String targetVertex = originalSimpleGraph.getEdgeTarget(curEdge);
    //			DefaultWeightedEdge newEdge = new DefaultWeightedEdge();
    //			inverseGraph.addEdge(sourceVertex, targetVertex, newEdge);
    //			inverseGraph.setEdgeWeight(newEdge, 1 / originalSimpleGraph.getEdgeWeight(curEdge));
    //		}
    // 2. Initialize the map of vertices and the corresponding weights (distance from current vertex
    // to the first vertex)
    HashMap<String, Double> mapVertexShortestDistance = new HashMap<String, Double>();
    //		for (String thisOriginalVertex : inverseGraph.vertexSet())
    for (String thisOriginalVertex : originalSimpleGraph.vertexSet())
      mapVertexShortestDistance.put(thisOriginalVertex, 10E10);
    // The weight of the first vertex is zero
    mapVertexShortestDistance.put(thisVertex, 0.0);

    // 3. Depth-first traversing, update the shortest-path values
    Stack<String> bfiVertices =
        new Stack<String>(); // Stack to store passed vertices in a breadth-first traversing
    // The map of a weighted edge and the flag of having been visited
    //		HashMap<DefaultWeightedEdge, Boolean> mapEdgeVisited = new HashMap<DefaultWeightedEdge,
    // Boolean>();
    //		for (DefaultWeightedEdge thisEdge : inverseGraph.edgeSet())
    //			mapEdgeVisited.put(thisEdge, false);
    String currentVertex = thisVertex;
    bfiVertices.push(currentVertex);
    //		System.out.println(bfiVertices.toString());
    while (!bfiVertices.isEmpty()) {
      // Operate the following codes for those edges started with current vertex
      boolean hasNewEdge = false;
      //			for (DefaultWeightedEdge curEdge : inverseGraph.outgoingEdgesOf(currentVertex)) {
      for (DefaultWeightedEdge curEdge : originalSimpleGraph.edgesOf(currentVertex)) {
        //				if (!mapEdgeVisited.get(curEdge)) {	// Used for those edges that have not been treated
        // yet
        // 3.1. Mark current edge as already been visited
        //					mapEdgeVisited.put(curEdge, true);
        //				String nextVertex = inverseGraph.getEdgeTarget(curEdge);
        String nextVertex = originalSimpleGraph.getEdgeTarget(curEdge);
        // 3.2. Update shortest-path values
        double curSD = mapVertexShortestDistance.get(currentVertex);
        //					double edgeWeight = inverseGraph.getEdgeWeight(curEdge);
        double edgeWeight = originalSimpleGraph.getEdgeWeight(curEdge);
        double newSD = curSD + edgeWeight;
        if (mapVertexShortestDistance.get(nextVertex) > newSD) {
          hasNewEdge = true;
          mapVertexShortestDistance.put(nextVertex, newSD);
          // 3.3. Push the target vertex of current edge into the stack
          bfiVertices.push(nextVertex);
          //						System.out.println(bfiVertices.toString());
          break;
          //						System.out.println("New shortest path [" + nextVertex + "]: " + newSD);
        }
        //				}
      }
      if (!hasNewEdge) {
        bfiVertices.pop();
      }
      if (!bfiVertices.isEmpty()) currentVertex = bfiVertices.peek();
    }
    // 4. Create shortest-path digraph of current vertex
    // 4.1. Initialize the shortest-path digraph
    Multigraph<String, DefaultEdge> shortestPathGraph =
        new Multigraph<String, DefaultEdge>(DefaultEdge.class);
    // 4.2. Add all qualified edges
    //		for (DefaultWeightedEdge curEdge : inverseGraph.edgeSet()) {
    for (DefaultWeightedEdge curEdge : originalSimpleGraph.edgeSet()) {
      // 4.2.1. Evaluate if current edge is suitable
      //			String sourceVertex = inverseGraph.getEdgeSource(curEdge);
      //			String targetVertex = inverseGraph.getEdgeTarget(curEdge);
      String sourceVertex = originalSimpleGraph.getEdgeSource(curEdge);
      String targetVertex = originalSimpleGraph.getEdgeTarget(curEdge);
      //			if (Math.abs(inverseGraph.getEdgeWeight(curEdge) -
      if (originalSimpleGraph.getEdgeWeight(curEdge) > 1.0E-5) {
        if (Math.abs(
                originalSimpleGraph.getEdgeWeight(curEdge)
                    - (mapVertexShortestDistance.get(targetVertex)
                        - mapVertexShortestDistance.get(sourceVertex)))
            < 1.0E-5) {
          // 4.2.2. Add suitable edge that found just now
          DefaultEdge newEdge = new DefaultEdge();
          if (!shortestPathGraph.containsVertex(sourceVertex))
            shortestPathGraph.addVertex(sourceVertex);
          if (!shortestPathGraph.containsVertex(targetVertex))
            shortestPathGraph.addVertex(targetVertex);
          shortestPathGraph.addEdge(sourceVertex, targetVertex, newEdge);
        }
      }
    }
    return shortestPathGraph;
  }