Skip to content

Commit

Permalink
upd: Optimizing Marriage in Simulation.
Browse files Browse the repository at this point in the history
  • Loading branch information
AsPJT committed May 27, 2024
1 parent 2ac37fb commit a79f60d
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 23 deletions.
30 changes: 29 additions & 1 deletion Library/PAX_MAHOROBA/StringViewer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -720,12 +720,40 @@ MurMur3::calcHash("en-US"), MurMur3::calcHash("ja-JP"), MurMur3::calcHash("zh-TW
(*one_font).drawTopRight(
((select_language.cgetKey() == MurMur3::calcHash("ja-JP")) ?
reinterpret_cast<const char*>(u8"渡来数") :
"Immigrants"),
"Total Immigrants"),
paxg::Vec2i(paxg::Window::width() - 140, debug_start_y + 120), paxg::Color(0, 0, 0));
(*one_font).drawTopRight(
std::to_string(simulator->emigrationSize()),
paxg::Vec2i(paxg::Window::width() - 40, debug_start_y + 120), paxg::Color(0, 0, 0));

(*one_font).drawTopRight(
((select_language.cgetKey() == MurMur3::calcHash("ja-JP")) ?
reinterpret_cast<const char*>(u8"処理時間") :
"All Processing Time [s]"),
paxg::Vec2i(paxg::Window::width() - 140, debug_start_y + 150), paxg::Color(0, 0, 0));
(*one_font).drawTopRight(
std::to_string(simulator->cgetProcessingTime()),
paxg::Vec2i(paxg::Window::width() - 40, debug_start_y + 150), paxg::Color(0, 0, 0));

(*one_font).drawTopRight(
((select_language.cgetKey() == MurMur3::calcHash("ja-JP")) ?
reinterpret_cast<const char*>(u8"処理時間") :
"Move Processing Time [s]"),
paxg::Vec2i(paxg::Window::width() - 140, debug_start_y + 180), paxg::Color(0, 0, 0));
(*one_font).drawTopRight(
std::to_string(simulator->cgetMoveProcessingTime()),
paxg::Vec2i(paxg::Window::width() - 40, debug_start_y + 180), paxg::Color(0, 0, 0));

