Raw File
graph.h
#pragma once

#include <string>
#include <unordered_map>
#include <vector>

using std::ostream;
using std::string;
using std::unordered_map;
using std::vector;

class Graph {
 public:
  /**
   * The number of vertices in the graph.
   */
  int n;

  /**
   * The edges in the graph.
   */
  vector<vector<int>> edges;

  /**
   * The labels of the nodes.
   */
  vector<std::string> labels;

  /**
   * Yields a vector that has at position i the number of nodes with
   * degree i.
   */
  vector<int> degHisto() const;

  /**
   * Constructor for Graph.
   *
   * The graph will have n vertices and no edges.
   *
   * @param n The number of nodes of the graph.
   */
  Graph(int n) {
    this->n = n;
    edges.resize(n);
    for (int i = 0; i < n; ++i) {
      labels.push_back(std::to_string(i));
    }
  }

  Graph(const Graph& G);
  virtual ~Graph() {}

  /**
   * Reads a graph from an edge list stored in a file.
   *
   * @param  filename      The name of the file where the graph is to
   *                       be read from.
   * @param  label_to_node Maps a node index to each labeled node.
   * @return               The resulting graph.
   */
  static Graph fromFile(const string& filename,
                        unordered_map<std::string, int>* label_to_node);

  /**
   * Changes the number of nodes.
   *
   * Adds zero-degree vertices, if n is larger than the number of vertices
   * in the graph.
   *
   * Deletes the last vertices in the graph if n is smaller than the
   * number of vertices in the graph.
   *
   * Warning: Does not delete the edges to the deleted nodes!
   *
   * @param n The number of nodes that graph has after the resizing.
   */
  void resize(int n);

  /**
   * Deletes the edge from node1 to node2.
   *
   * Runtime linear in the degree of node1 + node2.
   *
   * @param node1 One node of the edge.
   * @param node2 The other node of the edge.
   */
  void deleteEdge(int node1, int node2);

  /**
   * Get the subgraph of a graph containing only the vertices that are
   * marked as 'true' in the passed vertices vector.
   *
   * @param  vertices A vector of bool values indicating for each vertex
   *                  whether it is included in the subgraph or not.
   * @return          The resulting subgraph.
   */
  Graph subgraph(vector<bool> vertices);

  /**
   * Finds the subgraph of the largest connected component in the graph.
   * @return The corresponding subgraph.
   */
  Graph giantSubgraph();

  /**
   * A simple subgraph, i.e. no self-loops or double edges.
   * @return [description]
   */
  Graph simpleSubgraph();

  /**
   * Calculates the average degree of the graph.
   * @return The average degree.
   */
  double averageDegree() const;

  /**
   * The number of edges in the graph.
   * @return The number of edges.
   */
  int numEdges() const;

  /**
   * The minimum degree of the graph.
   * @return The minimum degree.
   */
  int minDegree();

  /**
   * The maximum degree of the graph.
   * @return The maximum degree.
   */
  int maxDegree();

  /**
   * Estimates the power-law exponent of the graph. Uses a cumulative
   * degree sequence (i.e., a rank sequence)
   * @param  xmin [description]
   * @return      The estimated power-law exponent of the graph.
   */
  double powerLawExponent(int* xmin = nullptr) const;

  /**
   * The sizes of the components in the graph.
   * @return	A vector containin the sizes of the components of the graph.
   */
  vector<int> components() const;

  /**
   * Determines the giant component of a graph.
   * @param components	A vector containing the sizes of the components.
   * @return 				The bool vector indicating which
   * vertices belong to the giant component.
   */
  vector<bool> giant(vector<int> components) const;

  /**
   * The component histogram of all components except the giant one.
   * @return       A vector where the value at index i denotes the number
   *               of components of size i.
   */
  vector<int> smallComponentHisto(vector<int> components, vector<bool> giant);

  /**
   * The number of vertices in the giant component.
   * @param  giant The bool vector indicating which vertices belong to
   *               the giant component.
   * @return       The number of vertices in the giant component.
   */
  int sizeOfGiant(vector<bool> giant) const;

  /**
   * An approximation of the clustering coefficient.
   * @param  eps   [description]
   * @param  delta [description]
   * @return       An approximated clustering coefficient.
   */
  double approximateClusterCoeff(double eps, double delta);

  /**
   * Determines the clustering coefficient of the graph.
   * @return The clustering coefficient of the graph.
   */
  double clusterCoeff();

  /**
   * Determines the distance between u and v in the graph.
   * @param  u             A vertex in the graph.
   * @param  v             Another vertex in the graph.
   * @param  pointsVisited An array containing the vertices visited
   *                       when determining the distance between u
   *                       and v.
   * @return               The distance between u and v.
   */
  int distance(int u, int v, int* pointsVisited = NULL) const;

  /**
   * A vector containing the distances from v to all other vertices.
   * @param v			The vertex whose distance to all other vertices
   * is to be determined.
   * @param parent	An array containg the parent of each vertex obtained
   *               	when determining the distances between v and the
   *               	remaining vertices in the graph.
   * @return          A vector where the value at index i is the distance
   *                  between vertex v and the node i.
   */
  vector<int> distances(int v, vector<int>* parent = NULL);

  /**
   * Determines the diameter of the graph.
   * @param  nodes_on_diameter A bool vector indicating which vertices belong to
   * the path representing the diameter of the graph.
   * @return The diameter of the graph.
   */
  int diameter(vector<bool>* nodes_on_diameter);

