File: verbose_run.cpp

package info (click to toggle)
iqtree 2.0.7%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 14,620 kB
  • sloc: cpp: 142,571; ansic: 57,789; sh: 275; python: 242; makefile: 95
file content (135 lines) | stat: -rw-r--r-- 4,697 bytes parent folder | download
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
#include "../lib/bitvector.hpp"
#include "../lib/constraints_impl.hpp"
#include "../lib/io_utils.hpp"
#include "../lib/multitree_iterator.hpp"
#include "../lib/subtree_extraction_impl.hpp"
#include "../lib/supertree_enumerator.hpp"
#include "../lib/supertree_variants_debug.hpp"
#include "../lib/supertree_variants_multitree.hpp"
#include "../lib/validation.hpp"
#include <iostream>
#include <terraces/constraints.hpp>
#include <terraces/parser.hpp>
#include <terraces/rooting.hpp>

enum class mode { count, enumerate };

using namespace terraces;

bool is_comprehensive(const tree& t, const bitmatrix& matrix) {
	const auto node_occ = compute_node_occ(t, matrix).first;
	for (terraces::index i = 0; i < matrix.cols(); ++i) {
		if (induced_lca(t, node_occ, i) != 0) {
			return false;
		}
	}
	return true;
}

void count_and_check_trees(const multitree_node* multitree, const bitmatrix& matrix,
                           const std::vector<tree>& ref_trees, const name_map& names) {
	std::cerr << "Enumerating all trees" << std::endl;

	// store all supertrees
	std::vector<tree> supertrees;
	multitree_iterator mit(multitree);
	do {
		supertrees.push_back(mit.tree());
	} while (mit.next());
	if (big_integer{supertrees.size()} != multitree->num_trees) {
		std::cerr << "PANIC! Inconsistent tree count" << std::endl;
	}

	// check for supertree property
	for (const auto& supertree : supertrees) {
		auto trees = subtrees(supertree, matrix);
		for (terraces::index i = 0; i < trees.size(); ++i) {
			if (!is_isomorphic_rooted(ref_trees[i], trees[i])) {
				std::cerr << "PANIC! Invalid supertree:\nPartition " << i
				          << "\nSupertree: " << as_newick(supertree, names)
				          << "\nExpected: " << as_newick(ref_trees[i], names)
				          << "\nReceived: " << as_newick(trees[i], names)
				          << std::endl;
			}
		}
	}

	// check for isomorphic trees
	std::vector<std::pair<std::vector<simple_bitvector>, terraces::index>> tree_bips;
	for (terraces::index i = 0; i < supertrees.size(); ++i) {
		const auto& supertree = supertrees[i];
		tree_bips.emplace_back(tree_bipartitions(supertree), i);
	}
	std::sort(tree_bips.begin(), tree_bips.end());
	int dupes = 0;
	for (terraces::index i = 1; i < supertrees.size(); ++i) {
		if (tree_bips[i - 1].first == tree_bips[i].first) {
			++dupes;
			std::cerr << "Duplicate tree found:\n"
			          << as_newick(supertrees[tree_bips[i].second], names) << '\n'
			          << as_newick(supertrees[tree_bips[i - 1].second], names)
			          << std::endl;
		}
	}
	std::cout << (supertrees.size() - dupes) << "(" << supertrees.size() << ")";
}

int main(int argc, char** argv) {
	if (argc < 5) {
		std::cerr << "Usage: " << argv[0]
		          << " [treefile] [datafile] [root_node] [use_root_split]\n";
		return -1;
	}

	terraces::index root_node = std::stoul(argv[3]);
	bool use_root_split = bool(std::stoi(argv[4]));

	try {
		auto data_stream = utils::open_ifstream(argv[2]);
		auto data = parse_bitmatrix(data_stream);
		auto tree = parse_nwk(utils::read_file_full(argv[1]), data.indices);
		auto num_leaves = data.matrix.rows();
		name_map number_names;
		for (terraces::index i = 0; i < num_leaves; ++i) {
			number_names.push_back(std::to_string(i));
		}

		std::cout << "Rooting at node " << root_node << "\n";
		auto rerooted_tree = reroot_at_node(tree, root_node);
		std::cout << as_newick(rerooted_tree, number_names) << std::endl;
		auto subtrees = terraces::subtrees(rerooted_tree, data.matrix);
		std::cout << "Per-partition trees\n";
		for (const auto& subtree : subtrees) {
			std::cout << as_newick(subtree, number_names) << "\n";
		}
		auto constraints = compute_constraints(subtrees);
		std::cout << "Constraints\n";
		for (auto c : constraints) {
			std::cout << utils::named_output<terraces::constraints,
			                                 name_map>{c, &number_names}
			          << "\n";
		}
		std::cout << "Removed " << deduplicate_constraints(constraints)
		          << " duplicate constraints\n";
		auto root_split = terraces::root_split(rerooted_tree, num_leaves);
		std::cout << "Root split\n";
		for (auto b : root_split) {
			std::cout << b;
		}
		std::cout << "\n";
		using callback = debug::variants::logging_decorator<variants::multitree_callback>;
		tree_enumerator<callback> e{callback{{}, std::cout, number_names}};
		multitree_node* result;
		if (use_root_split) {
			result = e.run(num_leaves, constraints, root_split);
		} else {
			result = e.run(num_leaves, constraints);
		}
		multitree_iterator mit(result);
		do {
			std::cout << as_newick(mit.tree(), number_names) << "\n";
		} while (mit.next());
	} catch (std::exception& e) {
		std::cerr << "Error: " << e.what() << "\n";
	}
}