67 std::unordered_set<size_t>
const& candidate_edges
70 std::unordered_set<size_t> sub_indices;
79 auto find_valid_next = [&](
TreeLink const* link_ptr ){
80 auto next_ptr = &link_ptr->next();
81 while( next_ptr != link_ptr ) {
83 if(
is_leaf( next_ptr->edge() )) {
86 assert( sub_indices.count( next_ptr->edge().index() ) == 0 );
87 sub_indices.insert( next_ptr->edge().index() );
88 }
else if( candidate_edges.count( next_ptr->edge().index() ) > 0 ) {
98 assert( candidate_edges.count( next_ptr->edge().index() ) == 0 );
99 next_ptr = &next_ptr->next();
106 if( next_ptr == link_ptr ) {
118 while( link_ptr != &subtree.
link() ) {
123 link_ptr = &link_ptr->
outer();
124 assert( candidate_edges.count( link_ptr->edge().index() ) > 0 );
125 assert( !
is_leaf( link_ptr->edge() ));
130 if( link_ptr != &subtree.
link() ) {
134 sub_indices.insert( link_ptr->edge().index() );
139 auto next_ptr = find_valid_next( link_ptr );
148 assert( candidate_edges.count( next_ptr->edge().index() ) > 0 );
149 assert( !
is_leaf( next_ptr->edge() ));
161 if( link_ptr != &subtree.
link() ) {
164 assert( sub_indices.count( link_ptr->edge().index() ) > 0 );
165 assert( candidate_edges.count( link_ptr->edge().index() ) > 0 );
171 link_ptr = find_valid_next( &link_ptr->outer() );
175 assert( !
is_leaf( link_ptr->edge() ));
186 std::unordered_set<size_t>
const& candidate_edges,
201 auto const cand_vec = std::vector<size_t>( candidate_edges.begin(), candidate_edges.end() );
204 #pragma omp parallel for schedule(dynamic)
205 for(
size_t i = 0; i < cand_vec.size(); ++i ) {
206 auto const ce_idx = cand_vec[i];
210 assert( edge.index() == ce_idx );
226 Subtree{ edge.primary_link() }, candidate_edges
228 if( p_indices.empty() ) {
232 Subtree{ edge.secondary_link() }, candidate_edges
234 if( s_indices.empty() ) {
239 assert( s_indices.count( edge.index() ) == 0 );
240 assert( p_indices.count( edge.index() ) == 0 );
243 auto const balances =
mass_balance( data, s_indices, p_indices );
246 auto const ov = objective( iteration, ce_idx, balances );
248 if( ! std::isfinite( ov )) {
253 #pragma omp critical( GENESIS_TREE_MASS_TREE_PHYLO_FACTOR_OBJECTIVE_UPDATE )
270 std::function<
double( std::vector<double>
const& balances )> objective,
271 size_t max_iterations,
272 std::function<
void(
size_t iteration,
size_t max_iterations )> log_progress
276 [&objective](
size_t,
size_t, std::vector<double>
const& balances ){
277 return objective( balances );
287 size_t max_iterations,
288 std::function<
void(
size_t iteration,
size_t max_iterations )> log_progress
292 return std::vector<PhyloFactor>{};
296 std::unordered_set<size_t> candidate_edges;
299 candidate_edges.insert( i );
304 if( max_iterations == 0 || max_iterations > candidate_edges.size() ) {
305 max_iterations = candidate_edges.size();
310 std::vector<PhyloFactor> result;
311 for(
size_t it = 0; it < max_iterations; ++it ) {
312 assert( candidate_edges.size() > 0 );
316 log_progress( it, max_iterations );
323 assert( candidate_edges.count( result.back().edge_index ) > 0 );
324 candidate_edges.erase( result.back().edge_index );