Skip to content

Commit

Permalink
Network: refactored the transpose function and introduces a new toggl…
Browse files Browse the repository at this point in the history
…e_direction function
  • Loading branch information
MSallermann committed Mar 8, 2024
1 parent 9a5bd4f commit e95c8cc
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 22 deletions.
62 changes: 49 additions & 13 deletions include/network.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,41 +22,77 @@ class 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 total number of nodes in the network
*/
[[nodiscard]] std::size_t n_agents() const;

/*
Gives the number of edges going out/coming in at agent_idx, depending on the value of direction().
If agent_idx is nullopt, gives the total number of edges
*/
[[nodiscard]] std::size_t n_edges( std::optional<std::size_t> agent_idx = std::nullopt ) const;

/*
Returns the current directionality of the adjacency list. That is if incoming or outgoing edges are stored.
*/
[[nodiscard]] const EdgeDirection & direction() const;

/*
Gives the number of edges going out/coming in from/at agent_idx.
If agent_idx is nullopt, give the total number of edges
Gives the strongly connected components in the graph
*/
std::size_t n_edges( std::optional<std::size_t> agent_idx = std::nullopt ) const;
[[nodiscard]] std::vector<std::vector<size_t>> strongly_connected_components() 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 );
/*
Gives a view into the neighbour indices going out/coming in at agent_idx
*/
[[nodiscard]] std::span<const size_t> get_neighbours( std::size_t agent_idx ) const;
[[nodiscard]] std::span<size_t> get_neighbours( std::size_t agent_idx );

std::vector<std::vector<size_t>> strongly_connected_components() const;
/*
Gives a view into the edge weights going out/coming in at agent_idx
*/
[[nodiscard]] std::span<const WeightT> get_weights( std::size_t agent_idx ) const;
[[nodiscard]] std::span<WeightT> get_weights( std::size_t agent_idx );

/*
Gives a view into the edge weights going out/coming in at agent_idx
*/
void set_weights( std::size_t agent_idx, std::span<const WeightT> weights );

/*
Sets the neighbour indices and sets the weight to a constant value at agent_idx
*/
void set_neighbours_and_weights(
std::size_t agent_idx, std::span<const size_t> buffer_neighbours, const WeightT & weight );

/*
Sets the neighbour indices and weights at agent_idx
*/
void set_neighbours_and_weights(
std::size_t agent_idx, std::span<const size_t> buffer_neighbours, std::span<const WeightT> buffer_weights );

void push_back_neighbour_and_weight( size_t i, size_t j, WeightT w );
/*
Adds an edge between agent_idx_i and agent_idx_j with weight w
*/
void push_back_neighbour_and_weight( size_t agent_idx_i, size_t agent_idx_j, WeightT w );

/*
Switches the directionality and *changes the topolgy*.
*Note*: This is cheap and changes the effective network topology by simply changing the directionality flag.
*/
void transpose();

const EdgeDirection & direction() const;
/*
Switches the directionality *without changing the topolgy*. *Note*: This is expensive and toggles the
directionality, while compensating by changing the adjacency list.
*/
void toggle_direction();

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
11 changes: 4 additions & 7 deletions src/models/ActivityDrivenModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ 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 @@ -114,7 +113,7 @@ void Seldon::ActivityAgentModel::update_network_probabilistic()
}
}

network.transpose(); // transpose the network, so that we have incoming edges
network.toggle_direction(); // switch direction, so that we have incoming edges
}

void Seldon::ActivityAgentModel::update_network_mean()
Expand All @@ -129,8 +128,7 @@ 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 @@ -141,8 +139,7 @@ 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
4 changes: 2 additions & 2 deletions src/network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ void Seldon::Network::set_weights( std::size_t agent_idx, std::span<const Seldon
weight_list[agent_idx].assign( weights.begin(), weights.end() );
}

void Seldon::Network::swap_direction()
void Seldon::Network::toggle_direction()
{
// Swap the edge direction
if( direction() == EdgeDirection::Incoming )
Expand Down Expand Up @@ -130,7 +130,7 @@ void Seldon::Network::transpose()
}
}

swap_direction();
toggle_direction();
neighbour_list = std::move( neighbour_list_transpose );
weight_list = std::move( weight_list_transpose );
}
5 changes: 5 additions & 0 deletions test/test_network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,12 @@ TEST_CASE( "Testing the network class" )
}
}

auto old_direction = network->direction();
network->transpose();
auto new_direction = network->direction();

// Direction should have changed as well
REQUIRE( old_direction != new_direction);

// Now we go over the transposed network and try to re-identify all edges
for( size_t i_agent = 0; i_agent < network->n_agents(); i_agent++ )
Expand Down

0 comments on commit e95c8cc

Please sign in to comment.