Skip to content

Commit

Permalink
Network: is now more explicit about incomging/outoging edges
Browse files Browse the repository at this point in the history
  • Loading branch information
MSallermann committed Mar 8, 2024
1 parent 2a12328 commit 9a5bd4f
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 30 deletions.
21 changes: 18 additions & 3 deletions include/network.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,24 @@ namespace Seldon
class Network
{
public:
enum class EdgeDirection
{
Incoming,
Outgoing
};

using WeightT = double;

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

// 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
/*
Gives the number of edges going out/coming in from/at 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;

Expand All @@ -27,6 +36,8 @@ class Network
std::span<const WeightT> get_weights( std::size_t agent_idx ) const;
std::span<WeightT> get_weights( std::size_t agent_idx );

std::vector<std::vector<size_t>> strongly_connected_components() const;

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

void set_neighbours_and_weights(
Expand All @@ -39,9 +50,13 @@ class Network

void transpose();

const EdgeDirection & direction() const;

private:
std::vector<std::vector<size_t>> neighbour_list; // Neighbour list for the connections
std::vector<std::vector<WeightT>> weight_list; // List for the interaction weights of each connection
EdgeDirection _direction;
void swap_direction();
};

} // namespace Seldon
2 changes: 2 additions & 0 deletions src/models/ActivityDrivenModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ void Seldon::ActivityAgentModel::get_agents_from_power_law()

void Seldon::ActivityAgentModel::update_network_probabilistic()
{
network = Network( {}, {}, Network::EdgeDirection::Outgoing );

std::uniform_real_distribution<> dis_activation( 0.0, 1.0 );
std::uniform_real_distribution<> dis_reciprocation( 0.0, 1.0 );
std::vector<size_t> contacted_agents{};
Expand Down
8 changes: 8 additions & 0 deletions src/models/DeGroot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
Seldon::DeGrootModel::DeGrootModel( int n_agents, Network & network )
: Model<AgentT>( n_agents ), network( network ), agents_current_copy( std::vector<AgentT>( n_agents ) )
{
// For a strongly connected network, the number of SCCs should be 1
// Print a warning if this is not true
auto n_components = network.strongly_connected_components().size();
if( n_components != 1 )
{
fmt::print( "WARNING: You have {} strongly connected components in your network!\n", n_components );
}

for( size_t i = 0; i < agents.size(); i++ )
{
agents[i].data = double( i ) / double( agents.size() );
Expand Down
58 changes: 36 additions & 22 deletions src/network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,10 @@
#include <stdexcept>

Seldon::Network::Network(
std::vector<std::vector<size_t>> && neighbour_list, std::vector<std::vector<WeightT>> && weight_list )
: neighbour_list( neighbour_list ), weight_list( weight_list )
std::vector<std::vector<size_t>> && neighbour_list, std::vector<std::vector<WeightT>> && weight_list,
EdgeDirection direction )
: neighbour_list( neighbour_list ), weight_list( weight_list ), _direction( direction )
{
// Now that we have the neighbour list (or adjacency list)
// Run Tarjan's algorithm for strongly connected components
auto tarjan_scc = TarjanConnectivityAlgo( neighbour_list );

// For a strongly connected network, the number of SCCs should be 1
// Print a warning if this is not true
if( tarjan_scc.scc_list.size() != 1 )
{
fmt::print(
"WARNING: You have {} strongly connected components in your network!\n", tarjan_scc.scc_list.size() );
}
}

size_t Seldon::Network::n_agents() const
Expand All @@ -42,6 +32,19 @@ std::size_t Seldon::Network::n_edges( std::optional<std::size_t> agent_idx ) con
}
}

const Seldon::Network::EdgeDirection & Seldon::Network::direction() const
{
return _direction;
}

std::vector<std::vector<size_t>> Seldon::Network::strongly_connected_components() const
{
// Now that we have the neighbour list (or adjacency list)
// Run Tarjan's algorithm for strongly connected components
auto tarjan_scc = TarjanConnectivityAlgo( neighbour_list );
return tarjan_scc.scc_list;
}

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 All @@ -65,11 +68,9 @@ void Seldon::Network::set_neighbours_and_weights(
std::span<const Seldon::Network::WeightT> buffer_weights )
{
if( buffer_neighbours.size() != buffer_weights.size() )
[[unlikely]]
{
throw std::runtime_error(
"Network::set_neighbours_and_weights: both buffers need to have the same length!" );
}
{
throw std::runtime_error( "Network::set_neighbours_and_weights: both buffers need to have the same length!" );
}

neighbour_list[agent_idx].assign( buffer_neighbours.begin(), buffer_neighbours.end() );
weight_list[agent_idx].assign( buffer_weights.begin(), buffer_weights.end() );
Expand All @@ -94,13 +95,25 @@ std::span<Seldon::Network::WeightT> Seldon::Network::get_weights( std::size_t ag
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() )
[[unlikely]]
{
throw std::runtime_error( "Network::set_weights: tried to set weights of the wrong size!" );
}
{
throw std::runtime_error( "Network::set_weights: tried to set weights of the wrong size!" );
}
weight_list[agent_idx].assign( weights.begin(), weights.end() );
}

void Seldon::Network::swap_direction()
{
// Swap the edge direction
if( direction() == EdgeDirection::Incoming )
{
_direction = EdgeDirection::Outgoing;
}
else
{
_direction = EdgeDirection::Incoming;
}
}

void Seldon::Network::transpose()
{
std::vector<std::vector<size_t>> neighbour_list_transpose( n_agents(), std::vector<size_t>( 0 ) );
Expand All @@ -117,6 +130,7 @@ void Seldon::Network::transpose()
}
}

swap_direction();
neighbour_list = std::move( neighbour_list_transpose );
weight_list = std::move( weight_list_transpose );
}
12 changes: 8 additions & 4 deletions src/network_generation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ Seldon::generate_n_connections( size_t n_agents, size_t n_connections, bool self

} // end of loop through n_agents

return std::make_unique<Network>( std::move( neighbour_list ), std::move( weight_list ) );
return std::make_unique<Network>(
std::move( neighbour_list ), std::move( weight_list ), Network::EdgeDirection::Incoming );
}

std::unique_ptr<Seldon::Network> Seldon::generate_from_file( const std::string & file )
Expand Down Expand Up @@ -148,7 +149,8 @@ std::unique_ptr<Seldon::Network> Seldon::generate_from_file( const std::string &
}
}

return std::make_unique<Network>( std::move( neighbour_list ), std::move( weight_list ) );
return std::make_unique<Network>(
std::move( neighbour_list ), std::move( weight_list ), Network::EdgeDirection::Incoming );
}

// Create a fully connected network, with each weight initialized to the same user-defined
Expand Down Expand Up @@ -180,7 +182,8 @@ std::unique_ptr<Seldon::Network> Seldon::generate_fully_connected( size_t n_agen

} // end of loop through n_agents

return std::make_unique<Network>( std::move( neighbour_list ), std::move( weight_list ) );
return std::make_unique<Network>(
std::move( neighbour_list ), std::move( weight_list ), Network::EdgeDirection::Incoming );
}

// Create a fully connected network, with each incoming weight initialized to some value from a
Expand Down Expand Up @@ -231,5 +234,6 @@ std::unique_ptr<Seldon::Network> Seldon::generate_fully_connected( size_t n_agen

} // end of loop through n_agents

return std::make_unique<Network>( std::move( neighbour_list ), std::move( weight_list ) );
return std::make_unique<Network>(
std::move( neighbour_list ), std::move( weight_list ), Network::EdgeDirection::Incoming );
}
2 changes: 1 addition & 1 deletion test/test_deGroot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ TEST_CASE( "Test the DeGroot Model Symmetric", "[DeGroot]" )
{ 0.2, 0.8 },
};

auto network = Network( std::move( neighbour_list ), std::move( weight_list ) );
auto network = Network( std::move( neighbour_list ), std::move( weight_list ), Network::EdgeDirection::Incoming );
auto model = DeGrootModel( n_agents, network );

model.convergence_tol = 1e-6;
Expand Down

0 comments on commit 9a5bd4f

Please sign in to comment.