Skip to content

Commit

Permalink
Moved generate_agents_from_file out of model and into its own function
Browse files Browse the repository at this point in the history
  • Loading branch information
MSallermann committed Mar 13, 2024
1 parent 5143d58 commit d9a0595
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 67 deletions.
50 changes: 50 additions & 0 deletions include/agent_generation.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#pragma once
#include "util/misc.hpp"
#include <cstddef>
#include <vector>

namespace Seldon::Agents
{

template<typename AgentT>
std::vector<AgentT> generate_from_file( const std::string & file )
{
std::vector<AgentT> agents{};

std::string file_contents = get_file_contents( file );
bool finished = false;
size_t start_of_line = 0;

while( !finished )
{
// Find the end of the current line
auto end_of_line = file_contents.find( '\n', start_of_line );
if( end_of_line == std::string::npos )
{
finished = true;
}
// Get the current line as a substring
auto line = file_contents.substr( start_of_line, end_of_line - start_of_line );
start_of_line = end_of_line + 1;
// TODO: check if empty or comment
if( line.empty() )
{
break;
}
if( line[0] == '#' )
{
continue;
}

agents.push_back( AgentT() );

// First column is the index of the agent
auto end_of_first_column = line.find( ',', 0 );
auto opinion_substring = line.substr( end_of_first_column + 1, end_of_line );
agents.back().from_string( opinion_substring );
}

return agents;
}

} // namespace Seldon::Agents
39 changes: 0 additions & 39 deletions include/model.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#pragma once
#include "model_base.hpp"
#include "util/misc.hpp"
#include <optional>

namespace Seldon
Expand All @@ -19,44 +18,6 @@ class Model : public ModelBase
Model( size_t n_agents ) : agents( std::vector<AgentT>( int( n_agents ), AgentT() ) ) {}
Model( std::vector<AgentT> && agents ) : agents( agents ) {}

void agents_from_file( const std::string & file ) override
{
agents.clear();

std::string file_contents = get_file_contents( file );
bool finished = false;
size_t start_of_line = 0;

while( !finished )
{
// Find the end of the current line
auto end_of_line = file_contents.find( '\n', start_of_line );
if( end_of_line == std::string::npos )
{
finished = true;
}
// Get the current line as a substring
auto line = file_contents.substr( start_of_line, end_of_line - start_of_line );
start_of_line = end_of_line + 1;
// TODO: check if empty or comment
if( line.empty() )
{
break;
}
if( line[0] == '#' )
{
continue;
}

agents.push_back( AgentT() );

// First column is the index of the agent
auto end_of_first_column = line.find( ',', 0 );
auto opinion_substring = line.substr( end_of_first_column + 1, end_of_line );
agents.back().from_string( opinion_substring );
}
}

void iteration() override
{
n_iterations++;
Expand Down
7 changes: 3 additions & 4 deletions include/model_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@ class ModelBase
return dynamic_cast<AgentT *>( get_agent( idx ) );
}

virtual void iteration() = 0;
virtual bool finished() = 0;
virtual void agents_from_file( const std::string & file ) = 0;
virtual ~ModelBase() = default;
virtual void iteration() = 0;
virtual bool finished() = 0;
virtual ~ModelBase() = default;
};

} // namespace Seldon
4 changes: 2 additions & 2 deletions include/network_generation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <memory>
#include <random>

