7 #ifndef GRAPHGEN_DRAG_COMPRESSOR_H_
8 #define GRAPHGEN_DRAG_COMPRESSOR_H_
13 #include <unordered_set>
93 std::unordered_set<const BinaryDrag<conact>::node*> visited_;
99 for (
auto& t : bd.
roots_) {
111 auto& left = n->left;
112 auto& right = n->right;
113 if (left->isleaf() && right->isleaf()) {
114 if (left->data.eq(right->data)) {
117 n->data = left->data;
118 n->data.action &= right->data.action;
119 left = right =
nullptr;
125 if (visited_.insert(n).second) {
134 std::unordered_set<BinaryDrag<conact>::node*> visited_nodes_;
135 std::unordered_set<BinaryDrag<conact>::node*> visited_leaves_;
136 std::unordered_map<BinaryDrag<conact>::node*, std::vector<BinaryDrag<conact>::node*>> parents_;
140 for (
auto& t : bd.
roots_) {
150 visited_leaves_.insert(n);
154 if (visited_nodes_.insert(n).second) {
155 parents_[n->left].push_back(n);
156 parents_[n->right].push_back(n);
164 for (
const auto& l : visited_leaves_) {
165 for (
const auto& a : l->data.actions()) {
168 os <<
"- " << l->data.next <<
"\n";
174 std::unordered_set<BinaryDrag<conact>::node*> already_updated;
176 for(
auto& i : visited_leaves_){
178 if (i->data.actions().size() != 1 || already_updated.find(i) != end(already_updated)){
185 for (
auto& j : visited_leaves_){
190 if (already_updated.find(j) != end(already_updated)) {
194 if ((i->data.action & j->data.action) != 0 && i->data.next == j->data.next) {
198 already_updated.insert(j);
201 for (
auto& x : parents_[j]) {
205 else if (x->right == j) {
223 PRINT_STATUS_BAR = 1,
228 SAVE_INTERMEDIATE_RESULTS = 4,
239 bool early_stopping_active_;
240 bool early_stopping_reached_ =
false;
242 int iterations_left_;
244 size_t progress_counter_ = 0;
245 size_t best_nodes_ = std::numeric_limits<size_t >::max();
246 size_t best_leaves_ = std::numeric_limits<size_t >::max();
251 if (print_status_bar) {
252 std::cout <<
"\r" << progress_counter_ <<
"\n";
260 early_stopping_active_ = iterations != -1;
261 iterations_left_ = iterations_max_ = iterations;
262 TLOG(
"Compressing BinaryDrag",
266 FastDragOptimizerRec(bd, flags);
271 UpdateProgress(flags);
276 iterations_left_ = iterations_max_;
277 early_stopping_reached_ =
false;
282 early_stopping_active_ = iterations != -1;
283 iterations_left_ = iterations_max_ = iterations;
289 FastDragOptimizerRec(lfh.
f_, flags);
293 UpdateProgress(flags);
298 progress_counter_ = 0;
306 FastDragOptimizerRec(f, flags);
310 UpdateProgress(flags);)
317 best_nodes_ = std::numeric_limits<size_t >::max();
318 best_leaves_ = std::numeric_limits<size_t >::max();
322 struct MergeEquivalentTreesAndUpdate {
323 std::unordered_set<BinaryDrag<conact>::node*> visited_;
324 std::unordered_map<BinaryDrag<conact>::node*, std::vector<BinaryDrag<conact>::node*>>& parents_;
331 MergeEquivalentTreesAndUpdateRec(a, b);
336 auto it = visited_.find(a);
337 if (it != end(visited_))
341 for (
auto& x : parents_[b]) {
349 a->data.action &= b->data.action;
352 MergeEquivalentTreesAndUpdateRec(a->left, b->left);
353 MergeEquivalentTreesAndUpdateRec(a->right, b->right);
362 if (early_stopping_reached_ && early_stopping_active_) {
372 std::vector<CollectDragStatistics::STreeProp> trees;
374 for (
const auto& x : cds.np_) {
375 trees.push_back(x.second);
379 for (
size_t i = 0; i < trees.size(); ) {
380 if (ignore_leaves && trees[i].conditions_ ==
".") {
381 trees.erase(begin(trees) + i);
386 for (
size_t j = 0; j < trees.size(); ++j) {
387 if (i != j && trees[i].equivalent(trees[j])) {
395 trees.erase(begin(trees) + i);
413 for (
size_t i = 0; i < trees.size(); ++i) {
416 for (j = i + 1; j < trees.size(); ++j) {
417 if (trees[i].equivalent(trees[j])) {
426 std::vector<BinaryDrag<conact>::node*> tracked_nodes{ trees[i].n_, trees[j].n_ };
434 MergeEquivalentTreesAndUpdate(tracked_nodes[0], tracked_nodes[1], cds.parents_);
444 FastDragOptimizerRec(bd_copy, flags);
452 if (print_status_bar) {
453 if (progress_counter_ % 1000 == 0) {
454 std::cout <<
"\r" << progress_counter_ << std::flush;
458 if (--iterations_left_ <= 0) {
459 early_stopping_reached_ =
true;
463 if (bds.Nodes() < best_nodes_) {
466 iterations_left_ = iterations_max_;
474 best_nodes_ = bds.Nodes();
475 best_leaves_ = bds.Leaves();
479 if (save_intermediate_results) {
484 if (print_status_bar) {
485 std::cout <<
"\r" << progress_counter_ <<
" - nodes: " << bds.Nodes() <<
"; leaves: " << bds.Leaves() <<
"\n";
std::vector< node * > roots_
Calculates the statistics of a binary drag with one or multiple roots.
void UpdateProgress(DragCompressorFlags flags)
DragCompressor(BinaryDrag< conact > &bd, int iterations=-1, DragCompressorFlags flags=DragCompressorFlags::PRINT_STATUS_BAR|DragCompressorFlags::IGNORE_LEAVES)
DragCompressor(LineForestHandler &lfh, int iterations=-1, DragCompressorFlags flags=DragCompressorFlags::PRINT_STATUS_BAR|DragCompressorFlags::IGNORE_LEAVES)
void SerializeVisitedLeaves(std::ostream &os=std::cout)
void CalculateStatsRec(BinaryDrag< conact >::node *&n)
MergeLeaves(BinaryDrag< conact > &bd)
void MergeSpecialLeavesRec(BinaryDrag< conact >::node *n)
MergeSpecialLeaves(BinaryDrag< conact > &bd)
DragCompressorFlags
This enum class defines the available flags for the DragCompression class.
@ SAVE_INTERMEDIATE_RESULTS
Whether to delete or not the dot code used to draw the drag.
@ IGNORE_LEAVES
Whether to ignore leaves or not during the compression. Please note that compressing the leaves will ...
@ PRINT_STATUS_BAR
Whether to print a sort of progress bar or not.
bool DrawDagOnFile(const string &base_filename, const BinaryDrag< conact > &t, DrawDagFlags flags)
std::string algorithm_name_
Generates all the forests needed to handle one line of the image.
std::vector< BinaryDrag< conact > > end_forests_
This class allows to "remove" equal subtrees from a BinaryDrag.
#define TLOG(message, instructions)
std::string zerostr(const T &val, size_t n)
#define DEFINE_ENUM_CLASS_FLAGS(class_name,...)