@@ -8727,6 +8727,7 @@ void Species::__CreateSubpopulationsFromTabulation(std::unordered_map<slim_objec
87278727 // This could be done with a hash table, but I imagine that would be slower until the number of individuals becomes very large
87288728 // Also, I'm a bit nervous about putting a large number of consecutive integers into a hash table, re: edge-case performance
87298729 std::vector<slim_pedigreeid_t> pedigree_id_check;
8730+ std::vector<slim_haplosomeid_t> haplosome_id_check;
87308731
87318732 gSLiM_next_pedigree_id = 0;
87328733
@@ -8806,12 +8807,16 @@ void Species::__CreateSubpopulationsFromTabulation(std::unordered_map<slim_objec
88068807 individual->spatial_z_ = subpop_info.spatial_z_[tabulation_index];
88078808
88088809 p_nodeToHaplosomeMap.emplace(node_id_0, individual->haplosomes_[first_haplosome_index]);
8809- individual->haplosomes_[first_haplosome_index]->haplosome_id_ = pedigree_id * 2;
8810+ slim_haplosomeid_t haplosome_id = pedigree_id * 2;
8811+ individual->haplosomes_[first_haplosome_index]->haplosome_id_ = haplosome_id;
8812+ haplosome_id_check.emplace_back(haplosome_id); // we will test for collisions below
88108813
88118814 if (last_haplosome_index != first_haplosome_index)
88128815 {
88138816 p_nodeToHaplosomeMap.emplace(node_id_1, individual->haplosomes_[last_haplosome_index]);
8814- individual->haplosomes_[last_haplosome_index]->haplosome_id_ = pedigree_id * 2 + 1;
8817+ haplosome_id = pedigree_id * 2 + 1;
8818+ individual->haplosomes_[last_haplosome_index]->haplosome_id_ = haplosome_id;
8819+ haplosome_id_check.emplace_back(haplosome_id); // we will test for collisions below
88158820 }
88168821
88178822 // check the referenced nodes; right now this is not essential for re-creating the saved state, but is just a crosscheck
@@ -9814,13 +9819,12 @@ void Species::__CheckNodePedigreeIDs(__attribute__((unused)) EidosInterpreter *p
98149819 // could be nodes in the node table with haplosome pedigree IDs greater than those in use by individuals, in nonWF models.
98159820 // See https://github.com/MesserLab/SLiM/pull/420 for an example model that does this very easily.
98169821
9817- // Also, check for duplicate pedigree IDs, just in case. __CreateSubpopulationsFromTabulation() does this for individual
9818- // pedigree IDs; we do it for node pedigree IDs. I decided to use a vector with std::sort () to check even though it is
9819- // O(n log n), rather than a hash table for O(n), because I'm nervous about hitting a bad edge case with the hash table
9820- // due to the nature of the values being inserted. Shouldn't be a big deal in the grand scheme of things.
9822+ // Previously, we checked for duplicate haplosome IDs here as well , just in case.
9823+ // __CreateSubpopulationsFromTabulation () does this in living individuals
9824+ // already; however, it was found to be overly restrictive, in situations
9825+ // involving merging of parallel simulations; see https://github.com/MesserLab/SLiM/issues/538
98219826 tsk_node_table_t &node_table = tables.nodes;
98229827 tsk_size_t node_count = node_table.num_rows;
9823- std::vector<slim_haplosomeid_t> haplosome_id_check;
98249828
98259829 for (tsk_size_t j = 0; (size_t)j < node_count; j++)
98269830 {
@@ -9833,11 +9837,7 @@ void Species::__CheckNodePedigreeIDs(__attribute__((unused)) EidosInterpreter *p
98339837 {
98349838 // get the metadata record and check the haplosome pedigree ID
98359839 HaplosomeMetadataRec *metadata_rec = (HaplosomeMetadataRec *)(node_table.metadata + offset1);
9836- slim_haplosomeid_t haplosome_id = metadata_rec->haplosome_id_;
9837-
9838- haplosome_id_check.emplace_back(haplosome_id); // we will test for collisions below
9839-
9840- slim_pedigreeid_t pedigree_id = haplosome_id / 2; // rounds down to integer
9840+ slim_pedigreeid_t pedigree_id = metadata_rec->haplosome_id_ / 2; // rounds down to integer
98419841
98429842 if (pedigree_id >= gSLiM_next_pedigree_id)
98439843 {
@@ -9854,13 +9854,6 @@ void Species::__CheckNodePedigreeIDs(__attribute__((unused)) EidosInterpreter *p
98549854 }
98559855 }
98569856 }
9857-
9858- // Check for haplosome pedigree ID collisions by sorting and looking for duplicates
9859- std::sort(haplosome_id_check.begin(), haplosome_id_check.end());
9860- const auto duplicate = std::adjacent_find(haplosome_id_check.begin(), haplosome_id_check.end());
9861-
9862- if (duplicate != haplosome_id_check.end())
9863- EIDOS_TERMINATION << "ERROR (Species::__CheckNodePedigreeIDs): the haplosome pedigree ID value " << *duplicate << " was used more than once; haplosome pedigree IDs must be unique." << EidosTerminate();
98649857}
98659858
98669859void Species::_ReadAncestralSequence(const char *p_file, Chromosome &p_chromosome)
0 commit comments