Skip to content

Commit

Permalink
Network: Renamed get_n_edges() to n_edges(), to be consistent with n_…
Browse files Browse the repository at this point in the history
…agents(). Also extended it so it can, optionally, give the total number of edges in the network
  • Loading branch information
MSallermann committed Mar 8, 2024
1 parent 1dd9ab4 commit 2a12328
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 26 deletions.
9 changes: 7 additions & 2 deletions include/network.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once
#include <cstddef>
#include <optional>
#include <span>
#include <vector>

Expand All @@ -13,15 +14,19 @@ class Network

Network( std::vector<std::vector<size_t>> && neighbour_list, std::vector<std::vector<WeightT>> && weight_list );

// Gives the total number of nodes in the network
std::size_t n_agents() const;

/* Gives the number of edges going out from agent_idx.
If agent_idx is nullopt, give the total number of edges
*/
std::size_t n_edges( std::optional<std::size_t> agent_idx = std::nullopt ) const;

std::span<const size_t> get_neighbours( std::size_t agent_idx ) const;
std::span<size_t> get_neighbours( std::size_t agent_idx );
std::span<const WeightT> get_weights( std::size_t agent_idx ) const;
std::span<WeightT> get_weights( std::size_t agent_idx );

std::size_t get_n_edges( std::size_t agent_idx ) const;

void set_weights( std::size_t agent_idx, std::span<const WeightT> weights );