  /**
   * A vector where the value at index i indicates the number of nodes
   * that have distance i to vertex v.
   * @param v		The vertex whose distance histogram is to be determined.
   * @return The distance histogram of vertex v.
   */
  vector<int> distanceHisto(int v);

  /**
   * Samples the distance histogram of the whole graph.
   * @param numsamples The number of samples used during the sampling.
   * @return A vector where the value at index i contains an approximation
   *         of how often the distance i occured between two vertices in
   *         the graph.
   */
  vector<double> sampleDistanceHisto(int numsamples);

  /**
   * An approximation of the average distance in the graph.
   * @param  eps                [description]
   * @param  delta              [description]
   * @param  diameterUpperBound [description]
   * @return                    [description]
   */
  double approximateAverageDistance(double eps, double delta,
                                    int diameterUpperBound);

  /**
   * Samples the average distance of the graph.
   * @param  numSamples The number of samples to use during the sampling.
   * @return            An approximation of the average distance in the
   *                    graph.
   */
  double sampleAverageDistance(int numSamples);

  /**
   * Samples an interval containing a lower and upper bound on the diameter.
   * @param numSamples The number of samples to use during the sampling.
   * @param upperBound The resulting upper bound on the diameter.
   * @param lowerBound The resulting lower bound on the diameter.
   */
  void diameterIntervalSampler(int numSamples, int& upperBound,
                               int& lowerBound);

  int push(int src);

  void pushpull(int src, double alpha1, double alpha2, int& time1, int& time2);

  double asynch_pushpull(int src, double alpha = 0.0);

  void asynch_pushpull(int src, double alpha1, double alpha2, double& time1,
                       double& time2);

  int pushpull(int src, double alpha, vector<int>* evol = NULL);

  /**
   * Determines whether the vertices u and v are adjacent.
   * @param  u A vertex in the graph.
   * @param  v Another vertex in the graph.
   * @return   true if u and v are adjacent. false if not.
   */
  bool adjacent(int u, int v) const;

  /**
   * Permutes the nodes on the graph to obtain an isomorphic graph.
   * Discards each node independently with probability 1-q.
   * @param q The inverse probability of discarding a node.
   */
  vector<int> permuteAndSubsampleGraph(double q);

  /**
   * Permutes nodes according to the given permutation.
   * If permutation[i] == -1 node i is discarded.
   * @param permutation [description]
   */
  void permuteGraph(const vector<int>& permutation);

  /**
   * Subsamples the graph's edges, keeping each edge with probability p.
   * @param  p The probability that an edge is kept.
   * @return   The subsampled graph.
   */
  Graph subsample(double p);

  /**
   * Reorders the adjacency lists s.t. they are ordered according to the
   * given permutation of nodes. Does not change the graph structure.
   *
   * E.g. if the permutation is [4,3,5,1,2] then a node with neighbors
   * 1,2,3 stores the neighbors as [3,1,2].
   * @param permutation The permutation that the node orders should be
   *                    adapted to.
   */
  void ReorderEdges(const vector<int>& permutation);

  /**
   * Determines whether the graph is directed or not.
   * @return true if and only if there exists an edge u-> but not v->u.
   */
  bool isDirected();

  /**
   * Reorders the nodes by decreasing degree. edges[0] is the node with
   * the largest degree. new_permutation will contain the reordering of
   * the nodes.
   * permutation[i] = j means that old node i is now node j.
   * @param new_permutation [description]
   */
  virtual void sortByDegrees(vector<int>* new_permutation);

  /**
   * Saves this graph to a file with the given name. Saves each edge
   * only once, i.e. consideres the graph to be undirected. Ignores
   * all edges (u, v) where either ignore_nodes[u] == true or
   * ignore_nodes[v] == true.
   * @param filename     The file that the graph should be written to.
   * @param ignore_nodes The nodes to not consider in the written graph.
   * @param use_labels   Denotes whether the indices of the nodes should
   *                     be used or their original labels.
   */
  virtual void printToFile(const char* filename,
                           const vector<bool>* ignore_nodes = NULL,
                           bool use_labels = true);

  /**
   * Determines a random edge. The two endpoints of the edge are passed
   * through.
   * @param u One endpoint of the random edge.
   * @param v The other endpoint of the random edge.
   */
  void getRandomEdge(int* u, int* v);

  /**
   * Swaps (w.h.p.) all edges at random, effectifely creating a new graph
   * with the same degree distribution but independent edge probabilities.
   * @return The graph with the swapped edges.
   */
  Graph randomSwap();

  /**
   * Counts the number of common neighbors of nodes u and v.
   * @param  u One vertex in the graph.
   * @param  v Another vertex in the graph.
   * @return   The number of common neighbors of u and v.
   */
  int commonNeighbors(int u, int v);

  /**
   * ignore_nodes indicates which nodes are indistinguishable from their
   * neighborhoods. ignore_nodes[i] is true if there is a node j in the
   * graph that has the exact same neighborhood as i, and ignore_nodes[j] =
   * false.
   * @param ignore_nodes The bool vector indicating whether node i should be
   *                     ignored or not.
   */
  void indistinguishableNodes(vector<bool>* ignore_nodes);

  /**
   * Performes a lexicographic breadth-first search on the graph.
   * @return The lexicographic ordering of the nodes.
   */
  vector<int> LexBFS();

  /**
   * Tests whether the graph is chordal, i.e. all cycles of length > 3
   * have a shortcut.
   * @return true if the graph is chordal, false if not.
   */
  bool isChordal();
};

ostream& operator<<(ostream& out, Graph& g);
back to top