/* * * gengraph - generation of random simple connected graphs with prescribed * degree sequence * * Copyright (C) 2006 Fabien Viger * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef GRAPH_MOLLOY_OPT_H #define GRAPH_MOLLOY_OPT_H #include "gengraph_definitions.h" #include "gengraph_degree_sequence.h" #include "gengraph_qsort.h" #include #include "gengraph_random.h" namespace gengraph { // This class handles graphs with a constant degree sequence. class graph_molloy_opt { private: // Random generator KW_RNG::RNG rng; // Number of vertices int n; //Number of arcs ( = #edges * 2 ) int a; // The degree sequence of the graph int *deg; // The array containing all links int *links; // The array containing pointers to adjacency list of every vertices int **neigh; // Allocate memory according to degree_sequence (for constructor use only!!) void alloc(degree_sequence &); // Compute #edges inline void refresh_nbarcs() { a = 0; for (int* d = deg + n; d != deg; ) { a += *(--d); } } // Build neigh with deg and links void compute_neigh(); // Swap edges. The swap MUST be valid !!! inline void swap_edges(int from1, int to1, int from2, int to2) { fast_rpl(neigh[from1], to1, to2); fast_rpl(neigh[from2], to2, to1); fast_rpl(neigh[to1], from1, from2); fast_rpl(neigh[to2], from2, from1); } // Swap edges only if they are simple. return false if unsuccessful. bool swap_edges_simple(int, int, int, int); // Test if vertex is in an isolated component of size dmax. void depth_isolated(int v, long &calls, int &left_to_explore, int dmax, int * &Kbuff, bool *visited); // breadth-first search. Store the distance (modulo 3) in dist[]. Returns eplorated component size. int width_search(unsigned char *dist, int *buff, int v0 = 0, int toclear = -1); // depth-first search. int depth_search(bool *visited, int *buff, int v0 = 0); // breadth-first search that count the number of shortest paths going from src to each vertex int breadth_path_search(int src, int *buff, double *paths, unsigned char *dist); // Used by traceroute_sample() ONLY void add_traceroute_edge(int, int, int*, double** red = NULL, double t = 1.0); // Used by traceroute() and betweenness(). if newdeg[]=NULL, do not discover edges. // breadth_path_search() must have been called to give the corresponding buff[],dist[],paths[] and nb_vertices void explore_usp(double *target, int nb_vertices, int *buff, double *paths, unsigned char *dist, int *newdeg = NULL, double **edge_redudancy = NULL); void explore_asp(double *target, int nb_vertices, int *buff, double *paths, unsigned char *dist, int *newdeg = NULL, double **edge_redudancy = NULL); void explore_rsp(double *target, int nb_vertices, int *buff, double *paths, unsigned char *dist, int *newdeg = NULL, double **edge_redudancy = NULL); // Return component indexes where vertices belong to, starting from 0, // sorted by size (biggest component has index 0) int *components(int *comp = NULL); // pick k random vertices of degree > 0. int *pick_random_vertices(int &k, int *output = NULL, int nb_v = -1, int *among = NULL); public: // neigh[] inline int** neighbors() { return neigh; }; // deg[] inline int* degrees() { return deg; }; //adjacency list of v inline int* operator[](const int v) { return neigh[v]; }; //degree of v inline int degree(const int v) { return deg[v]; }; //compare adjacency lists inline int compare(const int v, const int w) { return deg[v] == deg[w] ? lex_comp(neigh[v], neigh[w], deg[v]) : (deg[v] > deg[w] ? -1 : 1); }; // Detach deg[] and neigh[] void detach(); // Destroy deg and links ~graph_molloy_opt(); // Create graph from file (stdin not supported unless rewind() possible) graph_molloy_opt(FILE *f); // Allocate memory for the graph. Create deg and links. No edge is created. graph_molloy_opt(degree_sequence &); // Create graph from hard copy graph_molloy_opt(int *); // Create hard copy of graph int *hard_copy(); // Remove unused edges, updates neigh[], recreate links[] void clean(); // nb arcs inline int nbarcs() { return a; }; // last degree inline int last_degree() { return deg[n - 1]; }; // nb vertices inline int nbvertices() { return n; }; // nb vertices having degree > 0 inline int nbvertices_real() { int s = 0; for (int *d = deg + n; d-- != deg; ) if (*d) { s++; } return s; }; // return list of vertices with degree > 0. Compute #vertices, if not given. int *vertices_real(int &nb_v); // Keep only giant component void giant_comp(); // nb vertices in giant component int nbvertices_comp(); // nb arcs in giant component int nbarcs_comp(); // print graph in SUCC_LIST mode, in stdout void print(FILE *f = stdout, bool NOZERO = true); // Bind the graph avoiding multiple edges or self-edges (return false if fail) bool havelhakimi(); // Get the graph connected (return false if fail) bool make_connected(); // Test if graph is connected bool is_connected(); // Maximum degree int max_degree(); // breadth-first search. Store the distance (modulo 3) in dist[]. void breadth_search(int *dist, int v0 = 0, int* buff = NULL); // is edge ? inline bool is_edge(const int a, const int b) { if (deg[b] < deg[a]) { return (fast_search(neigh[b], deg[b], a) != NULL); } else { return (fast_search(neigh[a], deg[a], b) != NULL); } } // Backup graph [sizeof(int) bytes per edge] int* backup(int *here = NULL); // Restore from backup. Assume that degrees haven't changed void restore(int* back); // Resplace with hard backup. void replace(int* _hardbackup); // Backup degs of graph int* backup_degs(int *here = NULL); // Restore degs from neigh[]. Need last degree, though void restore_degs(int last_degree); // Restore degs[] from backup. Assume that links[] has only been permuted void restore_degs_only(int* backup_degs); // Restore degs[] and neigh[]. Assume that links[] has only been permuted void restore_degs_and_neigh(int* backup_degs); // WARNING : the following shuffle() algorithms are slow. // Use graph_molloy_hash::connected_shuffle() instead. // "Fab" Shuffle (Optimized heuristic of Gkantsidis algo.) long fab_connected_shuffle(long); // "Optimized-Fab" Shuffle (Optimized heuristic of Gkantsidis algo, with isolated pairs) long opt_fab_connected_shuffle(long); // Gkantsidis Shuffle long gkantsidis_connected_shuffle(long); // Connected Shuffle long slow_connected_shuffle(long); // shortest paths where vertex is an extremity double *vertex_betweenness(int mode, bool trivial_path = false); // Sample the graph with traceroute-like exploration from src[] to dst[]. // if dst[]=NULL, pick nb_dst new random destinations for each src double traceroute_sample(int mode, int nb_src, int *src, int nb_dst, int* dst, double *redudancy = NULL, double **edge_redudancy = NULL); // does one breadth-first search and returns the average_distance. double avg_dist(unsigned char *dist, int *buff, int v0, int &nb_vertices, int toclear = -1); // Number of edges needed to disconnect graph (one random instance) int disconnecting_edges(); // Compute vertex covering of the graph. Warning : this modifies degs[] void vertex_covering(); // Path sampling. Input is nb_dst[] and dst[]. nb_dst[v],dst[v] describe all paths (v,x) double path_sampling(int *nb_dst, int *dst = NULL, double *redudancies = NULL, double **edge_redudancy = NULL); // keep only core (tree parts are deleted). Returns number of removed vertices. int core(); // try to disconnect the graph by swapping edges (with isolation tests) int try_disconnect(int K, int max_tries = 10000000); // Eric & Cun-Hui estimator double rho(int mode, int nb_src, int *src, int nb_dst, int *dst = NULL); // sort adjacency lists void sort(); // sort the vertices according to their degrees (highest first) and to their adjacency lists (lexicographic) int* sort_vertices(int *buff = NULL); // count cycles passing through vertex v int cycles(int v); // remove vertex (i.e. remove all edges adjacent to vertex) void remove_vertex(int v); // pick k random vertices of degree > 0. If k \in [0,1[, k is understood as a density. int *pick_random_src(double k, int *nb = NULL, int* buff = NULL, int nb_v = -1, int* among = NULL); // pick k random vertices of degree > 0. If k \in [0,1], k is understood as a density. int *pick_random_dst(double k, int *nb = NULL, int* buff = NULL, int nb_v = -1, int* among = NULL); // For debug purposes : verify validity of the graph (symetry, simplicity) #define VERIFY_NORMAL 0 #define VERIFY_NONEIGH 1 #define VERIFY_NOARCS 2 bool verify(int mode = VERIFY_NORMAL); /*___________________________________________________________________________________ Not to use anymore : use graph_molloy_hash class instead public: // Shuffle. returns number of swaps done. void shuffle(long); // Connected Shuffle long connected_shuffle(long); // Get caracteristic K double eval_K(int quality = 100); // Get effective K double effective_K(int K, int quality = 10000); // Test window double window(int K, double ratio); // Try to shuffle n times. Return true if at the end, the graph was still connected. bool try_shuffle(int T, int K); //___________________________________________________________________________________ //*/ /*___________________________________________________________________________________ Not to use anymore : replaced by vertex_betweenness() 22/04/2005 // shortest paths where vertex is an extremity long long *vertex_betweenness_usp(bool trivial_path); // shortest paths where vertex is an extremity long long *vertex_betweenness_rsp(bool trivial_path); // same, but when multiple shortest path are possible, average the weights. double *vertex_betweenness_asp(bool trivial_path); //___________________________________________________________________________________ //*/ }; } // namespace gengraph #endif //GRAPH_MOLLOY_OPT_H