File: validation.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 (73 lines) | stat: -rw-r--r-- 2,171 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
#include <numeric>
#include <unordered_map>

#include <algorithm>

#include "ranked_bitvector.hpp"
#include "supertree_helpers.hpp"
#include "trees_impl.hpp"
#include "validation.hpp"

namespace terraces {

std::vector<simple_bitvector> tree_bipartitions(const tree& t) {
	std::vector<simple_bitvector> bips(t.size(), {0, {}});
	std::vector<simple_bitvector> subtrees(t.size(), {(t.size() + 1) / 2, {}});
	foreach_postorder(t, [&](index i) {
		auto n = t[i];
		if (is_leaf(n)) {
			subtrees[i].set(n.taxon());
		} else {
			subtrees[i].set_bitwise_or(subtrees[n.lchild()], subtrees[n.rchild()]);
		}
	});
	foreach_preorder(t, [&](index i) {
		auto n = t[i];
		bool at_root = is_root(n);
		bool at_rhs_of_root =
		        !at_root && (is_root(t[n.parent()]) && t[n.parent()].rchild() == i);
		if (!(at_root || at_rhs_of_root)) {
			if (subtrees[i].get(0)) {
				subtrees[i].invert();
			}
			bips[i] = std::move(subtrees[i]);
		}
	});
	bips[t[0].rchild()] = std::move(subtrees[t[0].rchild()]);
	bips[t[0].rchild()].blank();
	bips[0] = std::move(subtrees[0]);
	bips[0].blank();
	std::sort(bips.begin(), bips.end());
	return bips;
}

bool is_isomorphic_unrooted(const tree& fst, const tree& snd) {
	assert(fst.size() == snd.size());

	auto fst_bip = tree_bipartitions(fst);
	auto snd_bip = tree_bipartitions(snd);

	return fst_bip == snd_bip;
}

bool is_isomorphic_rooted_impl(const tree& fst, const tree& snd, index fst_idx, index snd_idx) {
	auto fst_node = fst[fst_idx];
	auto snd_node = snd[snd_idx];
	if (is_leaf(fst_node) != is_leaf(snd_node)) {
		return false;
	} else if (is_leaf(fst_node)) {
		return fst_node.taxon() == snd_node.taxon();
	}

	return (is_isomorphic_rooted_impl(fst, snd, fst_node.lchild(), snd_node.lchild()) &&
	        is_isomorphic_rooted_impl(fst, snd, fst_node.rchild(), snd_node.rchild())) ||
	       (is_isomorphic_rooted_impl(fst, snd, fst_node.lchild(), snd_node.rchild()) &&
	        is_isomorphic_rooted_impl(fst, snd, fst_node.rchild(), snd_node.lchild()));
}

bool is_isomorphic_rooted(const tree& fst, const tree& snd) {
	assert(fst.size() == snd.size());
	return is_isomorphic_rooted_impl(fst, snd, 0, 0);
}

} // namespace terraces