Program Listing for File ThreadWorld.hpp¶
↰ Return to documentation for file (include/dish2/world/ThreadWorld.hpp)
#pragma once
#ifndef DISH2_WORLD_THREADWORLD_HPP_INCLUDE
#define DISH2_WORLD_THREADWORLD_HPP_INCLUDE
#include <set>
#include "../../../third-party/conduit/include/netuit/mesh/Mesh.hpp"
#include "../../../third-party/conduit/include/netuit/mesh/MeshNode.hpp"
#include "../../../third-party/conduit/include/uitsl/algorithm/for_each.hpp"
#include "../../../third-party/conduit/include/uitsl/mpi/comm_utils.hpp"
#include "../../../third-party/Empirical/include/emp/tools/string_utils.hpp"
#include "../cell/cardinal_iterators/PushNodeOutputWrapper.hpp"
#include "../cell/Cell.hpp"
#include "../config/cfg.hpp"
#include "../config/thread_idx.hpp"
#include "../debug/LogScope.hpp"
#include "../debug/PopulationExtinctionException.hpp"
#include "../introspection/make_causes_of_death_string_histogram.hpp"
#include "../push/DistanceToGraphCenterCellState.hpp"
#include "../push/DistanceToGraphCenterMessage.hpp"
namespace dish2 {
template<typename Spec>
struct ThreadWorld {
using spec_t = Spec;
using this_t = ThreadWorld<Spec>;
using population_t = emp::vector< dish2::Cell<Spec> >;
population_t population;
using genome_mesh_spec_t = typename Spec::genome_mesh_spec_t;
using genome_submesh_t
= typename netuit::Mesh<genome_mesh_spec_t>::submesh_t;
using genome_node_t = netuit::MeshNode<genome_mesh_spec_t>;
using message_mesh_spec_t = typename Spec::message_mesh_spec_t;
using message_submesh_t
= typename netuit::Mesh<message_mesh_spec_t>::submesh_t;
using message_node_t = netuit::MeshNode<message_mesh_spec_t>;
using push_mesh_spec_t = typename Spec::push_mesh_spec_t;
using push_submesh_t
= typename netuit::Mesh<push_mesh_spec_t>::submesh_t;
using push_node_t = netuit::MeshNode<push_mesh_spec_t>;
using quorum_mesh_spec_t = typename Spec::quorum_mesh_spec_t;
using quorum_submesh_t
= typename netuit::Mesh<quorum_mesh_spec_t>::submesh_t;
using quorum_node_t = netuit::MeshNode<quorum_mesh_spec_t>;
using resource_mesh_spec_t = typename Spec::resource_mesh_spec_t;
using resource_submesh_t
= typename netuit::Mesh<resource_mesh_spec_t>::submesh_t;
using resource_node_t = netuit::MeshNode<resource_mesh_spec_t>;
using state_mesh_spec_t = typename Spec::state_mesh_spec_t;
using state_submesh_t
= typename netuit::Mesh<state_mesh_spec_t>::submesh_t;
using state_node_t = netuit::MeshNode<state_mesh_spec_t>;
explicit ThreadWorld(
const genome_submesh_t& genome_submesh,
const message_submesh_t& message_submesh,
const push_submesh_t& push_submesh,
const quorum_submesh_t& quorum_submesh,
const resource_submesh_t& resource_submesh,
const state_submesh_t& state_submesh
) {
emp_assert(( 1 == std::set<size_t>{
genome_submesh.size(),
message_submesh.size(),
push_submesh.size(),
quorum_submesh.size(),
resource_submesh.size(),
state_submesh.size()
}.size() ));
for (size_t i{}; i < message_submesh.size(); ++i) population.emplace_back(
genome_submesh[i],
message_submesh[i],
push_submesh[i],
quorum_submesh[i],
resource_submesh[i],
state_submesh[i]
);
// kick off distributed distance to center computation
if ( uitsl::is_root() && dish2::thread_idx == 0 && population.size() ) {
auto& target = population.front();
auto& center_dist = std::get<dish2::DistanceToGraphCenterCellState>(
target.cell_push_state
);
center_dist.my_distance = 0;
const dish2::DistanceToGraphCenterMessage message{ 0 };
std::for_each(
target.template begin< dish2::PushNodeOutputWrapper<spec_t> >(),
target.template end< dish2::PushNodeOutputWrapper<spec_t> >(),
[&message]( auto& output ){ output.Put( message ); }
);
}
}
size_t update{};
template<bool THROW_ON_EXTINCTION=true>
void Update() {
using thread_local_service_manager_t
= typename Spec::thread_local_service_manager_t;
thread_local_service_manager_t::template Run<this_t>( *this, update );
if constexpr ( THROW_ON_EXTINCTION ) {
if ( dish2::cfg.THROW_ON_EXTINCTION() && std::none_of(
std::begin( population ), std::end( population ),
[]( const auto& cell ){ return cell.IsAlive(); }
) ) throw dish2::PopulationExtinctionException{
update,
population.size(),
dish2::make_causes_of_death_string_histogram< ThreadWorld >( *this )
};
}
++update;
}
size_t GetUpdate() const { return update; }
size_t GetSize() const { return population.size(); }
const dish2::Cell<Spec>& GetCell(const size_t idx) const {
return population[idx];
}
};
} // namespace dish2
#endif // #ifndef DISH2_WORLD_THREADWORLD_HPP_INCLUDE