Skip to content

Commit cda89ed

Browse files
Merge pull request #2385 from jeromekelleher/embed-avl-lineage
Embed avl into lineage struct
2 parents 26bcbf8 + 8e2ab4f commit cda89ed

File tree

3 files changed

+31
-51
lines changed

3 files changed

+31
-51
lines changed

lib/msprime.c

Lines changed: 16 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
** Copyright (C) 2015-2024 University of Oxford
2+
** Copyright (C) 2015-2025 University of Oxford
33
**
44
** This file is part of msprime.
55
**
@@ -1470,19 +1470,14 @@ msp_insert_individual(msp_t *self, lineage_t *lin)
14701470

14711471
tsk_bug_assert(lin != NULL);
14721472
tsk_bug_assert(lin->head != NULL);
1473-
node = msp_alloc_avl_node(self);
1474-
if (node == NULL) {
1475-
ret = MSP_ERR_NO_MEMORY;
1476-
goto out;
1477-
}
1473+
node = &lin->avl_node;
14781474
avl_init_node(node, lin);
14791475
node = avl_insert_node(msp_get_lineage_population(self, lin), node);
1480-
tsk_bug_assert(node != NULL);
1476+
tsk_bug_assert(node == &lin->avl_node);
14811477

14821478
if (self->model.type == MSP_MODEL_SMC_K) {
14831479
ret = msp_insert_individual_hull(self, lin);
14841480
}
1485-
out:
14861481
return ret;
14871482
}
14881483

@@ -1491,12 +1486,11 @@ msp_remove_individual(msp_t *self, lineage_t *lin)
14911486
{
14921487
avl_node_t *node;
14931488
avl_tree_t *pop;
1489+
14941490
tsk_bug_assert(lin != NULL);
14951491
pop = msp_get_lineage_population(self, lin);
1496-
node = avl_search(pop, lin);
1497-
tsk_bug_assert(node != NULL);
1492+
node = &lin->avl_node;
14981493
avl_unlink_node(pop, node);
1499-
msp_free_avl_node(self, node);
15001494
msp_free_lineage(self, lin);
15011495
}
15021496

