private static void computeGraphStatistics(
      RDFDataSet tripleStore, ClassificationDataSet ds, boolean[] inference, int[] depths) {
    Map<Boolean, Map<Integer, Pair<Double, Double>>> stats =
        new HashMap<Boolean, Map<Integer, Pair<Double, Double>>>();

    for (boolean inf : inference) {
      stats.put(inf, new HashMap<Integer, Pair<Double, Double>>());
      for (int depth : depths) {

        Set<Statement> st =
            RDFUtils.getStatements4Depth(tripleStore, ds.getRDFData().getInstances(), depth, inf);
        st.removeAll(ds.getRDFData().getBlackList());
        DTGraph<String, String> graph = RDFUtils.statements2Graph(st, RDFUtils.REGULAR_LITERALS);
        List<DTNode<String, String>> instanceNodes =
            RDFUtils.findInstances(graph, ds.getRDFData().getInstances());
        graph = RDFUtils.simplifyInstanceNodeLabels(graph, instanceNodes);
        GraphList<DTGraph<String, String>> graphs =
            RDFUtils.getSubGraphs(graph, instanceNodes, depth);

        double v = 0;
        double e = 0;
        for (DTGraph<String, String> g : graphs.getGraphs()) {
          v += g.nodes().size();
          e += g.links().size();
        }
        v /= graphs.numInstances();
        e /= graphs.numInstances();

        stats.get(inf).put(depth, new Pair<Double, Double>(v, e));
      }
    }

    for (boolean k1 : stats.keySet()) {
      System.out.println("Inference: " + k1);
      for (int k2 : stats.get(k1).keySet()) {
        System.out.println(
            "Depth "
                + k2
                + ", vertices: "
                + (stats.get(k1).get(k2).getFirst())
                + " , edges: "
                + (stats.get(k1).get(k2).getSecond()));
      }
    }
  }
  private void init(DTGraph<String, String> graph, List<DTNode<String, String>> instances) {
    DTNode<StringLabel, StringLabel> startV;
    List<DTNode<String, String>> frontV, newFrontV;
    List<Pair<DTNode<StringLabel, StringLabel>, Integer>> vertexIndexMap;
    List<Pair<DTLink<StringLabel, StringLabel>, Integer>> edgeIndexMap;
    Map<DTNode<String, String>, DTNode<StringLabel, StringLabel>> vOldNewMap =
        new HashMap<DTNode<String, String>, DTNode<StringLabel, StringLabel>>();
    Map<DTLink<String, String>, DTLink<StringLabel, StringLabel>> eOldNewMap =
        new HashMap<DTLink<String, String>, DTLink<StringLabel, StringLabel>>();

    instanceVertices = new ArrayList<DTNode<StringLabel, StringLabel>>();
    instanceVertexIndexMap =
        new HashMap<
            DTNode<StringLabel, StringLabel>,
            List<Pair<DTNode<StringLabel, StringLabel>, Integer>>>();
    instanceEdgeIndexMap =
        new HashMap<
            DTNode<StringLabel, StringLabel>,
            List<Pair<DTLink<StringLabel, StringLabel>, Integer>>>();
    rdfGraph = new LightDTGraph<StringLabel, StringLabel>();

    for (DTNode<String, String> oldStartV : instances) {
      vertexIndexMap = new ArrayList<Pair<DTNode<StringLabel, StringLabel>, Integer>>();
      edgeIndexMap = new ArrayList<Pair<DTLink<StringLabel, StringLabel>, Integer>>();

      // Get the start node
      if (vOldNewMap.containsKey(oldStartV)) {
        startV = vOldNewMap.get(oldStartV);
      } else {
        startV = rdfGraph.add(new StringLabel());
        vOldNewMap.put(oldStartV, startV);
      }
      startV.label().clear();
      startV.label().append(oldStartV.label());
      instanceVertices.add(startV);

      instanceVertexIndexMap.put(startV, vertexIndexMap);
      instanceEdgeIndexMap.put(startV, edgeIndexMap);

      frontV = new ArrayList<DTNode<String, String>>();
      frontV.add(oldStartV);

      // Process the start node
      vertexIndexMap.add(new Pair<DTNode<StringLabel, StringLabel>, Integer>(startV, depth));

      for (int j = depth - 1; j >= 0; j--) {
        newFrontV = new ArrayList<DTNode<String, String>>();
        for (DTNode<String, String> qV : frontV) {
          for (DTLink<String, String> edge : qV.linksOut()) {
            if (vOldNewMap.containsKey(edge.to())) { // This vertex has been added to rdfGraph
              vertexIndexMap.add(
                  new Pair<DTNode<StringLabel, StringLabel>, Integer>(
                      vOldNewMap.get(edge.to()), j));
              vOldNewMap.get(edge.to()).label().clear();
              vOldNewMap.get(edge.to()).label().append(edge.to().label());
            } else {
              DTNode<StringLabel, StringLabel> newN = rdfGraph.add(new StringLabel());
              newN.label().clear();
              newN.label().append(edge.to().label());
              vOldNewMap.put(edge.to(), newN);
              vertexIndexMap.add(new Pair<DTNode<StringLabel, StringLabel>, Integer>(newN, j));
            }

            if (eOldNewMap.containsKey(edge)) {
              edgeIndexMap.add(
                  new Pair<DTLink<StringLabel, StringLabel>, Integer>(eOldNewMap.get(edge), j));
              eOldNewMap.get(edge).tag().clear();
              eOldNewMap.get(edge).tag().append(edge.tag());
            } else {
              DTLink<StringLabel, StringLabel> newE =
                  vOldNewMap.get(qV).connect(vOldNewMap.get(edge.to()), new StringLabel());
              newE.tag().clear();
              newE.tag().append(edge.tag());
              eOldNewMap.put(edge, newE);
              edgeIndexMap.add(new Pair<DTLink<StringLabel, StringLabel>, Integer>(newE, j));
            }

            // Add the vertex to the new front, if we go into a new round
            if (j > 0) {
              newFrontV.add(edge.to());
            }
          }
        }
        frontV = newFrontV;
      }
    }
  }