namespace Seldon
namespace Seldon::NetworkGeneration
{
/* 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
Expand All @@ -14,4 +14,4 @@ generate_n_connections( size_t n_agents, size_t n_connections, bool self_interac
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 );
} // namespace Seldon
} // namespace Seldon::NetworkGeneration
20 changes: 12 additions & 8 deletions src/network_generation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@
#include <util/math.hpp>
#include <util/misc.hpp>

std::unique_ptr<Seldon::Network>
Seldon::generate_n_connections( size_t n_agents, size_t n_connections, bool self_interaction, std::mt19937 & gen )
namespace Seldon::NetworkGeneration
{

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

Expand All @@ -35,7 +38,7 @@ Seldon::generate_n_connections( size_t n_agents, size_t n_connections, bool self

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

incoming_neighbour_weights.resize( incoming_neighbour_buffer.size() );
for( size_t j = 0; j < incoming_neighbour_buffer.size(); ++j )
Expand Down Expand Up @@ -73,13 +76,13 @@ Seldon::generate_n_connections( size_t n_agents, size_t n_connections, bool self
std::move( neighbour_list ), std::move( weight_list ), Network::EdgeDirection::Incoming );
}

std::unique_ptr<Seldon::Network> Seldon::generate_from_file( const std::string & file )
std::unique_ptr<Network> generate_from_file( const std::string & file )
{
using WeightT = Network::WeightT;
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

std::string file_contents = Seldon::get_file_contents( file );
std::string file_contents = get_file_contents( file );

// bool finished = false;
size_t start_of_line = 0;
Expand Down Expand Up @@ -155,7 +158,7 @@ std::unique_ptr<Seldon::Network> Seldon::generate_from_file( const std::string &

// Create a fully connected network, with each weight initialized to the same user-defined
// value, weight. The neighbours include the agent itself as well.
std::unique_ptr<Seldon::Network> Seldon::generate_fully_connected( size_t n_agents, Network::WeightT weight )
std::unique_ptr<Network> generate_fully_connected( size_t n_agents, Network::WeightT weight )
{
using WeightT = Network::WeightT;

Expand Down Expand Up @@ -188,7 +191,7 @@ std::unique_ptr<Seldon::Network> Seldon::generate_fully_connected( size_t n_agen

// Create a fully connected network, with each incoming weight initialized to some value from a
// distribution, normalized to 1.
std::unique_ptr<Seldon::Network> Seldon::generate_fully_connected( size_t n_agents, std::mt19937 & gen )
std::unique_ptr<Network> generate_fully_connected( size_t n_agents, std::mt19937 & gen )
{
using WeightT = Network::WeightT;

Expand Down Expand Up @@ -236,4 +239,5 @@ std::unique_ptr<Seldon::Network> Seldon::generate_fully_connected( size_t n_agen

return std::make_unique<Network>(
std::move( neighbour_list ), std::move( weight_list ), Network::EdgeDirection::Incoming );
}
}
} // namespace Seldon::NetworkGeneration
29 changes: 19 additions & 10 deletions src/simulation.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "simulation.hpp"
#include "agent_generation.hpp"
#include "config_parser.hpp"
#include "models/ActivityDrivenModel.hpp"
#include "models/DeGroot.hpp"
Expand Down Expand Up @@ -31,7 +32,7 @@ Seldon::Simulation::Simulation(

if( file.has_value() )
{
network = generate_from_file( file.value() );
network = NetworkGeneration::generate_from_file( file.value() );
}
else
{
Expand All @@ -44,16 +45,16 @@ Seldon::Simulation::Simulation(
auto model_settings = std::get<Config::ActivityDrivenSettings>( options.model_settings );
if( model_settings.mean_weights )
{
network = generate_fully_connected( n_agents );
network = NetworkGeneration::generate_fully_connected( n_agents );
}
else
{
network = generate_n_connections( n_agents, n_connections, true, gen );
network = NetworkGeneration::generate_n_connections( n_agents, n_connections, true, gen );
}
}
else
{
network = generate_n_connections( n_agents, n_connections, true, gen );
network = NetworkGeneration::generate_n_connections( n_agents, n_connections, true, gen );
}
}

Expand All @@ -65,7 +66,13 @@ Seldon::Simulation::Simulation(
auto model_DeGroot = std::make_unique<DeGrootModel>( network->n_agents(), *network );
model_DeGroot->max_iterations = degroot_settings.max_iterations;
model_DeGroot->convergence_tol = degroot_settings.convergence_tol;
model = std::move( model_DeGroot );

if( cli_agent_file.has_value() )
{
model_DeGroot->agents = Agents::generate_from_file<DeGrootModel::AgentT>( cli_agent_file.value() );
}

model = std::move( model_DeGroot );
}
else if( options.model == Config::Model::ActivityDrivenModel )
{
Expand Down Expand Up @@ -93,12 +100,14 @@ Seldon::Simulation::Simulation(
model_activityDriven->bot_activity = activitydriven_settings.bot_activity;

model_activityDriven->get_agents_from_power_law();
model = std::move( model_activityDriven );
}

if( cli_agent_file.has_value() )
{
model->agents_from_file( cli_agent_file.value() );
if( cli_agent_file.has_value() )
{
model_activityDriven->agents
= Agents::generate_from_file<ActivityAgentModel::AgentT>( cli_agent_file.value() );
}

model = std::move( model_activityDriven );
}
}

Expand Down
4 changes: 2 additions & 2 deletions test/test_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ TEST_CASE( "Test reading in the network from a file", "[io_network]" )
auto proj_root_path = fs::current_path();
auto network_file = proj_root_path / fs::path( "test/res/network.txt" );

auto network = Seldon::generate_from_file( network_file );
auto network = Seldon::NetworkGeneration::generate_from_file( network_file );

REQUIRE( network->n_agents() == 3 );

std::vector<std::vector<int>> neighbours_expected = { { 2, 1 }, {}, { 1 } };
std::vector<std::vector<Network::WeightT>> weights_expected = { { 0.1, -0.2 }, {}, { 1.2 } };

for( int i = 0; i < network->n_agents(); i++ )
for( size_t i = 0; i < network->n_agents(); i++ )
{
fmt::print( "{}", i );
REQUIRE_THAT( neighbours_expected[i], Catch::Matchers::UnorderedRangeEquals( network->get_neighbours( i ) ) );
Expand Down
2 changes: 1 addition & 1 deletion test/test_network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ TEST_CASE( "Testing the network class" )
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, false, gen );
auto network = NetworkGeneration::generate_n_connections( n_agents, n_connections, false, gen );

// Does n_agents work?
REQUIRE( network->n_agents() == n_agents );
Expand Down
2 changes: 1 addition & 1 deletion test/test_network_generation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ TEST_CASE( "Testing the network generation functions" )
{
WeightT weight = 0.25;
std::vector<WeightT> weights{ weight, weight, weight }; // Weights to set to
auto network = generate_fully_connected( n_agents, weight );
auto network = NetworkGeneration::generate_fully_connected( n_agents, weight );
// Make sure that the network has been generated correctly
REQUIRE( network->n_agents() == n_agents ); // There should be n_agents in the new network

Expand Down

0 comments on commit d9a0595

Please sign in to comment.