/* * File: GraphStats.java * Authors: Jeremy D. Wendt * Company: Sandia National Laboratories * Project: Cognitive Foundry * * Copyright 2016, Sandia Corporation. * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive * license for use of this work by or on behalf of the U.S. Government. * Export of this program may require a license from the United States * Government. See CopyrightHistory.txt for complete details. * */ package examples; import examples.io.GraphFileIo; import gov.sandia.cognition.graph.DirectedNodeEdgeGraph; import gov.sandia.cognition.graph.GraphMetrics; import gov.sandia.cognition.util.Pair; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * This class shows how you can perform various statistics on an input graph. * * @author jdwendt */ public class GraphStats { /** * Specifies the arguments this code requires to run */ private static class Arguments { private String inputFilename; private boolean numNodes; private boolean numEdges; private boolean assortativity; private boolean graphAll; private boolean nodeDegree; private boolean nodeNumNeighbors; private boolean nodeNumSuccessors; private boolean nodeNumTriangles; private boolean nodeAll; private boolean edgeJaccardSimilarity; private boolean edgeNumTriangles; private boolean edgeTriangleDensity; private boolean edgeAll; private boolean all; private boolean printAttrs; private boolean printCsv; public Arguments() { // Set this to the appropriate filename inputFilename = "example.dot"; // You may set each of these separately true .... numNodes = false; numEdges = false; assortativity = false; nodeDegree = false; nodeNumNeighbors = false; nodeNumSuccessors = false; nodeNumTriangles = false; edgeJaccardSimilarity = false; edgeNumTriangles = false; edgeTriangleDensity = false; // .... or you may set groups of them true // All per-node metrics nodeAll = true; // All per-edge metrics edgeAll = false; // All graph-wide metrics (numNodes, numEdges) graphAll = false; // All metrics (per-node, per-edge, graph-wide) all = false; // Affects what gets output and how printCsv = false; printAttrs = false; } }; /** * Takes in the command line args and sets up the flags for running this * * @param args * @return */ private static Arguments handleArgs(String[] args) { Arguments ret = new Arguments(); if (args.length == 1) { ret.inputFilename = args[0]; } if (ret.inputFilename == null) { System.err.println("Can't run without filename set"); return null; } return ret; } /** * Writes out the results to stdout * * @param output * @param verticalCsv */ private static void print(List<List<String>> output, boolean verticalCsv) { if (verticalCsv) { int maxLen = 0; for (List<String> row : output) { maxLen = Math.max(maxLen, row.size()); } for (int i = 0; i < maxLen; ++i) { String comma = ""; for (List<String> row : output) { System.out.print(comma); if (i < row.size()) { System.out.print(row.get(i)); } comma = ","; } System.out.println(); } } else { for (List<String> row : output) { String comma = ""; for (int i = 0; i < row.size(); ++i) { System.out.print(comma + row.get(i)); comma = ", "; } System.out.println(); } } } public static Set<String> getAllPossibleAttributes( Map<String, Map<String, String>> attrs) { Set<String> ret = new HashSet<>(); for (Map.Entry<String, Map<String, String>> e : attrs.entrySet()) { ret.addAll(e.getValue().keySet()); } return ret; } public static void main(String[] args) { Arguments a = handleArgs(args); if (a == null) { return; } // Read in the graph DirectedNodeEdgeGraph<String> graph; Map<String, Map<String, String>> nodeAttrs = new HashMap<>();; Map<String, Map<String, String>> edgeAttrs = new HashMap<>(); String extension = a.inputFilename.substring( a.inputFilename.lastIndexOf(".")); switch (extension.toLowerCase()) { case ".dot": graph = GraphFileIo.readDotFile(a.inputFilename, nodeAttrs, edgeAttrs); break; case ".csv": case ".el": case ".txt": graph = GraphFileIo.readEdgeListFile(a.inputFilename); break; default: throw new RuntimeException("Unknown file extension: " + extension); } // This object stores a link to the graph and computes/stores metrics as requested GraphMetrics<String> metrics = new GraphMetrics<>(graph); List<List<String>> output = new ArrayList<>(); List<String> tmp; // We now go through the various flags and add results to the output if (a.numNodes || a.graphAll || a.all) { tmp = new ArrayList<>(); tmp.add("Graph NumNodes"); tmp.add(Integer.toString(metrics.numNodes())); output.add(tmp); } if (a.numEdges || a.graphAll || a.all) { tmp = new ArrayList<>(); tmp.add("Graph NumEdges"); tmp.add(Integer.toString(metrics.numEdges())); output.add(tmp); } if (a.assortativity || a.graphAll || a.all) { tmp = new ArrayList<>(); tmp.add("Graph Assortativity"); tmp.add(Double.toString(metrics.degreeAssortativity())); output.add(tmp); } if (a.nodeDegree || a.nodeNumNeighbors || a.nodeNumSuccessors || a.nodeNumTriangles || a.nodeAll || a.printAttrs || a.all) { // Print the names of all nodes in order tmp = new ArrayList<>(); tmp.add("Node Names"); for (int i = 0; i < graph.getNumNodes(); ++i) { tmp.add(graph.getNode(i)); } output.add(tmp); } if (a.printAttrs || a.nodeAll || a.all) { Set<String> attrNames = getAllPossibleAttributes(nodeAttrs); if (attrNames.size() > 0) { for (String attr : attrNames) { tmp = new ArrayList<>(); tmp.add(attr); for (int i = 0; i < graph.getNumNodes(); ++i) { String v = nodeAttrs.get(graph.getNode(i)).get(attr); v = (v == null) ? "" : v; tmp.add(v); } output.add(tmp); } } } if (a.nodeDegree || a.nodeAll || a.all) { tmp = new ArrayList<>(); tmp.add("Node Degrees"); for (int i = 0; i < graph.getNumNodes(); ++i) { tmp.add(Integer.toString(metrics.degree(i))); } output.add(tmp); } if (a.nodeNumNeighbors || a.nodeAll || a.all) { tmp = new ArrayList<>(); tmp.add("Node NumNeighbors"); for (int i = 0; i < graph.getNumNodes(); ++i) { tmp.add(Integer.toString(metrics.numNeighbors(i))); } output.add(tmp); } if (a.nodeNumSuccessors || a.nodeAll || a.all) { tmp = new ArrayList<>(); tmp.add("Node NumSuccessors"); for (int i = 0; i < graph.getNumNodes(); ++i) { tmp.add(Integer.toString(metrics.numSuccessors(i))); } output.add(tmp); } if (a.nodeNumTriangles || a.nodeAll || a.all) { tmp = new ArrayList<>(); tmp.add("Node NumTriangles"); for (int i = 0; i < graph.getNumNodes(); ++i) { tmp.add(Integer.toString(metrics.numNodeTriangles(i))); } output.add(tmp); } if (a.edgeJaccardSimilarity || a.edgeNumTriangles || a.edgeTriangleDensity || a.printAttrs || a.edgeAll || a.all) { // First print all edges in order tmp = new ArrayList<>(); tmp.add("Edge Names"); for (int i = 0; i < graph.getNumEdges(); ++i) { Pair<Integer, Integer> e = graph.getEdgeEndpointIds(i); String edge = "(" + graph.getNode(e.getFirst()) + "-" + graph.getNode(e.getSecond()) + ")"; tmp.add(edge); } output.add(tmp); } if (a.printAttrs || a.edgeAll || a.all) { Set<String> attrNames = getAllPossibleAttributes(edgeAttrs); if (attrNames.size() > 0) { for (String attr : attrNames) { tmp = new ArrayList<>(); tmp.add(attr); for (int i = 0; i < graph.getNumEdges(); ++i) { Pair<Integer, Integer> ee = graph.getEdgeEndpointIds(i); String src = graph.getNode(ee.getFirst()); String dst = graph.getNode(ee.getSecond()); String edge = GraphFileIo.toEdgeName(src, dst); String v = edgeAttrs.get(edge).get(attr); v = (v == null) ? "" : v; tmp.add(v); } output.add(tmp); } } } if (a.edgeJaccardSimilarity || a.edgeAll || a.all) { tmp = new ArrayList<>(); tmp.add("Edge JaccardSimilarity"); for (int i = 0; i < graph.getNumEdges(); ++i) { tmp.add(Double.toString( metrics.getEdgeJaccardSimilarity(i))); } output.add(tmp); } if (a.edgeNumTriangles || a.edgeAll || a.all) { tmp = new ArrayList<>(); tmp.add("Edge NumTriangles"); for (int i = 0; i < graph.getNumEdges(); ++i) { tmp.add(Integer.toString(metrics.numEdgeTriangles(i))); } output.add(tmp); } if (a.edgeTriangleDensity || a.edgeAll || a.all) { tmp = new ArrayList<>(); tmp.add("Edge TriangleDensity"); for (int i = 0; i < graph.getNumEdges(); ++i) { tmp.add(Double.toString( metrics.getPerEdgeTriangleDensity(i))); } output.add(tmp); } print(output, a.printCsv); } }