1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
#include <terraces/advanced.hpp>
#include <terraces/clamped_uint.hpp>
#include <terraces/errors.hpp>
#include <terraces/rooting.hpp>
#include <terraces/subtree_extraction.hpp>
#include "multitree_iterator.hpp"
#include "supertree_enumerator.hpp"
#include "supertree_variants.hpp"
#include "supertree_variants_multitree.hpp"
namespace terraces {
supertree_data create_supertree_data(const tree& tree, const bitmatrix& data) {
auto root = find_comprehensive_taxon(data);
utils::ensure<bad_input_error>(data.rows() == num_leaves_from_nodes(tree.size()),
bad_input_error_type::tree_mismatching_size);
utils::ensure<no_usable_root_error>(root != none, "No comprehensive taxon found");
auto rerooted_tree = tree;
reroot_at_taxon_inplace(rerooted_tree, root);
auto trees = subtrees(rerooted_tree, data);
auto constraints = compute_constraints(trees);
deduplicate_constraints(constraints);
auto num_leaves = data.rows();
utils::ensure<bad_input_error>(num_leaves >= 4, bad_input_error_type::nwk_tree_trivial);
return {constraints, num_leaves, root};
}
index_t find_comprehensive_taxon(const bitmatrix& data) {
for (index_t i = 0; i < data.rows(); ++i) {
bool comp = true;
for (index_t j = 0; j < data.cols(); ++j) {
comp &= data.get(i, j);
}
if (comp) {
return i;
}
}
return none;
}
bitmatrix maximum_comprehensive_columnset(const bitmatrix& data) {
std::vector<index_t> row_counts(data.rows(), 0u);
for (index_t i = 0; i < data.rows(); ++i) {
for (index_t j = 0; j < data.cols(); ++j) {
row_counts[i] += data.get(i, j) ? 1u : 0u;
}
}
auto it = std::max_element(row_counts.begin(), row_counts.end());
index_t comp_row = static_cast<index_t>(std::distance(row_counts.begin(), it));
std::vector<index_t> columns;
for (index_t j = 0; j < data.cols(); ++j) {
if (data.get(comp_row, j)) {
columns.push_back(j);
}
}
return data.get_cols(columns);
}
index_t fast_count_terrace(const supertree_data& data) {
tree_enumerator<variants::check_callback> enumerator{{}};
try {
return enumerator.run(data.num_leaves, data.constraints, data.root);
} catch (terraces::tree_count_overflow_error&) {
return std::numeric_limits<index_t>::max();
}
}
bool check_terrace(const supertree_data& data) { return fast_count_terrace(data) > 1; }
index_t count_terrace(const supertree_data& data, execution_limits limits, bool& terminated_early) {
tree_enumerator<variants::timeout_decorator<variants::clamped_count_callback>> enumerator{
{limits.time_limit_seconds}};
try {
auto result = enumerator.run(data.num_leaves, data.constraints, data.root).value();
terminated_early = enumerator.callback().has_timed_out();
return result;
} catch (terraces::tree_count_overflow_error&) {
return std::numeric_limits<index_t>::max();
}
}
big_integer count_terrace_bigint(const supertree_data& data, execution_limits limits,
bool& terminated_early) {
tree_enumerator<variants::timeout_decorator<variants::count_callback<big_integer>>>
enumerator{{limits.time_limit_seconds}};
auto result = enumerator.run(data.num_leaves, data.constraints, data.root);
terminated_early = enumerator.callback().has_timed_out();
return result;
}
using limited_multitree_callback =
variants::timeout_decorator<variants::memory_limited_multitree_callback>;
big_integer print_terrace_compressed(const supertree_data& data, const name_map& names,
std::ostream& output, execution_limits limits,
bool& terminated_early) {
tree_enumerator<limited_multitree_callback> enumerator{
limited_multitree_callback{limits.time_limit_seconds, limits.mem_limit_bytes}};
auto result = enumerator.run(data.num_leaves, data.constraints, data.root);
terminated_early = enumerator.callback().has_timed_out() ||
enumerator.callback().has_hit_memory_limit();
output << as_newick(result, names);
return result->num_trees;
}
big_integer print_terrace(const supertree_data& data, const name_map& names, std::ostream& output,
execution_limits limits, bool& terminated_early) {
tree_enumerator<limited_multitree_callback> enumerator{
limited_multitree_callback{limits.time_limit_seconds, limits.mem_limit_bytes}};
auto result = enumerator.run(data.num_leaves, data.constraints, data.root);
terminated_early = enumerator.callback().has_timed_out() ||
enumerator.callback().has_hit_memory_limit();
if (!terminated_early) {
multitree_iterator mit{result};
do {
output << as_newick(mit.tree(), names) << '\n';
} while (mit.next());
}
return result->num_trees;
}
void enumerate_terrace(const supertree_data& data, std::function<void(const tree&)> callback,
execution_limits limits, bool& terminated_early) {
tree_enumerator<limited_multitree_callback> enumerator{
limited_multitree_callback{limits.time_limit_seconds, limits.mem_limit_bytes}};
auto result = enumerator.run(data.num_leaves, data.constraints, data.root);
terminated_early = enumerator.callback().has_timed_out() ||
enumerator.callback().has_hit_memory_limit();
if (!terminated_early) {
multitree_iterator mit{result};
do {
callback(mit.tree());
} while (mit.next());
}
}
index_t count_terrace(const supertree_data& data) {
execution_limits limits{};
bool tmp;
return count_terrace(data, limits, tmp);
}
big_integer count_terrace_bigint(const supertree_data& data) {
execution_limits limits{};
bool tmp;
return count_terrace_bigint(data, limits, tmp);
}
big_integer print_terrace_compressed(const supertree_data& data, const name_map& names,
std::ostream& output) {
execution_limits limits{};
bool tmp;
return print_terrace_compressed(data, names, output, limits, tmp);
}
big_integer print_terrace(const supertree_data& data, const name_map& names, std::ostream& output) {
execution_limits limits{};
bool tmp;
return print_terrace(data, names, output, limits, tmp);
}
void enumerate_terrace(const supertree_data& data, std::function<void(const tree&)> callback) {
execution_limits limits{};
bool tmp;
return enumerate_terrace(data, std::move(callback), limits, tmp);
}
} // namespace terraces
|