Skip to content

Commit

Permalink
upd: Ultra-fast marriage processing
Browse files Browse the repository at this point in the history
  • Loading branch information
AsPJT committed Dec 11, 2024
1 parent 5b7d2d1 commit 5400bdc
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 55 deletions.
100 changes: 50 additions & 50 deletions Library/PAX_SAPIENTICA/Simulation/Settlement.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,7 @@ namespace paxs {

// std::vector のメモリ確保・解放のコストを削減するために再利用する
/* この入力値は使わない */ std::vector<std::size_t>& marriageable_female_index,
/* この入力値は使わない */ std::vector<std::pair<std::uint_least32_t, std::uint_least32_t>>& male_settlement_pair,
/* この入力値は使わない */ std::vector<Settlement*>& close_settlements,
/* この入力値は使わない */ std::vector<Marriage3>& male_settlement_pair,
std::vector<GridType4>& marriage_pos_list
) noexcept {
// 結婚の条件を満たすエージェントを取得
Expand All @@ -368,39 +367,58 @@ namespace paxs {
if (marriageable_female_index.empty()) {
return;
}
// 近隣の集落を探す
close_settlements.clear();
for (const auto& const_close_settlements : close_settlements_list) {
for (std::size_t i = 0; i < const_close_settlements->size(); ++i) {
if ((*const_close_settlements)[i].getPosition().distance_pow2(position) <= SimulationConstants::getInstance()->marriage_search_range_pow2) {
close_settlements.emplace_back(&((*const_close_settlements)[i]));
// 農耕度が高い順にソート
std::sort(marriageable_female_index.begin(), marriageable_female_index.end(),
[&](const std::size_t a, const std::size_t b) {
return agents[a].cgetFarming() > agents[b].cgetFarming();
});

// 近隣の集落を探し、エージェントIDと集落IDのペアを作成
male_settlement_pair.clear();
const double const_marriage_search_range_pow2 = SimulationConstants::getInstance()->marriage_search_range_pow2;
for (std::size_t i = 0; i < close_settlements_list.size(); ++i) {
if (marriageable_female_index.size() <= male_settlement_pair.size()) break;

const std::size_t close_settlements_size = close_settlements_list[i]->size();
if (close_settlements_size == 0) continue;
std::uniform_int_distribution<int> dist(0, close_settlements_size - 1);
const std::size_t cs_start = static_cast<std::size_t>(dist(*gen));

for (std::size_t acs = 0, css = cs_start; acs < close_settlements_size; ++acs, ++css) {
if (marriageable_female_index.size() <= male_settlement_pair.size()) break;
if (css >= close_settlements_size) css -= close_settlements_size;

if ((*close_settlements_list[i])[css].getPosition().distance_pow2(position) <= const_marriage_search_range_pow2) {
const std::vector<Agent>& close_agent = (*close_settlements_list[i])[css].cgetAgents();
const std::size_t close_agent_size = close_agent.size();
for (std::size_t ca = 0; ca < close_agent_size; ++ca) {
if (close_agent[ca].isMale() && close_agent[ca].isAbleToMarriage()) {
male_settlement_pair.emplace_back(
Marriage3{
static_cast<std::uint_least32_t>(ca),
static_cast<std::uint_least32_t>(css),
static_cast<std::uint_least32_t>(i),
close_agent[ca].cgetFarming()
});
break; // 1集落1人まで
}
}
}
}
}
// 自分の集落を含めて、近くに集落がない
if (close_settlements.empty()) {
// 自分の集落を含めて、近くに婚約者がない
if (male_settlement_pair.empty()) {
PAXS_ERROR("Settlement not found.");
return;
}
// 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のペアを作成
male_settlement_pair.clear();
for (std::size_t cs = 0; cs < close_settlements.size(); ++cs) {
const std::vector<Agent>& close_agent = close_settlements[cs]->cgetAgents();
const std::size_t ca_size = close_agent.size();
for (std::size_t ca = 0; ca < ca_size; ++ca) {
if (close_agent[ca].isAbleToMarriage() && close_agent[ca].isMale()) {
male_settlement_pair.emplace_back(ca, cs);
}
}
}
// 女性と男性の組み合わせをランダムに選択
std::shuffle(male_settlement_pair.begin(), male_settlement_pair.end(), *gen);
// 農耕度が高い順にソート
std::sort(male_settlement_pair.begin(), male_settlement_pair.end(),
[&](const Marriage3 a, const Marriage3 b) {
return a.farming > b.farming;
});

const std::size_t num_elements = (std::min)(marriageable_female_index.size(), male_settlement_pair.size());

// 居住婚
Expand All @@ -424,25 +442,16 @@ namespace paxs {

// シミュレーションの設定で母方に移住するか父方に移住するかを決める
for (std::size_t i = 0; i < num_elements; ++i) {
const std::uint_least32_t pair_agent_index = male_settlement_pair[i/*元婚姻ペア(夫)*/].first;
const std::uint_least32_t pair_settlement_index = male_settlement_pair[i/*元婚姻ペア(夫)*/].second;
Settlement& pair_settlement = *(close_settlements[pair_settlement_index]);
const std::uint_least32_t pair_agent_index = male_settlement_pair[i].first;
const std::uint_least32_t pair_settlement_index = male_settlement_pair[i].second;
Settlement& pair_settlement = (*(close_settlements_list[male_settlement_pair[i].third]))[pair_settlement_index];
Agent& pair_agent = pair_settlement.getAgents()[pair_agent_index];

bool is_found = false;
if (i/*元婚姻ペア(妻)*/ >= marriageable_female_index.size()) {
PAXS_ERROR("The FIRST of index_pair is larger than the size of marriageable_female_index.");
continue;
}
if (marriageable_female_index[i/*元婚姻ペア(妻)*/] >= agents.size()) {
PAXS_ERROR("marriageable_female_index is larger than the size of AGENTS.");
continue;
}
Vector2 male_settlement_position = pair_settlement.getPosition();
// 母方の場合
if (is_matrilocality) {
Agent male_ = pair_agent;
Agent& female_ = agents[marriageable_female_index[i/*元婚姻ペア(妻)*/]];
Agent& female_ = agents[marriageable_female_index[i]];

female_.marry(pair_agent.getId(), male_.cgetGenome(), male_.cgetFarming(), male_.cgetHunterGatherer(), male_.cgetLanguage());
const HumanIndexType female_id = female_.getId();
Expand All @@ -452,14 +461,13 @@ namespace paxs {

marriage_pos_list.emplace_back(GridType4{ pair_settlement.position.x, pair_settlement.position.y, position.x, position.y });

pair_agent.setAge((std::numeric_limits<AgeType>::max)());
pair_agent.setLifeSpan(0);
pair_agent.setPartnerId(0);
}
// 父方の場合
else {
Agent& male_ = pair_agent;
Agent female_ = agents[marriageable_female_index[i/*元婚姻ペア(妻)*/]];
Agent female_ = agents[marriageable_female_index[i]];

female_.marry(pair_agent.getId(), male_.cgetGenome(), male_.cgetFarming(), male_.cgetHunterGatherer(), male_.cgetLanguage());
const HumanIndexType female_id = female_.getId();
Expand All @@ -471,17 +479,9 @@ namespace paxs {

marriage_pos_list.emplace_back(GridType4{ position.x, position.y, pair_settlement.position.x, pair_settlement.position.y });

agents[marriageable_female_index[i/*元婚姻ペア(妻)*/]].setAge((std::numeric_limits<AgeType>::max)());
agents[marriageable_female_index[i/*元婚姻ペア(妻)*/]].setLifeSpan(0);
agents[marriageable_female_index[i/*元婚姻ペア(妻)*/]].setPartnerId(0);
}
is_found = true;
break;

if (!is_found) {
PAXS_ERROR("Settlement not found.");
continue;
}
}
}

Expand Down
10 changes: 5 additions & 5 deletions Library/PAX_SAPIENTICA/Simulation/SettlementSimulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,11 +300,9 @@ namespace paxs {
// 結婚の条件を満たすエージェントを取得
std::vector<std::size_t> marriageable_female_index;
// エージェントIDと集落IDのペアを作成
std::vector<std::pair<std::uint_least32_t, std::uint_least32_t>> male_settlement_pair;
// 婚姻半径内の集落
std::vector<Settlement*> marriage_settlements;
std::vector<Marriage3> male_settlement_pair;

// 近隣8グリッドの集落を取得
// 近隣9グリッドの集落を取得
std::vector<std::vector<Settlement>*> close_settlements_list;

for (auto& settlement_grid : settlement_grids) {
Expand All @@ -323,6 +321,8 @@ namespace paxs {
}
}
}
// 近隣9グリッドのシャッフル
std::shuffle(close_settlements_list.begin(), close_settlements_list.end(), gen);
for (auto& close_settlements : close_settlements_list) {
// 青銅交換
if (close_settlements->size() >= 2) {
Expand All @@ -334,7 +334,7 @@ namespace paxs {
for (auto& settlement : settlements) {
settlement.marriage(
close_settlements_list,
marriageable_female_index, male_settlement_pair, marriage_settlements,
marriageable_female_index, male_settlement_pair,
marriage_pos_list
);
}
Expand Down
5 changes: 5 additions & 0 deletions Library/PAX_SAPIENTICA/Simulation/SimulationConst.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ namespace paxs {
struct GridType4 {
GridType sx{}, sy{}, ex{}, ey{};
};
// 始点と終点を管理(婚姻の前後の位置情報を保持する用)
struct Marriage3 {
std::uint_least32_t first{}, second{}, third{};
std::uint_least8_t farming{};
};

struct SimulationConstants {
// インスタンスを取得
Expand Down

0 comments on commit 5400bdc

Please sign in to comment.