@Override
 public Number[] getValues(Graph graph) {
   DirectedGraph dgraph = (DirectedGraph) graph;
   List<Integer> values = new ArrayList<>(dgraph.getNodeCount());
   for (Node n : dgraph.getNodes()) {
     int degree = dgraph.getInDegree(n);
     values.add(degree);
   }
   return values.toArray(new Number[0]);
 }
  @Override
  public boolean evaluate(Graph graph, Edge edge) {
    DirectedGraph directedGraph = (DirectedGraph) graph;

    // Make sure the edge is not  self loop
    if (!edge.isSelfLoop()) {
      // Get the potential mutual edge
      Edge mutualEdge = directedGraph.getEdge(edge.getTarget(), edge.getSource());

      // Remove the mutual edge if exists
      // Make sure only one of the two mutual edges will bre removed
      if (mutualEdge != null && mutualEdge.getId() < edge.getId()) {
        return false;
      }
    }
    return true;
  }
  private void exportData(Graph graph) throws Exception {
    int max = graph.getNodeCount();

    Progress.start(progressTicket, max);

    if (!list) {
      if (header) {
        writer.append(SEPARATOR);
        Node[] nodes = graph.getNodes().toArray();
        for (int i = 0; i < nodes.length; i++) {
          writeMatrixNode(nodes[i], i < nodes.length - 1);
        }
        writer.append(EOL);
      }
    }

    if (list) {
      Node[] nodes = graph.getNodes().toArray();
      for (int i = 0; i < nodes.length; i++) {
        Node n = nodes[i];
        List<Node> neighbours = new ArrayList<Node>();
        for (Edge e : graph.getEdges(n)) {
          if (!e.isDirected() || (e.isDirected() && n == e.getSource())) {
            Node m = graph.getOpposite(n, e);
            neighbours.add(m);
          }
        }

        for (Edge e : ((HierarchicalGraph) graph).getMetaEdges(n)) {
          if (!e.isDirected() || (e.isDirected() && n == e.getSource())) {
            Node m = graph.getOpposite(n, e);
            neighbours.add(m);
          }
        }

        writeListNode(n, !neighbours.isEmpty());
        for (int j = 0; j < neighbours.size(); j++) {
          writeListNode(neighbours.get(j), j < neighbours.size() - 1);
        }
        writer.append(EOL);
      }
    } else {
      if (graph instanceof DirectedGraph) {
        DirectedGraph directedGraph = (DirectedGraph) graph;
        Node[] nodes = graph.getNodes().toArray();
        for (Node n : nodes) {
          if (cancel) {
            break;
          }
          writeMatrixNode(n, true);
          for (int j = 0; j < nodes.length; j++) {
            Node m = nodes[j];
            Edge e = directedGraph.getEdge(n, m);
            e = e == null ? ((HierarchicalDirectedGraph) directedGraph).getMetaEdge(n, m) : e;
            writeEdge(e, j < nodes.length - 1);
          }
          Progress.progress(progressTicket);
          writer.append(EOL);
        }
      } else if (graph instanceof UndirectedGraph) {
        UndirectedGraph undirectedGraph = (UndirectedGraph) graph;
        Node[] nodes = graph.getNodes().toArray();
        for (Node n : nodes) {
          if (cancel) {
            break;
          }
          writeMatrixNode(n, true);
          for (int j = 0; j < nodes.length; j++) {
            Node m = nodes[j];
            Edge e = undirectedGraph.getEdge(n, m);
            e = e == null ? ((HierarchicalUndirectedGraph) undirectedGraph).getMetaEdge(n, m) : e;
            writeEdge(e, j < nodes.length - 1);
          }
          Progress.progress(progressTicket);
          writer.append(EOL);
        }
      } else {
        MixedGraph mixedGraph = (MixedGraph) graph;
        Node[] nodes = graph.getNodes().toArray();
        for (Node n : graph.getNodes()) {
          if (cancel) {
            break;
          }
          writeMatrixNode(n, true);
          for (int j = 0; j < nodes.length; j++) {
            Node m = nodes[j];
            Edge e = mixedGraph.getEdge(n, m);
            e = e == null ? ((HierarchicalMixedGraph) mixedGraph).getMetaEdge(n, m) : e;
            writeEdge(e, j < nodes.length - 1);
          }
          Progress.progress(progressTicket);
          writer.append(EOL);
        }
      }
    }

    graph.readUnlockAll();

    Progress.finish(progressTicket);
  }