From 6daca16bc6e3e7f91184346ed774220c35095247 Mon Sep 17 00:00:00 2001 From: Moritz Sallermann Date: Mon, 18 Mar 2024 18:01:35 +0000 Subject: [PATCH] IO: Start to refactor agent to/from_string Created `agent_writer.hpp` to provide a more streamlined interface to agent parsing and output. Moved the `to_string` function out of agent Also changed the agent type of the DeGroot model, so that it contains the opinion as `agent.data.opinion`. Co-authored-by: Amrita Goswami --- include/agent.hpp | 5 ----- include/agent_writer.hpp | 20 ++++++++++++++++++ include/models/ActivityDrivenModel.hpp | 13 +++++++++--- include/models/DeGroot.hpp | 28 ++++++++++++++++++++++++-- include/util/io.hpp | 3 ++- src/models/DeGroot.cpp | 14 ++++++------- test/test_deGroot.cpp | 12 +++++------ 7 files changed, 71 insertions(+), 24 deletions(-) create mode 100644 include/agent_writer.hpp diff --git a/include/agent.hpp b/include/agent.hpp index bf200ef..aa17e88 100644 --- a/include/agent.hpp +++ b/include/agent.hpp @@ -17,11 +17,6 @@ class Agent virtual ~Agent() = default; void from_string( const std::string & str ); - - virtual std::string to_string() const - { - return fmt::format( "{:.16f}", data ); - } }; template<> diff --git a/include/agent_writer.hpp b/include/agent_writer.hpp new file mode 100644 index 0000000..330e980 --- /dev/null +++ b/include/agent_writer.hpp @@ -0,0 +1,20 @@ +#pragma once +#include + +namespace Seldon +{ + +template +std::string agent_to_string( const AgentT & agent ) +{ + static_assert( false, "Base implementation not valid" ); + return ""; +} + +template +std::string opinion_to_string( const AgentT & agent ) +{ + return fmt::format( "{}", agent.data.opinion ); +} + +} // namespace Seldon \ No newline at end of file diff --git a/include/models/ActivityDrivenModel.hpp b/include/models/ActivityDrivenModel.hpp index c642fa6..c39a437 100644 --- a/include/models/ActivityDrivenModel.hpp +++ b/include/models/ActivityDrivenModel.hpp @@ -1,6 +1,7 @@ #pragma once #include "agent.hpp" +#include "agent_writer.hpp" #include "model.hpp" #include "network.hpp" #include @@ -21,10 +22,16 @@ struct ActivityAgentData }; template<> -inline std::string Agent::to_string() const +inline std::string agent_to_string>( const Agent & agent ) { - return fmt::format( "{}, {}, {}", data.opinion, data.activity, data.reluctance ); -}; + return fmt::format( "{}, {}, {}", agent.data.opinion, agent.data.activity, agent.data.reluctance ); +} + +template<> +inline std::string opinion_to_string>( const Agent & agent ) +{ + return fmt::format( "{}", agent.data.opinion ); +} template<> inline void Agent::from_string( const std::string & str ) diff --git a/include/models/DeGroot.hpp b/include/models/DeGroot.hpp index b7a9f0a..23d1dac 100644 --- a/include/models/DeGroot.hpp +++ b/include/models/DeGroot.hpp @@ -1,5 +1,6 @@ #pragma once #include "agent.hpp" +#include "agent_writer.hpp" #include "model.hpp" #include "network.hpp" #include @@ -7,10 +8,33 @@ namespace Seldon { -class DeGrootModel : public Model> +struct DeGrootAgentData +{ + double opinion = 0; // x_i +}; + +template<> +inline std::string agent_to_string>( const Agent & agent ) +{ + return fmt::format( "{}", agent.data.opinion ); +} + +template<> +inline std::string opinion_to_string>( const Agent & agent ) +{ + return agent_to_string( agent ); +} + +template<> +inline void Agent::from_string( const std::string & str ) +{ + data.opinion = std::stod( str ); +}; + +class DeGrootModel : public Model> { public: - using AgentT = Agent; + using AgentT = Agent; using NetworkT = Network; double convergence_tol = 1e-12; diff --git a/include/util/io.hpp b/include/util/io.hpp index a7f135c..b38c794 100644 --- a/include/util/io.hpp +++ b/include/util/io.hpp @@ -1,4 +1,5 @@ #pragma once +#include "agent_writer.hpp" #include "fstream" #include "network.hpp" #include @@ -48,7 +49,7 @@ void opinions_to_file( const Network & network, const std::string & file fmt::print( fs, "# idx_agent, opinion[...]\n" ); for( size_t idx_agent = 0; idx_agent < n_agents; idx_agent++ ) { - std::string row = fmt::format( "{:>5}, {:>25}\n", idx_agent, network.agents[idx_agent].to_string() ); + std::string row = fmt::format( "{:>5}, {:>25}\n", idx_agent, agent_to_string( network.agents[idx_agent] ) ); fs << row; } fs.close(); diff --git a/src/models/DeGroot.cpp b/src/models/DeGroot.cpp index db4c5ad..eda534f 100644 --- a/src/models/DeGroot.cpp +++ b/src/models/DeGroot.cpp @@ -18,7 +18,7 @@ DeGrootModel::DeGrootModel( NetworkT & network ) for( size_t i = 0; i < network.agents.size(); i++ ) { - network.agents[i].data = double( i ) / double( network.agents.size() ); + network.agents[i].data.opinion = double( i ) / double( network.agents.size() ); } } @@ -31,14 +31,14 @@ void DeGrootModel::iteration() for( size_t i = 0; i < network.agents.size(); i++ ) { - auto neighbour_buffer = network.get_neighbours( i ); - auto weight_buffer = network.get_weights( i ); - agents_current_copy[i].data = 0.0; + auto neighbour_buffer = network.get_neighbours( i ); + auto weight_buffer = network.get_weights( i ); + agents_current_copy[i].data.opinion = 0.0; for( size_t j = 0; j < neighbour_buffer.size(); j++ ) { j_index = neighbour_buffer[j]; weight = weight_buffer[j]; - agents_current_copy[i].data += weight * network.agents[j_index].data; + agents_current_copy[i].data.opinion += weight * network.agents[j_index].data.opinion; } } @@ -46,8 +46,8 @@ void DeGrootModel::iteration() // Update the original agent opinions for( std::size_t i = 0; i < network.agents.size(); i++ ) { - max_opinion_diff - = std::max( max_opinion_diff, std::abs( network.agents[i].data - agents_current_copy[i].data ) ); + max_opinion_diff = std::max( + max_opinion_diff, std::abs( network.agents[i].data.opinion - agents_current_copy[i].data.opinion ) ); network.agents[i] = agents_current_copy[i]; } } diff --git a/test/test_deGroot.cpp b/test/test_deGroot.cpp index 8d78d0a..92f7987 100644 --- a/test/test_deGroot.cpp +++ b/test/test_deGroot.cpp @@ -26,10 +26,10 @@ TEST_CASE( "Test the DeGroot Model Symmetric", "[DeGroot]" ) auto network = Network( std::move( neighbour_list ), std::move( weight_list ), Network::EdgeDirection::Incoming ); auto model = DeGrootModel( network ); - model.convergence_tol = 1e-6; - model.max_iterations = 100; - network.agents[0].data = 0.0; - network.agents[1].data = 1.0; + model.convergence_tol = 1e-6; + model.max_iterations = 100; + network.agents[0].data.opinion = 0.0; + network.agents[1].data.opinion = 1.0; do { @@ -39,7 +39,7 @@ TEST_CASE( "Test the DeGroot Model Symmetric", "[DeGroot]" ) INFO( fmt::format( "N_iterations = {} (with convergence_tol {})\n", model.n_iterations(), model.convergence_tol ) ); for( size_t i = 0; i < n_agents; i++ ) { - INFO( fmt::format( "Opinion {} = {}\n", i, network.agents[i].data ) ); - REQUIRE_THAT( network.agents[i].data, WithinAbs( 0.5, model.convergence_tol * 10.0 ) ); + INFO( fmt::format( "Opinion {} = {}\n", i, network.agents[i].data.opinion ) ); + REQUIRE_THAT( network.agents[i].data.opinion, WithinAbs( 0.5, model.convergence_tol * 10.0 ) ); } } \ No newline at end of file