void one_way_ring::connect(const vertices_size_type &n) { // Store frequently-used variables. const vertices_size_type t_size = get_number_of_vertices(); pagmo_assert(t_size != 0); switch (t_size) { case 1: { // If the topology was empty, just update the id of the first element. m_first = n; break; } case 2: { pagmo_assert(n != m_first); // Add connections to the only existing element. add_edge(m_first,n); add_edge(n,m_first); break; } default: { // The current last must be connected to the new one. remove_edge(m_last,m_first); add_edge(m_last,n); add_edge(n,m_first); } } // Update the id of the last island. m_last = n; }
/** * Calculate and return the average path length of the underlying graph representation using Johnson's all pairs shortest paths * algorithm. All edges are given equal weight 1. If a node is unconnected, its distance from any other node will be the highest * value representable by the C++ int type. The average path length is calculated as the mean value of the shortest paths between * all pairs of vertices. * * @return the average path length for the topology. * * @see http://en.wikipedia.org/wiki/Johnson's_algorithm * @see http://www.boost.org/doc/libs/release/libs/graph/doc/johnson_all_pairs_shortest.html */ double base::get_average_shortest_path_length() const { // Output matrix. std::vector<std::vector<int> > D(boost::numeric_cast<std::vector<std::vector<int> >::size_type>(get_number_of_vertices()), std::vector<int>(boost::numeric_cast<std::vector<int>::size_type>(get_number_of_vertices()))); boost::johnson_all_pairs_shortest_paths(m_graph,D); double retval = 0; for (std::vector<std::vector<int> >::size_type i = 0; i < D.size(); ++i) { for (std::vector<int>::size_type j = 0; j < D[i].size(); ++j) { retval += D[i][j]; } } if (get_number_of_vertices() < 2) { return 0; } else { return retval / (static_cast<double>(get_number_of_vertices()) * (get_number_of_vertices() - 1)); } }
/** * Will return a formatted string containing: * - the output of get_name(), * - the number of vertices, * - the output of human_readable_extra(). * * @return string containing terse human readable representation of the topology. */ std::string base::human_readable_terse() const { std::ostringstream s; s << "Topology type: " << get_name() << '\n'; s << "\tNumber of vertices: " << get_number_of_vertices() << '\n'; s << "\tNumber of edges: " << get_number_of_edges() << '\n'; s << human_readable_extra() << '\n'; return s.str(); }
void rim::connect(const vertices_size_type &) { // Store frequently-used variables. const vertices_size_type t_size = get_number_of_vertices(); pagmo_assert(t_size != 0); switch (t_size) { case 1: { // If the topology was empty, do not do anything. break; } case 2: { add_edge(0,1); add_edge(1,0); break; } case 3: { // Add edge to the center. add_edge(0,2); add_edge(2,0); // Add 1-2 connection. add_edge(1,2); add_edge(2,1); break; } case 4: { // Add edge to the center. add_edge(0,3); add_edge(3,0); // Add 1-3 and 3-2 connections. add_edge(1,3); add_edge(3,1); add_edge(2,3); add_edge(3,2); break; } default: { // Add edge to the center. add_edge(0,t_size - 1); add_edge(t_size - 1,0); // Remove connection (previous last)-first. remove_edge(t_size - 2,1); remove_edge(1,t_size - 2); // Add connection (previous last)-(new last). add_edge(t_size - 2,t_size - 1); add_edge(t_size - 1,t_size - 2); // Add connection (new last)-(first). add_edge(t_size - 1,1); add_edge(1,t_size - 1); } } }
void clustered_ba::connect(const vertices_size_type &idx) { pagmo_assert(get_number_of_vertices() > 0); const vertices_size_type prev_size = get_number_of_vertices() - 1; if (prev_size < m_m0) { // If we had not built the initial m0 nodes, do it. // We want to connect the newcomer island with high probability, and make sure that // at least one connection exists (otherwise the island stays isolated). // NOTE: is it worth to make it a user-tunable parameter? const double prob = 0.0; // Flag indicating if at least 1 connection was added. bool connection_added = false; // Main loop. for (std::pair<v_iterator,v_iterator> vertices = get_vertices(); vertices.first != vertices.second; ++vertices.first) { // Do not consider the new vertex itself. if (*vertices.first != idx) { if (m_drng() < prob) { connection_added = true; // Add the connections add_edge(*vertices.first,idx); add_edge(idx,*vertices.first); } } } // If no connections were established and this is not the first island being inserted, // establish at least one connection with a random island other than n. if ((!connection_added) && (prev_size != 0)) { // Get a random vertex index between 0 and n_vertices - 1. Keep on repeating the procedure if by // chance we end up on idx again. boost::uniform_int<vertices_size_type> uni_int(0,get_number_of_vertices() - 1); vertices_size_type rnd; do { rnd = uni_int(m_urng); } while (rnd == idx); // Add connections to the random vertex. add_edge(rnd,idx); add_edge(idx,rnd); } } else { // Now we need to add j edges, choosing the nodes with a probability // proportional to their number of connections. We keep track of the // connection established in order to avoid connecting twice to the same // node. // j is a random integer in the range 1 to m. boost::uniform_int<edges_size_type> uni_int2(1,m_m); std::size_t i = 0; std::size_t j = uni_int2(m_urng); std::pair<v_iterator,v_iterator> vertices; std::pair<a_iterator,a_iterator> adj_vertices; while (i < j) { // Let's find the current total number of edges. const edges_size_type n_edges = get_number_of_edges(); pagmo_assert(n_edges > 0); boost::uniform_int<edges_size_type> uni_int(0,n_edges - 1 - i); // Here we choose a random number between 0 and n_edges - 1 - i. const edges_size_type rn = uni_int(m_urng); edges_size_type n = 0; // Iterate over all vertices and accumulate the number of edges for each of them. Stop when the accumulated number of edges is greater // than rn. This is equivalent to giving a chance of connection to vertex v directly proportional to the number of edges departing from v. // You can think of this process as selecting a random edge among all the existing edges and connecting to the vertex from which the // selected edge departs. vertices = get_vertices(); for (; vertices.first != vertices.second; ++vertices.first) { // Do not consider it_n. if (*vertices.first != idx) { adj_vertices = get_adjacent_vertices(*vertices.first); n += boost::numeric_cast<edges_size_type>(std::distance(adj_vertices.first,adj_vertices.second)); if (n > rn) { break; } } } pagmo_assert(vertices.first != vertices.second); // If the candidate was not already connected, then add it. if (!are_adjacent(idx,*vertices.first)) { // Connect to nodes that are already adjacent to idx with probability p. // This step increases clustering in the network. adj_vertices = get_adjacent_vertices(idx); for(;adj_vertices.first != adj_vertices.second; ++adj_vertices.first) { if(m_drng() < m_p && *adj_vertices.first != *vertices.first && !are_adjacent(*adj_vertices.first,*vertices.first)) { add_edge(*adj_vertices.first, *vertices.first); add_edge(*vertices.first, *adj_vertices.first); } } // Connect to idx add_edge(*vertices.first,idx); add_edge(idx,*vertices.first); ++i; } } } }
/** * This method will add a vertex and will then call connect() to establish the connections between the newly-added node * and the existing nodes in the graph. */ void base::push_back() { add_vertex(); connect(get_number_of_vertices() - 1); }