-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlossless_decomposition.cpp
103 lines (87 loc) · 2.89 KB
/
lossless_decomposition.cpp
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
#include "lossless_decomposition.hpp"
namespace detail {
int offset_of(const Field& field, const TableHeader& header) {
auto it = std::find(header.begin(), header.end(), field);
return it - header.begin();
}
Row init_row(int row_index, const TableHeader& header) {
Row row(header.size());
for (auto& item: row) {
item.determized = false;
item.row_index = row_index;
}
return row;
}
bool row_equals(const TableHeader& header,
const Row& row1, const Row& row2, const FieldSet& X)
{
return std::all_of(X.begin(), X.end(),
[&row1, &row2, &header](const Field& field) {
int item_offset = offset_of(field, header);
return row1[item_offset] == row2[item_offset];
});
}
bool row_homogenize(const TableHeader& header,
Row& row1, Row& row2, const FieldSet& X) {
bool changed = false;
for (auto& field: X) {
auto offset = offset_of(field, header);
auto& item1 = row1[offset];
auto& item2 = row2[offset];
if (item1.determized ^ item2.determized) {
item1.determized = true;
item2.determized = true;
changed = true;
}
if (!item1.determized && !item2.determized &&
item1.row_index != item2.row_index) {
item2.row_index = item1.row_index;
changed = true;
}
}
return changed;
}
void init_table(Table& table, const TableHeader& header,
const std::vector<FieldSet>& relation_list) {
table.clear();
int row_index = 0;
for (auto& relation: relation_list) {
auto row = init_row(row_index, header);
for (auto& field: relation) {
row[offset_of(field, header)].determized = true;
}
table.push_back(row);
row_index++;
}
}
} // namespace detail
bool is_lossless_decomposition(const FieldSet& U,
const FDSet& F, const std::vector<FieldSet>& relation_list) {
using namespace detail;
// Initialize table
Table table;
TableHeader header;
for (auto& field: U) {
header.push_back(field);
}
init_table(table, header, relation_list);
auto pred = [&table, &header] (const FD& fd) -> bool {
bool changed = false;
for (size_t i = 0; i < table.size() - 1; i++)
for (size_t j = i + 1; j < table.size(); j++) {
if (row_equals(header, table[i], table[j], fd.first)) {
changed = row_homogenize(header, table[i], table[j], fd.second);
}
}
return changed;
};
while (std::any_of(F.begin(), F.end(), pred));
auto satisfy_pred = [](const Row& row) {
return std::all_of(row.begin(), row.end(),
[](const Item& item) { return item.determized; });
};
if (std::any_of(table.begin(), table.end(), satisfy_pred))
return true;
else
return false;
}