(*one_font).drawTopRight(
((select_language.cgetKey() == MurMur3::calcHash("ja-JP")) ?
reinterpret_cast<const char*>(u8"処理時間") :
"Marriage Processing Time [s]"),
paxg::Vec2i(paxg::Window::width() - 140, debug_start_y + 210), paxg::Color(0, 0, 0));
(*one_font).drawTopRight(
std::to_string(simulator->cgetMarriageProcessingTime()),
paxg::Vec2i(paxg::Window::width() - 40, debug_start_y + 210), paxg::Color(0, 0, 0));


}
#endif
//debug_start_y += debug_move_y;
Expand Down
28 changes: 14 additions & 14 deletions Library/PAX_SAPIENTICA/Simulation/Settlement.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ namespace paxs {

/// @brief Delete the agent.
/// @brief エージェントを削除する
void deleteAgent(const std::uint_least64_t id_) noexcept {
void deleteAgent(const std::uint_least32_t id_) noexcept {
agents.erase(std::remove_if(agents.begin(), agents.end(), [id_](const Agent& agent) { return agent.getId() == id_; }), agents.end());
}

Expand All @@ -117,7 +117,7 @@ namespace paxs {
/// @brief Get the agent.
/// @brief エージェントを取得
/// @param id The agent's id. エージェントのID
Agent& getAgent(const std::uint_least64_t id_) noexcept {
Agent& getAgent(const std::uint_least32_t id_) noexcept {
auto it = std::find_if(agents.begin(), agents.end(), [id_](const Agent& agent) { return agent.getId() == id_; });
if (it == agents.end()) {
const std::string message = "Agent not found.";
Expand All @@ -129,7 +129,7 @@ namespace paxs {

/// @brief Get the agent.
/// @brief エージェントを取得
const Agent& cgetAgent(const std::uint_least64_t id_) const noexcept {
const Agent& cgetAgent(const std::uint_least32_t id_) const noexcept {
auto it = std::find_if(agents.begin(), agents.end(), [id_](const Agent& agent) { return agent.getId() == id_; });
if (it == agents.end()) {
const std::string message = "Agent not found.";
Expand All @@ -141,7 +141,7 @@ namespace paxs {

/// @brief Get the agent copy.
/// @brief エージェントを取得
Agent getAgentCopy(const std::uint_least64_t id_) const noexcept {
Agent getAgentCopy(const std::uint_least32_t id_) const noexcept {
auto it = std::find_if(agents.begin(), agents.end(), [id_](const Agent& agent) { return agent.getId() == id_; });
if (it == agents.end()) {
const std::string message = "Agent not found.";
Expand All @@ -161,7 +161,7 @@ namespace paxs {

/// @brief Marriage.
/// @brief 婚姻
void marriage(std::vector<Settlement> close_settlements, std::function<void(const std::uint64_t, const std::uint_least32_t, const Vector2)> delete_agent) noexcept {
void marriage(std::vector<Settlement*> close_settlements, std::function<void(const std::uint64_t, const std::uint_least32_t, const Vector2)> delete_agent) noexcept {
// 結婚の条件を満たすエージェントを取得
std::vector<std::size_t> marriageable_female_index;
for (std::size_t i = 0; i < agents.size(); ++i) {
Expand All @@ -182,7 +182,7 @@ namespace paxs {

// 近隣の集落を探す
for (std::size_t i = 0; i < close_settlements.size();) {
if (close_settlements[i].getPosition().distance(position) > SimulationConstants::getInstance()->marriage_search_range) {
if (close_settlements[i]->getPosition().distance(position) > SimulationConstants::getInstance()->marriage_search_range) {
close_settlements[i] = close_settlements.back(); // 同義 it = close_settlements.erase(it);
close_settlements.pop_back();
} else {
Expand All @@ -197,18 +197,18 @@ namespace paxs {
}

// idで自分を探す
auto it = std::find_if(close_settlements.begin(), close_settlements.end(), [this](const Settlement& settlement) { return settlement.getId() == id; });
auto it = std::find_if(close_settlements.begin(), close_settlements.end(), [this](const Settlement* const settlement) { return settlement->getId() == id; });
if (it == close_settlements.end()) {
PAXS_ERROR("Settlement not found.");
return;
}

// エージェントIDと集落IDのペアを作成
std::vector<std::pair<std::uint_least64_t, std::uint_least32_t>> male_settlement_pair;
std::vector<std::pair<std::uint_least32_t, std::uint_least32_t>> male_settlement_pair;
for (auto& close_settlement : close_settlements) {
for (auto& agent : close_settlement.cgetAgents()) {
for (auto& agent : close_settlement->cgetAgents()) {
if (agent.isAbleToMarriage() && agent.getGender() == SimulationConstants::getInstance()->male) {
male_settlement_pair.emplace_back(agent.getId(), close_settlement.getId());
male_settlement_pair.emplace_back(agent.getId(), close_settlement->getId());
}
}
}
Expand All @@ -225,13 +225,13 @@ namespace paxs {
if (true) {
for (std::size_t i = 0; i < marriageable_agents_index_pair.size(); ++i) {
std::pair<std::size_t, std::size_t> index_pair = marriageable_agents_index_pair[i];
std::uint_least64_t male_id = male_settlement_pair[index_pair.second].first;
std::uint_least32_t male_id = male_settlement_pair[index_pair.second].first;
std::uint_least32_t male_settlement_id = male_settlement_pair[index_pair.second].second;

bool is_found = false;
Vector2 male_settlement_position;
for (std::size_t j = 0; j < close_settlements.size(); ++j) {
if (close_settlements[j].getId() == male_settlement_id) {
if (close_settlements[j]->getId() == male_settlement_id) {

if (index_pair.first >= marriageable_female_index.size()) {
PAXS_ERROR("The FIRST of index_pair is larger than the size of marriageable_female_index.");
Expand All @@ -242,7 +242,7 @@ namespace paxs {
continue;
}

Agent male_ = close_settlements[j].getAgentCopy(male_id);
Agent male_ = close_settlements[j]->getAgentCopy(male_id);
Agent& female_ = agents[marriageable_female_index[index_pair.first]];

female_.marry(male_id, male_.cgetGenome(), male_.cgetFarming(), male_.cgetHunterGatherer());
Expand All @@ -252,7 +252,7 @@ namespace paxs {
agents.emplace_back(male_);

is_found = true;
male_settlement_position = close_settlements[j].getPosition();
male_settlement_position = close_settlements[j]->getPosition();
break;
}
}
Expand Down
4 changes: 2 additions & 2 deletions Library/PAX_SAPIENTICA/Simulation/SettlementAgent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ namespace paxs {
life_span == a.life_span &&
genome == a.genome &&
partner_id == a.partner_id &&
partner_genome == a.partner_genome;
partner_farming == a.partner_farming;
partner_genome == a.partner_genome &&
partner_farming == a.partner_farming &&
partner_hunter_gatherer == a.partner_hunter_gatherer;
}

Expand Down
40 changes: 34 additions & 6 deletions Library/PAX_SAPIENTICA/Simulation/SettlementSimulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <cstdint>

#include <array>
#include <chrono>
#include <memory>
#include <random>
#include <unordered_map>
Expand Down Expand Up @@ -105,6 +106,9 @@ namespace paxs {
/// @brief Execute the simulation for the one step.
/// @brief シミュレーションを1ステップ実行する
void step() noexcept {
std::chrono::system_clock::time_point start_time, end_time, move_time, m_start_time, m_end_time;
start_time = std::chrono::system_clock::now(); // 計測開始

std::vector<std::tuple<std::uint_least32_t, Vector2, Vector2>> move_list;
for (auto& settlement_grid : settlement_grids) {
std::vector<Settlement>& settlements = settlement_grid.second.getSettlements();
Expand All @@ -124,6 +128,8 @@ namespace paxs {
for (auto& move : move_list) {
moveSettlement(std::get<0>(move), std::get<1>(move), std::get<2>(move));
}
move_time = std::chrono::system_clock::now(); // 移動
move_processing_time = static_cast<double>(std::chrono::duration_cast<std::chrono::milliseconds>(move_time - start_time).count() / 1000.0);

for (auto& settlement_grid : settlement_grids) {
for (auto& settlement : settlement_grid.second.getSettlements()) {
Expand All @@ -133,6 +139,8 @@ namespace paxs {

randomizeSettlements(1, 255, 0);

m_start_time = std::chrono::system_clock::now(); // 婚姻計測開始

auto delete_agent = [this](const std::uint_least64_t agent_id, const std::uint_least32_t settlement_id, const Vector2 key) {
auto it = settlement_grids.find(key.toU64());
if (it != settlement_grids.end()) {
Expand All @@ -150,15 +158,15 @@ namespace paxs {
}

// 近隣8グリッドの集落を取得
std::vector<Settlement> close_settlements;
std::vector<Settlement*> close_settlements;
Vector2 grid_position = settlement_grid.second.getGridPosition();
grid_position /= SimulationConstants::getInstance()->grid_length;
for (int i = -1; i <= 1; ++i) {
for (int j = -1; j <= 1; ++j) {
auto it = settlement_grids.find((grid_position + Vector2(i, j)).toU64());
if (it != settlement_grids.end()) {
for (auto& settlement : it->second.getSettlements()) {
close_settlements.emplace_back(settlement);
close_settlements.emplace_back(&settlement);
}
}
}
Expand All @@ -169,6 +177,9 @@ namespace paxs {
}
}

m_end_time = std::chrono::system_clock::now(); // 婚姻計測終了
marriage_processing_time = static_cast<double>(std::chrono::duration_cast<std::chrono::milliseconds>(m_end_time - m_start_time).count() / 1000.0);

for (auto& settlement_grid : settlement_grids) {
for (auto& settlement : settlement_grid.second.getSettlements()) {
settlement.onUpdate();
Expand All @@ -182,6 +193,9 @@ namespace paxs {
for (auto& settlement_grid : settlement_grids) {
settlement_grid.second.divideSettlements();
}

end_time = std::chrono::system_clock::now(); // 計測終了
processing_time = static_cast<double>(std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count() / 1000.0);
}

/// @brief Get the agent list.
Expand All @@ -193,7 +207,21 @@ namespace paxs {
constexpr const std::unordered_map<std::uint_least64_t, SettlementGrid>&
cgetSettlementGrids() const noexcept { return settlement_grids; }

/// @brief Get processing_time.
/// @brief 処理時間を取得する
constexpr double cgetProcessingTime() const noexcept { return processing_time; }
/// @brief Get processing_time.
/// @brief 処理時間を取得する
constexpr double cgetMoveProcessingTime() const noexcept { return move_processing_time; }
/// @brief Get processing_time.
/// @brief 処理時間を取得する
constexpr double cgetMarriageProcessingTime() const noexcept { return marriage_processing_time; }

private:
double processing_time = 0.0;
double move_processing_time = 0.0;
double marriage_processing_time = 0.0;

std::unordered_map<std::uint_least64_t, SettlementGrid> settlement_grids;
std::shared_ptr<Environment> environment;

Expand All @@ -220,7 +248,7 @@ namespace paxs {
habitable_land_positions.emplace_back(habitable_land_positions_);
}
};
std::unique_ptr<std::array<Live, 90>> live_list;
std::unique_ptr<std::array<Live, max_number_of_districts>> live_list;

/// @brief ()
/// @brief 集落をランダムに配置する前の初期化処理
Expand All @@ -229,7 +257,7 @@ namespace paxs {

environment->getLandPositions(land_positions);

live_list = std::unique_ptr<std::array<Live, 90>>(new std::array<Live, 90>());
live_list = std::unique_ptr<std::array<Live, max_number_of_districts>>(new std::array<Live, max_number_of_districts>());

if (live_list.get() == nullptr) {
std::cout << "Low memory" << std::endl;
Expand Down Expand Up @@ -261,7 +289,7 @@ namespace paxs {

// 令制国ごとに人口が決められているので、人口に空きがあるかどうかを判定
std::uint_least8_t ryoseikoku_id = environment->template getData<std::uint_least8_t>(MurMur3::calcHash("gbank"), position);
if (ryoseikoku_id < 90) {
if (ryoseikoku_id < max_number_of_districts) {
(*live_list)[ryoseikoku_id].emplaceBack(live_probability, land_position);
}
}
Expand Down Expand Up @@ -291,7 +319,7 @@ namespace paxs {
}
int population_sum = 0;
// 集落配置
for (std::uint_least8_t ryoseikoku_id = 0; ryoseikoku_id < 90; ++ryoseikoku_id) {
for (std::uint_least8_t ryoseikoku_id = 0; ryoseikoku_id < max_number_of_districts; ++ryoseikoku_id) {

Live live = (*live_list)[ryoseikoku_id];

Expand Down
2 changes: 2 additions & 0 deletions Library/PAX_SAPIENTICA/Simulation/SimulationConst.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ namespace paxs {

constexpr int pixel_size = 256; // 1画像あたりの縦横のピクセル数

constexpr std::size_t max_number_of_districts = 90; // 最大地区数

using GridType = int;

struct SimulationConstants {
Expand Down

0 comments on commit a79f60d

Please sign in to comment.