From b10f2529fa106205fc99d7e3eec8aa80bfb487ce Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 17 Aug 2018 20:26:51 +0300 Subject: [PATCH] Merge and conditions if they only differ in one sub-condition --- source/condition.cpp | 80 ++++++++++++++++++++++++++++++++++++++++++-- source/condition.h | 5 +++ 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/source/condition.cpp b/source/condition.cpp index e9400c4..5978250 100644 --- a/source/condition.cpp +++ b/source/condition.cpp @@ -216,7 +216,7 @@ Condition *AndCondition::flatten(OrCondition *cond1, Condition *cond2) const unsigned count = cond1->count(); for(unsigned i=0; iget(i).clone(), (i+1clone() : cond2))) - result->add(sub); + add_merged_to(sub, result, true); delete cond1; if(result->is_viable()) @@ -239,7 +239,7 @@ Condition *AndCondition::flatten(OrCondition *cond1, OrCondition *cond2) const for(unsigned i=0; iget(i).clone(), cond2->get(j).clone())) - result->add(sub); + add_merged_to(sub, result, true); delete cond1; delete cond2; @@ -251,6 +251,82 @@ Condition *AndCondition::flatten(OrCondition *cond1, OrCondition *cond2) const return 0; } +bool AndCondition::can_merge(const Condition &other, const CompoundCondition &parent) const +{ + const AndCondition *other_and = dynamic_cast(&other); + if(!other_and || !dynamic_cast(&parent)) + return false; + + return merge(*this, *other_and, parent, 0); +} + +AndCondition *AndCondition::merge(const vector &conds, const CompoundCondition &parent) const +{ + if(conds.size()!=2) + return 0; + + const AndCondition *and1 = dynamic_cast(conds[0]); + const AndCondition *and2 = dynamic_cast(conds[1]); + if(!and1 || !and2 || !dynamic_cast(&parent)) + return 0; + + AndCondition *result = 0; + merge(*and1, *and2, parent, &result); + return result; +} + +bool AndCondition::merge(const AndCondition &cond1, const AndCondition &cond2, const CompoundCondition &parent, AndCondition **result) +{ + if(cond1.count()!=cond2.count()) + return false; + + int merge1 = -1; + vector used(cond1.count(), false); + for(unsigned i=0; i=0) + used[match] = true; + else if(merge1<0) + merge1 = i; + else + return false; + } + + if(merge1>=0) + { + vector merge_conds(2, 0); + merge_conds[0] = &cond1.get(merge1); + for(unsigned i=0; (!merge_conds[1] && ican_merge(*merge_conds[1], parent)) + return false; + + if(result) + { + *result = new AndCondition; + (*result)->add(merge_conds[0]->merge(merge_conds, parent)); + } + } + else if(result) + *result = new AndCondition; + + if(result) + { + for(unsigned i=0; iadd(cond2.get(i).clone()); + } + + return true; +} + bool AndCondition::is_viable() const { for(vector::const_iterator i=conditions.begin(); i!=conditions.end(); ++i) diff --git a/source/condition.h b/source/condition.h index 9d945c7..6b0cf6b 100644 --- a/source/condition.h +++ b/source/condition.h @@ -74,6 +74,11 @@ protected: virtual Condition *flatten(OrCondition *, Condition *) const; virtual Condition *flatten(OrCondition *, AndCondition *) const; virtual Condition *flatten(OrCondition *, OrCondition *) const; +public: + virtual bool can_merge(const Condition &, const CompoundCondition &) const; + virtual AndCondition *merge(const std::vector &, const CompoundCondition &) const; +private: + static bool merge(const AndCondition &, const AndCondition &, const CompoundCondition &, AndCondition **); public: virtual bool is_viable() const; virtual void add_lines(std::list &) const; -- 2.43.0