void set_neighbours_and_weights(
Expand Down
7 changes: 5 additions & 2 deletions include/network_generation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@

namespace Seldon
{
// Returns a unique pointer to a new network with n_connections per agent
std::unique_ptr<Network> generate_n_connections( size_t n_agents, int n_connections, std::mt19937 & gen );
/* Constructs a new network with n_connections per agent
If self_interaction=true, a connection of the agent with itself is included, which is *not* counted in n_connections
*/
std::unique_ptr<Network>
generate_n_connections( size_t n_agents, size_t n_connections, bool self_interaction, std::mt19937 & gen );
std::unique_ptr<Network> generate_fully_connected( size_t n_agents, Network::WeightT weight = 0.0 );
std::unique_ptr<Network> generate_fully_connected( size_t n_agents, std::mt19937 & gen );
std::unique_ptr<Network> generate_from_file( const std::string & file );
Expand Down
9 changes: 6 additions & 3 deletions src/models/ActivityDrivenModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ void Seldon::ActivityAgentModel::update_network_probabilistic()
{
// Implement the weight for the probability of agent `idx_agent` contacting agent `j`
// Not normalised since this is taken care of by the reservoir sampling
auto weight_callback = [idx_agent, this]( size_t j ) {
auto weight_callback = [idx_agent, this]( size_t j )
{
if( idx_agent == j ) // The agent does not contact itself
return 0.0;
return std::pow(
Expand Down Expand Up @@ -126,7 +127,8 @@ void Seldon::ActivityAgentModel::update_network_mean()
contact_prob_list[idx_agent] = weights; // set to zero
}

auto probability_helper = []( double omega, size_t m ) {
auto probability_helper = []( double omega, size_t m )
{
double p = 0;
for( size_t i = 1; i <= m; i++ )
p += ( std::pow( -omega, i + 1 ) + omega ) / ( omega + 1 );
Expand All @@ -137,7 +139,8 @@ void Seldon::ActivityAgentModel::update_network_mean()
{
// Implement the weight for the probability of agent `idx_agent` contacting agent `j`
// Not normalised since this is taken care of by the reservoir sampling
auto weight_callback = [idx_agent, this]( size_t j ) {
auto weight_callback = [idx_agent, this]( size_t j )
{
constexpr double tolerance = 1e-16;
auto opinion_diff = std::abs( this->agents[idx_agent].data.opinion - this->agents[j].data.opinion );
if( opinion_diff < tolerance )
Expand Down
20 changes: 15 additions & 5 deletions src/network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <fmt/format.h>
#include <algorithm>
#include <cstddef>
#include <numeric>
#include <stdexcept>

Seldon::Network::Network(
Expand All @@ -27,6 +28,20 @@ size_t Seldon::Network::n_agents() const
return neighbour_list.size();
}

std::size_t Seldon::Network::n_edges( std::optional<std::size_t> agent_idx ) const
{
if( agent_idx.has_value() )
{
return neighbour_list[agent_idx.value()].size();
}
else
{
return std::transform_reduce(
neighbour_list.cbegin(), neighbour_list.cend(), 0, std::plus{},
[]( const auto & neigh_list ) { return neigh_list.size(); } );
}
}

std::span<const size_t> Seldon::Network::get_neighbours( std::size_t agent_idx ) const
{
return std::span( neighbour_list[agent_idx].cbegin(), neighbour_list[agent_idx].cend() );
Expand Down Expand Up @@ -76,11 +91,6 @@ std::span<Seldon::Network::WeightT> Seldon::Network::get_weights( std::size_t ag
return std::span<Seldon::Network::WeightT>( weight_list[agent_idx].begin(), weight_list[agent_idx].end() );
}

std::size_t Seldon::Network::get_n_edges( std::size_t agent_idx ) const
{
return neighbour_list[agent_idx].size();
}

void Seldon::Network::set_weights( std::size_t agent_idx, std::span<const Seldon::Network::WeightT> weights )
{
if( neighbour_list[agent_idx].size() != weights.size() )
Expand Down
20 changes: 11 additions & 9 deletions src/network_generation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include <util/misc.hpp>

std::unique_ptr<Seldon::Network>
Seldon::generate_n_connections( size_t n_agents, int n_connections, std::mt19937 & gen )
Seldon::generate_n_connections( size_t n_agents, size_t n_connections, bool self_interaction, std::mt19937 & gen )
{
using WeightT = Network::WeightT;

Expand All @@ -34,7 +34,7 @@ Seldon::generate_n_connections( size_t n_agents, int n_connections, std::mt19937
incoming_neighbour_weights.clear();

// Get the vector of sorted adjacencies, excluding i (include i later)
// TODO: option for making the n_conections variable
// TODO: option for making the n_connections variable
Seldon::draw_unique_k_from_n( i_agent, n_connections, n_agents, incoming_neighbour_buffer, gen );

incoming_neighbour_weights.resize( incoming_neighbour_buffer.size() );
Expand All @@ -44,13 +44,15 @@ Seldon::generate_n_connections( size_t n_agents, int n_connections, std::mt19937
outgoing_norm_weight += incoming_neighbour_weights[j];
}

// Put the self-interaction as the last entry
auto self_interaction_weight = dis( gen );
outgoing_norm_weight += self_interaction_weight;

// outgoing_norm_weights += self_interaction_weight;
incoming_neighbour_buffer.push_back( i_agent ); // Add the agent itself
incoming_neighbour_weights.push_back( self_interaction_weight );
if( self_interaction )
{
// Put the self-interaction as the last entry
auto self_interaction_weight = dis( gen );
outgoing_norm_weight += self_interaction_weight;
// outgoing_norm_weights += self_interaction_weight;
incoming_neighbour_buffer.push_back( i_agent ); // Add the agent itself
incoming_neighbour_weights.push_back( self_interaction_weight );
}

// ---------
// Normalize the weights so that the row sums to 1
Expand Down
2 changes: 1 addition & 1 deletion src/simulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ Seldon::Simulation::Simulation(
}
else
{
network = generate_n_connections( n_agents, n_connections, gen );
network = generate_n_connections( n_agents, n_connections, true, gen );
}
}

Expand Down
11 changes: 7 additions & 4 deletions test/test_network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ TEST_CASE( "Testing the network class" )
using namespace Seldon;

// Generate some network
const int n_agents = 20;
const int n_connections = 10;
const size_t n_agents = 20;
const size_t n_connections = 10;
std::mt19937 gen( 0 );
auto network = generate_n_connections( n_agents, n_connections, gen );
auto network = generate_n_connections( n_agents, n_connections, false, gen );

// Does n_agents work?
REQUIRE( network->n_agents() == n_agents );
// Does n_edges work?
REQUIRE( network->n_edges() == n_agents * n_connections );

// Check that the function for setting neighbours and a single weight work
// Agent 3
Expand All @@ -30,11 +32,12 @@ TEST_CASE( "Testing the network class" )

SECTION( "Checking that set_weight, get_neighbour work" )
{

weight = { 0.25, 0.55 };
network->set_weights( 3, weight );
auto buffer_w_get = network->get_weights( 3 );
REQUIRE_THAT( weight, Catch::Matchers::UnorderedRangeEquals( buffer_w_get ) );
REQUIRE( network->get_n_edges( 3 ) == 2 );
REQUIRE( network->n_edges( 3 ) == 2 );

size_t & n = network->get_neighbours( 3 )[0];
REQUIRE( n == neigh[0] );
Expand Down

0 comments on commit 2a12328

Please sign in to comment.