3 #include <carl-arith/constraint/Conversion.h>
4 #include <carl-arith/ran/Conversion.h>
6 #include <carl-common/util/streamingOperators.h>
11 using carl::operator<<;
13 namespace formula_ds {
16 template<
class... Ts>
struct overloaded : Ts... {
using Ts::operator()...; };
23 stream << std::string(level,
' ') <<
"TRUE";
26 stream << std::string(level,
' ') <<
"FALSE";
29 stream << std::string(level,
' ') <<
"NOT(" << std::endl;
30 print(stream, db, c.subformula, level+1);
31 stream << std::endl << std::string(level,
' ') <<
")";
34 stream << std::string(level,
' ') <<
"AND(" << std::endl;
35 for (
const auto subformula : c.subformulas) {
36 print(stream, db, subformula, level+1);
39 stream << std::string(level,
' ') <<
")";
42 stream << std::string(level,
' ') <<
"OR(" << std::endl;
43 for (
const auto subformula : c.subformulas) {
44 print(stream, db, subformula, level+1);
47 stream << std::string(level,
' ') <<
")";
50 stream << std::string(level,
' ') <<
"IFF(" << std::endl;
51 for (
const auto subformula : c.subformulas) {
52 print(stream, db, subformula, level+1);
55 stream << std::string(level,
' ') <<
")";
58 stream << std::string(level,
' ') <<
"XOR(" << std::endl;
59 for (
const auto subformula : c.subformulas) {
60 print(stream, db, subformula, level+1);
63 stream << std::string(level,
' ') <<
")";
66 stream << std::string(level,
' ') << c.variable;
69 stream << std::string(level,
' ') << c.constraint;
73 std::size_t spacing = 50 - level;
74 if (level > 50) spacing = 4;
76 stream << std::string(spacing,
' ') <<
"id: " <<
id <<
" T: " << db[id].reasons_true <<
" F: " << db[id].reasons_false;
90 auto cache_it = cache.find(f.id());
91 if (cache_it != cache.end())
return cache_it->second;
94 assert(db.size() < std::numeric_limits<FormulaID>::max());
96 if (f.id() > f.negated().id()) {
98 db.emplace_back(
NOT{ child });
99 db[child].parents.insert((
FormulaID)(db.size()-1));
100 cache.emplace(f.id(), (
FormulaID)(db.size()-1));
106 auto id =
to_formula_db(c,
FormulaT(
carl::FormulaType::OR,
FormulaT(
carl::FormulaType::AND, f.condition(), f.first_case()),
FormulaT(
carl::FormulaType::AND, f.condition().negated(), f.second_case())), db, vartof, cache);
107 cache.emplace(f.id(),
id);
110 case carl::FormulaType::TRUE: {
111 db.emplace_back(
TRUE{ });
112 cache.emplace(f.id(), (
FormulaID)(db.size()-1));
115 case carl::FormulaType::FALSE: {
116 db.emplace_back(
FALSE{ });
117 cache.emplace(f.id(), (
FormulaID)(db.size()-1));
121 auto child =
to_formula_db(c,f.subformula(),db,vartof, cache);
122 db.emplace_back(
NOT{ child });
123 db[child].parents.insert((
FormulaID)(db.size()-1));
124 cache.emplace(f.id(), (
FormulaID)(db.size()-1));
127 case carl::FormulaType::IMPLIES: {
129 cache.emplace(f.id(),
id);
133 std::vector<FormulaID> subformulas;
134 for (
const auto& sf : f.subformulas()) {
135 subformulas.emplace_back(
to_formula_db(c,sf, db, vartof, cache));
137 db.emplace_back(
AND{ subformulas });
138 for (
const auto child : subformulas) {
139 db[child].parents.insert((
FormulaID)(db.size()-1));
141 cache.emplace(f.id(), (
FormulaID)(db.size()-1));
145 std::vector<FormulaID> subformulas;
146 for (
const auto& sf : f.subformulas()) {
147 subformulas.emplace_back(
to_formula_db(c,sf, db, vartof, cache));
149 db.emplace_back(
OR{ subformulas });
150 for (
const auto child : subformulas) {
151 db[child].parents.insert((
FormulaID)(db.size()-1));
153 cache.emplace(f.id(), (
FormulaID)(db.size()-1));
157 std::vector<FormulaID> subformulas;
158 for (
const auto& sf : f.subformulas()) {
159 subformulas.emplace_back(
to_formula_db(c,sf, db, vartof, cache));
161 db.emplace_back(
XOR{ subformulas });
162 for (
const auto child : subformulas) {
163 db[child].parents.insert((
FormulaID)(db.size()-1));
165 cache.emplace(f.id(), (
FormulaID)(db.size()-1));
169 std::vector<FormulaID> subformulas;
170 for (
const auto& sf : f.subformulas()) {
171 subformulas.emplace_back(
to_formula_db(c,sf, db, vartof, cache));
173 db.emplace_back(
IFF{ subformulas });
174 for (
const auto child : subformulas) {
175 db[child].parents.insert((
FormulaID)(db.size()-1));
177 cache.emplace(f.id(), (
FormulaID)(db.size()-1));
180 case carl::FormulaType::CONSTRAINT: {
181 auto bc = carl::convert<cadcells::Polynomial>(c.
polys().context(), f.constraint().constr());
183 auto var = bc.lhs().main_var();
184 vartof.try_emplace(
var).first->second.push_back((
FormulaID)(db.size()-1));
185 cache.emplace(f.id(), (
FormulaID)(db.size()-1));
188 case carl::FormulaType::BOOL: {
189 db.emplace_back(
BOOL{ f.boolean() });
190 vartof.try_emplace(f.boolean()).first->second.push_back((
FormulaID)(db.size()-1));
191 cache.emplace(f.id(), (
FormulaID)(db.size()-1));
196 db.emplace_back(
FALSE{});
197 cache.emplace(f.id(), (
FormulaID)(db.size()-1));
206 if (a.size() == b.size()) {
207 auto it_a = a.begin();
208 auto it_b = b.begin();
209 while (it_a != a.end() && *it_a == *it_b) {
210 assert(it_b != b.end());
214 return (it_a == a.end()) ?
EQ :
NONE;
215 }
else if (a.size() < b.size()) {
223 for (
auto s = set.begin(); s != set.end(); ) {
242 for (
const auto& add : adds) {
243 bool redundant =
false;
244 for (
auto s = set.begin(); s != set.end(); ) {
259 if (!redundant) to_add.push_back(add);
261 if (to_add.empty())
return false;
263 set.insert(set.end(), to_add.begin(), to_add.end());
270 result.reserve(a.size()+b.size());
271 auto first1 = a.begin();
272 auto last1 = a.end();
273 auto first2 = b.begin();
274 auto last2 = b.end();
275 auto d_first = std::back_inserter(
result);
276 for (; first1 != last1; ++d_first) {
277 if (first2 == last2) {
281 if (*first2 < *first1) {
284 }
else if (*first2 > *first1) {
300 for (
const auto& ar : a) {
301 for (
const auto& br : b) {
309 std::vector<FormulaID>
tru;
317 for (
const auto f : formulas) {
318 auto sub_val = db[f].valuation();
320 subs.
fals.push_back(f);
322 subs.
tru.push_back(f);
324 subs.
multi.push_back(f);
327 subs.
confl.push_back(f);
341 #ifdef SMTRAT_DEVOPTION_Expensive
349 auto val =
db[id].valuation();
350 auto sub_val =
db[c.subformula].valuation();
366 auto val =
db[id].valuation();
371 if (!subs.fals.empty()) {
372 for (
const auto& subformula : subs.fals) {
375 }
else if (subs.confl.empty() && subs.multi.empty() && subs.fals.empty()) {
377 reasons.emplace_back();
378 for (
const auto& subformula : subs.tru) {
388 for (
const auto subformula : subs.multi) {
392 if (subs.multi.size() == 1 && subs.confl.empty() && subs.fals.empty()) {
394 for (
const auto& subformula : subs.tru) {
403 auto val =
db[id].valuation();
408 if (!subs.tru.empty()) {
409 for (
const auto& subformula : subs.tru) {
412 }
else if (subs.confl.empty() && subs.multi.empty() && subs.tru.empty()) {
414 reasons.emplace_back();
415 for (
const auto& subformula : subs.fals) {
425 if (subs.multi.size() == 1 && subs.confl.empty() && subs.tru.empty()) {
427 for (
const auto& subformula : subs.fals) {
433 for (
const auto subformula : subs.multi) {
441 auto val =
db[id].valuation();
445 if (!subs.tru.empty() && !subs.fals.empty()) {
447 for (
const auto t : subs.tru) {
448 for (
const auto f : subs.fals) {
454 }
else if (subs.multi.empty() && !subs.tru.empty()) {
456 reasons.emplace_back();
457 for (
const auto t : subs.tru) {
461 }
else if (subs.multi.empty() && !subs.fals.empty()) {
463 reasons.emplace_back();
464 for (
const auto f : subs.fals) {
474 for (
const auto t : subs.tru) {
475 for (
const auto sub : c.subformulas) {
476 auto sub_val =
db[sub].valuation();
482 for (
const auto f : subs.fals) {
483 for (
const auto sub : c.subformulas) {
484 auto sub_val =
db[sub].valuation();
491 if (subs.multi.size() == 1 && (subs.tru.empty() || subs.fals.empty())) {
492 if (subs.tru.empty()) {
494 for (
const auto f : subs.fals) {
499 assert(subs.fals.empty());
501 for (
const auto t : subs.tru) {
511 auto val =
db[id].valuation();
514 if (subs.confl.empty() && (subs.multi.empty() || subs.multi.size() == 1)) {
516 reasons.emplace_back();
517 for (
const auto subformula : subs.tru) {
520 for (
const auto subformula : subs.fals) {
525 if (subs.multi.empty() && subs.confl.empty()) {
526 if (subs.tru.size() % 2 != 0) {
535 if (subs.multi.size() == 1 && subs.confl.empty()) {
536 bool value = (subs.tru.size() % 2 != 0);
560 SMTRAT_LOG_FUNC(
"smtrat.covering_ng.evaluation",
id <<
", " << is_true);
561 #ifdef SMTRAT_DEVOPTION_Expensive
566 db[id].reasons_true.emplace_back();
569 db[id].reasons_false.emplace_back();
575 SMTRAT_LOG_FUNC(
"smtrat.covering_ng.evaluation",
id <<
", " << is_true);
576 #ifdef SMTRAT_DEVOPTION_Expensive
591 for (
const auto parent :
db[
id].parents) {
604 for (
const auto parent :
db[
id].parents) {
625 for (
auto reason = f.reasons_true.begin(); reason != f.reasons_true.end(); ) {
626 if (std::binary_search(reason->begin(), reason->end(), std::make_pair(
id, is_true))) {
627 reason = f.reasons_true.erase(reason);
632 for (
auto reason = f.reasons_false.begin(); reason != f.reasons_false.end(); ) {
633 if (std::binary_search(reason->begin(), reason->end(), std::make_pair(
id, is_true))) {
634 reason = f.reasons_false.erase(reason);
640 if (f.reasons_true.empty() || f.reasons_false.empty()) {
649 for (
const auto& [k,v] : new_ass) {
650 if (old_ass.find(k) == old_ass.end())
return k;
652 return carl::Variable::NO_VARIABLE;
657 inline carl::BasicConstraint<Poly>
normalize(
const carl::BasicConstraint<Poly>& c) {
658 assert(c.relation() == carl::Relation::LESS || c.relation() == carl::Relation::LEQ || c.relation() ==
carl::Relation::EQ || c.relation() == carl::Relation::NEQ);
659 return carl::BasicConstraint<Poly>(c.lhs().normalize(), carl::is_negative(c.lhs().lcoeff()) ? carl::turn_around(c.relation()) : c.relation());
669 void set(carl::Relation rel) {
671 else if (rel == carl::Relation::NEQ)
NEQ =
true;
672 else if (rel == carl::Relation::LESS)
LESS =
true;
673 else if (rel == carl::Relation::LEQ)
LEQ =
true;
674 else if (rel == carl::Relation::GREATER)
GREATER =
true;
675 else if (rel == carl::Relation::GEQ)
GEQ =
true;
680 std::vector<ConstraintT> constraints;
681 carl::arithmetic_constraints(f, constraints);
682 boost::container::flat_map<Poly,PolyInfo> info;
683 for (
const auto& c : constraints) {
685 info.try_emplace(constr.lhs()).first->second.set(constr.relation());
688 std::vector<FormulaT> lemmas;
689 for (
const auto& [poly,rels] : info) {
690 if ((rels.LESS || rels.GEQ) && (rels.GREATER || rels.LEQ)) {
693 if ((rels.LESS || rels.GEQ) && (rels.EQ || rels.NEQ)) {
696 if ((rels.GREATER || rels.LEQ) && (rels.EQ || rels.NEQ)) {
699 if ((rels.LESS || rels.GEQ) && (rels.GREATER || rels.LEQ) && (rels.EQ || rels.NEQ)) {
718 std::map<std::size_t,formula_ds::FormulaID> cache;
724 if (
var.type() == carl::VariableType::VT_REAL) {
726 const auto& constr_a = std::get<formula_ds::CONSTRAINT>(true_graph.db[a].content).constraint;
727 const auto& constr_b = std::get<formula_ds::CONSTRAINT>(true_graph.db[b].content).constraint;
728 return m_constraint_complexity_ordering(m_proj, constr_a, constr_b);
739 if (std::holds_alternative<formula_ds::TRUE>(
true_graph.
db[i].content)) {
742 if (std::holds_alternative<formula_ds::FALSE>(
true_graph.
db[i].content)) {
749 if (std::holds_alternative<formula_ds::TRUE>(
false_graph.
db[i].content)) {
752 if (std::holds_alternative<formula_ds::FALSE>(
false_graph.
db[i].content)) {
761 std::optional<formula_ds::FormulaID> next_dec_id;
762 for (
const auto& [k,vs] :
vartof) {
764 for (
const auto& v : vs) {
765 if (graph.
db[v].reasons_true.empty() && graph.
db[v].reasons_false.empty()) {
770 if (next_dec_id)
break;
776 if (true_conflicts.empty()) {
777 true_conflicts =
explore(graph);
780 if (true_conflicts.empty()) {
786 if (false_conflicts.empty()) {
787 false_conflicts =
explore(graph);
790 if (false_conflicts.empty()) {
796 std::erase(conflict, std::make_pair(*next_dec_id,
true));
797 std::erase(conflict, std::make_pair(*next_dec_id,
false));
806 if (
var == carl::Variable::NO_VARIABLE)
return;
809 if (atoms ==
vartof.end())
return;
811 for (
const auto id : atoms->second) {
812 const auto& constr = std::get<formula_ds::CONSTRAINT>(
true_graph.
db[
id].content).constraint;
815 SMTRAT_LOG_TRACE(
"smtrat.covering_ng.evaluation",
"Evaluate constraint " << constr);
817 if (!boost::indeterminate(res)) {
855 if (
var == carl::Variable::NO_VARIABLE)
return;
857 if (atomset ==
vartof.end())
return;
859 for (
const auto id : atomset->second) {
864 if (std::binary_search(iter->begin(), iter->end(), std::make_pair(
id,
m_decisions[
id]))) {
872 if (std::binary_search(iter->begin(), iter->end(), std::make_pair(
id,
m_decisions[
id]))) {
887 boost::container::flat_set<cadcells::Constraint> implicant;
888 for (
const auto& e : i) {
889 implicant.insert(proj.
polys()(e));
891 std::vector<cadcells::Polynomial> equations;
892 for (
const auto& c : implicant) {
894 equations.emplace_back(c.lhs());
897 if (equations.size()>1) {
898 equations = carl::groebner_basis(equations);
899 for (
auto it = implicant.begin(); it != implicant.end(); ) {
901 it = implicant.erase(it);
906 for (
const auto& poly : equations) {
911 for (
const auto& e : implicant) {
912 i.insert(proj.
polys()(e));
919 std::vector<boost::container::flat_set<cadcells::datastructures::PolyConstraint>> implicants;
920 for (
const auto& r : reasons) {
921 implicants.emplace_back();
922 for (
const auto& c : r) {
924 implicants.back().insert(std::get<formula_ds::CONSTRAINT>(
true_graph.
db[c.first].content).constraint);
936 implicants.erase(implicants.begin() + 1, implicants.end());
940 implicants.erase(implicants.begin() +
m_results, implicants.end());
944 for (
auto& implicant : implicants) {
Encapsulates all computations on polynomials.
RAN evaluate(const Assignment &sample, IndexedRoot r)
PolyConstraint negation(const PolyConstraint &constraint) const
auto main_var(PolyRef p) const
void sort(T *array, int size, LessThan lt)
static void copy(const T &from, T &to)
carl::Assignment< RAN > Assignment
bool includes(const VariableRange &superset, const carl::Variables &subset)
carl::Formula< Poly > FormulaT
carl::Constraint< Poly > ConstraintT
#define SMTRAT_LOG_TRACE(channel, msg)
#define SMTRAT_LOG_FUNC(channel, args)
#define SMTRAT_STATISTICS_CALL(function)