@@ -1688,11 +1682,8 @@ msp_verify_segments(msp_t *self, bool verify_breakpoints)
16881682
label_segments == object_heap_get_num_allocated(&self->segment_heap[k]));
16891683
tsk_bug_assert(
16901684
label_hulls == object_heap_get_num_allocated(&self->hull_heap[k]));
1691-
/* tsk_bug_assert( */
1692-
/* label_hulls == object_heap_get_num_allocated(&self->hullend_heap[k])); */
16931685
}
1694-
total_avl_nodes = msp_get_num_ancestors(self) + avl_count(&self->breakpoints)
1695-
+ avl_count(&self->overlap_counts)
1686+
total_avl_nodes = avl_count(&self->breakpoints) + avl_count(&self->overlap_counts)
16961687
+ avl_count(&self->non_empty_populations);
16971688
tsk_bug_assert(msp_get_num_ancestors(self)
16981689
== object_heap_get_num_allocated(&self->lineage_heap));
@@ -1705,8 +1696,7 @@ msp_verify_segments(msp_t *self, bool verify_breakpoints)
17051696
}
17061697
tsk_bug_assert(total_avl_nodes + pedigree_avl_nodes
17071698
== object_heap_get_num_allocated(&self->avl_node_heap));
1708-
tsk_bug_assert(total_avl_nodes - msp_get_num_ancestors(self)
1709-
- avl_count(&self->non_empty_populations)
1699+
tsk_bug_assert(total_avl_nodes - avl_count(&self->non_empty_populations)
17101700
== object_heap_get_num_allocated(&self->node_mapping_heap));
17111701
if (self->recomb_mass_index != NULL) {
17121702
msp_verify_segment_index(
@@ -2682,7 +2672,6 @@ msp_move_individual(msp_t *self, avl_node_t *node, avl_tree_t *source,
26822672

26832673
ind = (lineage_t *) node->item;
26842674
avl_unlink_node(source, node);
2685-
msp_free_avl_node(self, node);
26862675
if (self->model.type == MSP_MODEL_SMC_K) {
26872676
msp_remove_hull(self, ind);
26882677
}
@@ -4146,8 +4135,7 @@ msp_merge_n_ancestors(msp_t *self, avl_tree_t *Q, population_id_t population_id,
41464135
tsk_bug_assert(u->lineage != NULL);
41474136
if (u->lineage->population != population_id) {
41484137
current_pop = &self->populations[u->lineage->population];
4149-
avl_node = avl_search(&current_pop->ancestors[label], u->lineage);
4150-
tsk_bug_assert(avl_node != NULL);
4138+
avl_node = &u->lineage->avl_node;
41514139
ret = msp_move_individual(
41524140
self, avl_node, &current_pop->ancestors[label], population_id, label);
41534141
if (ret != 0) {
@@ -4229,7 +4217,6 @@ msp_reset_memory_state(msp_t *self)
42294217
u = v;
42304218
}
42314219
avl_unlink_node(&pop->ancestors[label], node);
4232-
msp_free_avl_node(self, node);
42334220
if (lin->hull != NULL) {
42344221
msp_remove_hull(self, lin);
42354222
}
@@ -5816,11 +5803,7 @@ static int
58165803
msp_change_label(msp_t *self, lineage_t *lin, label_id_t label)
58175804
{
58185805
avl_tree_t *pop = &self->populations[lin->population].ancestors[lin->label];
5819-
avl_node_t *node;
5820-
5821-
/* Find the this individual in the AVL tree. */
5822-
node = avl_search(pop, lin);
5823-
tsk_bug_assert(node != NULL);
5806+
avl_node_t *node = &lin->avl_node;
58245807
return msp_move_individual(self, node, pop, lin->population, label);
58255808
}
58265809

@@ -7162,7 +7145,6 @@ msp_simple_bottleneck(msp_t *self, demographic_event_t *event)
71627145
lin = (lineage_t *) node->item;
71637146
u = lin->head;
71647147
avl_unlink_node(pop, node);
7165-
msp_free_avl_node(self, node);
71667148
msp_free_lineage(self, lin);
71677149
q_node = msp_alloc_avl_node(self);
71687150
if (q_node == NULL) {
@@ -7314,7 +7296,6 @@ msp_instantaneous_bottleneck(msp_t *self, demographic_event_t *event)
73147296
* set for the root at u */
73157297
lin = (lineage_t *) avl_nodes[j]->item;
73167298
avl_unlink_node(pop, avl_nodes[j]);
7317-
msp_free_avl_node(self, avl_nodes[j]);
73187299
set_node = msp_alloc_avl_node(self);
73197300
if (set_node == NULL) {
73207301
ret = MSP_ERR_NO_MEMORY;
@@ -7601,9 +7582,7 @@ msp_std_common_ancestor_event(
76017582
tsk_bug_assert(node != NULL);
76027583
} else {
76037584
self->num_ca_events++;
7604-
msp_free_avl_node(self, x_node);
76057585
msp_free_lineage(self, x_lin);
7606-
msp_free_avl_node(self, y_node);
76077586
msp_free_lineage(self, y_lin);
76087587
ret = msp_merge_two_ancestors(self, population_id, label, x, y, TSK_NULL, NULL);
76097588
}
@@ -7647,14 +7626,13 @@ msp_smc_k_common_ancestor_event(
76477626
double random_mass, num_pairs, remaining_mass;
76487627
size_t hull_id;
76497628
fenwick_t *coal_mass_index;
7650-
avl_tree_t *avl;
7629+
avl_tree_t *ancestors;
76517630
avl_node_t *x_node, *y_node, *search;
76527631
hull_t *x_hull, *y_hull = NULL;
76537632
lineage_t *x_lin, *y_lin;
76547633
segment_t *x, *y;
76557634

76567635
/* find first hull */
7657-
/* FIX ME: clean up the various type castings */
76587636
coal_mass_index = &self->populations[population_id].coal_mass_index[label];
76597637
num_pairs = fenwick_get_total(coal_mass_index);
76607638
random_mass = gsl_ran_flat(self->rng, 0, num_pairs);
@@ -7666,9 +7644,7 @@ msp_smc_k_common_ancestor_event(
76667644
remaining_mass = fenwick_get_cumulative_sum(coal_mass_index, hull_id) - random_mass;
76677645

76687646
/* find second hull */
7669-
avl = &self->populations[population_id].hulls_left[label];
7670-
search = avl_search(avl, x_hull);
7671-
tsk_bug_assert(search != NULL);
7647+
search = &x_hull->left_avl_node;
76727648
for (search = search->prev; remaining_mass >= 0; search = search->prev) {
76737649
tsk_bug_assert(search != NULL);
76747650
y_hull = (hull_t *) search->item;
@@ -7682,19 +7658,15 @@ msp_smc_k_common_ancestor_event(
76827658
msp_remove_hull(self, y_lin);
76837659

76847660
/* retrieve ancestors linked to both hulls */
7685-
avl = &self->populations[population_id].ancestors[label];
7661+
ancestors = &self->populations[population_id].ancestors[label];
76867662
x = x_lin->head;
7687-
x_node = avl_search(avl, x_lin);
7688-
tsk_bug_assert(x_node != NULL);
7689-
avl_unlink_node(avl, x_node);
7663+
x_node = &x_lin->avl_node;
7664+
avl_unlink_node(ancestors, x_node);
76907665
y = y_lin->head;
7691-
y_node = avl_search(avl, y_lin);
7692-
tsk_bug_assert(y_node != NULL);
7693-
avl_unlink_node(avl, y_node);
7666+
y_node = &y_lin->avl_node;
7667+
avl_unlink_node(ancestors, y_node);
76947668

76957669
self->num_ca_events++;
7696-
msp_free_avl_node(self, x_node);
7697-
msp_free_avl_node(self, y_node);
76987670
msp_free_lineage(self, x_lin);
76997671
msp_free_lineage(self, y_lin);
77007672
ret = msp_merge_two_ancestors(self, population_id, label, x, y, TSK_NULL, NULL);
@@ -7781,9 +7753,7 @@ msp_dirac_common_ancestor_event(msp_t *self, population_id_t pop_id, label_id_t
77817753
y = y_lin->head;
77827754
avl_unlink_node(ancestors, y_node);
77837755
self->num_ca_events++;
7784-
msp_free_avl_node(self, x_node);
77857756
msp_free_lineage(self, x_lin);
7786-
msp_free_avl_node(self, y_node);
77877757
msp_free_lineage(self, y_lin);
77887758
ret = msp_merge_two_ancestors(self, pop_id, label, x, y, TSK_NULL, NULL);
77897759
} else {
@@ -7947,7 +7917,6 @@ msp_multi_merger_common_ancestor_event(
79477917
lin = (lineage_t *) node->item;
79487918
u = lin->head;
79497919
avl_unlink_node(ancestors, node);
7950-
msp_free_avl_node(self, node);
79517920
msp_free_lineage(self, lin);
79527921

79537922
q_node = msp_alloc_avl_node(self);

lib/msprime.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
** Copyright (C) 2015-2024 University of Oxford
2+
** Copyright (C) 2015-2025 University of Oxford
33
**
44
** This file is part of msprime.
55
**
@@ -91,6 +91,7 @@ typedef struct lineage_t_t {
9191
label_id_t label;
9292
segment_t *head;
9393
segment_t *tail;
94+
avl_node_t avl_node;
9495
struct hull_t_t *hull;
9596
} lineage_t;
9697

lib/tests/test_ancestry.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
** Copyright (C) 2016-2024 University of Oxford
2+
** Copyright (C) 2016-2025 University of Oxford
33
**
44
** This file is part of msprime.
55
**
@@ -795,7 +795,7 @@ test_dtwf_multi_locus_simulation(void)
795795
long seed = 10;
796796
double migration_matrix[] = { 0, 0.1, 0.1, 0 };
797797
const char *model_name;
798-
size_t num_ca_events, num_re_events;
798+
size_t num_ca_events, num_re_events, num_mig_events;
799799
double t;
800800
tsk_table_collection_t tables;
801801
msp_t msp;
@@ -809,6 +809,8 @@ test_dtwf_multi_locus_simulation(void)
809809
CU_ASSERT_EQUAL_FATAL(msp_set_recombination_rate(&msp, 0.1), 0);
810810
ret = msp_set_population_configuration(&msp, 0, n, 0, true);
811811
CU_ASSERT_EQUAL(ret, 0);
812+
ret = msp_set_population_configuration(&msp, 1, n, 0, true);
813+
CU_ASSERT_EQUAL(ret, 0);
812814
ret = msp_set_migration_matrix(&msp, 4, migration_matrix);
813815
CU_ASSERT_EQUAL(ret, 0);
814816
ret = msp_set_store_migrations(&msp, true);
@@ -819,12 +821,14 @@ test_dtwf_multi_locus_simulation(void)
819821
CU_ASSERT_STRING_EQUAL(model_name, "dtwf");
820822

821823
ret = msp_run(&msp, DBL_MAX, ULONG_MAX);
824+
CU_ASSERT_EQUAL(ret, 0);
822825
msp_verify(&msp, 0);
823826
num_ca_events = msp_get_num_common_ancestor_events(&msp);
824827
num_re_events = msp_get_num_recombination_events(&msp);
828+
num_mig_events = tables.migrations.num_rows;
825829
CU_ASSERT_TRUE(num_ca_events > 0);
826830
CU_ASSERT_TRUE(num_re_events > 0);
827-
CU_ASSERT_EQUAL(ret, 0);
831+
CU_ASSERT_TRUE(num_mig_events > 0);
828832
msp_free(&msp);
829833
tsk_table_collection_free(&tables);
830834

@@ -838,7 +842,12 @@ test_dtwf_multi_locus_simulation(void)
838842
CU_ASSERT_EQUAL(ret, 0);
839843
ret = msp_set_population_configuration(&msp, 0, n, 0, true);
840844
CU_ASSERT_EQUAL(ret, 0);
845+
ret = msp_set_population_configuration(&msp, 1, n, 0, true);
846+
CU_ASSERT_EQUAL(ret, 0);
841847
ret = msp_set_migration_matrix(&msp, 4, migration_matrix);
848+
CU_ASSERT_EQUAL(ret, 0);
849+
ret = msp_set_store_migrations(&msp, true);
850+
CU_ASSERT_EQUAL(ret, 0);
842851
ret = msp_initialise(&msp);
843852
CU_ASSERT_EQUAL(ret, 0);
844853
t = 1;
@@ -854,6 +863,7 @@ test_dtwf_multi_locus_simulation(void)
854863
CU_ASSERT_EQUAL(ret, 0);
855864
CU_ASSERT_TRUE(num_ca_events == msp_get_num_common_ancestor_events(&msp));
856865
CU_ASSERT_TRUE(num_re_events == msp_get_num_recombination_events(&msp));
866+
CU_ASSERT_TRUE(num_mig_events == tables.migrations.num_rows);
857867

858868
ret = msp_free(&msp);
859869
CU_ASSERT_EQUAL(ret, 0);

0 commit comments

Comments
 (0)