3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-30 04:15:51 +00:00
z3/src/math/lp/explanation.h
Lev Nachmanson 97b480ded3
Expl (#4462)
* cleaner API for explanation

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* remove an unnecessery check

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* expl

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
2020-05-24 17:06:39 -07:00

112 lines
3.1 KiB
C++

/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
<name>
Abstract:
<abstract>
Author:
Nikolaj Bjorner (nbjorner)
Lev Nachmanson (levnach)
Revision History:
--*/
#pragma once
#include "math/lp/lp_utils.h"
#include "util/map.h"
#include "util/hashtable.h"
namespace lp {
class explanation {
typedef vector<std::pair<unsigned, mpq>> pair_vec;
typedef hashtable<unsigned, u_hash, u_eq> ci_set;
// Only one of the fields below is used. The first call adding an entry decides which one it is.
vector<std::pair<constraint_index, mpq>> m_vector;
ci_set m_set;
public:
explanation() {}
template <typename T>
explanation(const T& t) {
for (unsigned c : t)
push_back(c);
}
void clear() { m_vector.clear(); m_set.reset(); }
void add_pair(constraint_index j, const mpq& v) {
SASSERT(m_set.empty());
m_vector.push_back(std::make_pair(j, v));
}
// this signature is needed to use it in a template that also works for the vector type
void push_back(constraint_index j) {
SASSERT(m_vector.empty());
m_set.insert(j);
}
void add_expl(const explanation& e) {
if (e.m_vector.empty()) {
for (constraint_index j : e.m_set)
push_back(j);
} else {
for (const auto & p : e.m_vector) {
add_pair(p.first, p.second);
}
}
}
bool empty() const { return m_vector.empty() || m_set.empty(); }
size_t size() const { return std::max(m_vector.size(), m_set.size()); }
class cimpq {
constraint_index m_var;
const mpq& m_coeff;
public:
cimpq(constraint_index var, const mpq & val) : m_var(var), m_coeff(val) { }
constraint_index ci() const { return m_var; }
const mpq &coeff() const { return m_coeff; }
};
class iterator {
bool m_run_on_vector;
pair_vec::const_iterator m_vi;
ci_set::iterator m_ci;
public:
cimpq operator*() const {
return m_run_on_vector?
cimpq( m_vi->first, m_vi->second) :
cimpq( *m_ci, one_of_type<mpq>());
}
iterator operator++() {
if (m_run_on_vector)
m_vi++;
else
m_ci++;
return *this;
}
iterator operator++(int) {
iterator i = *this; ++(*this); return i;
}
iterator(bool run_on_vector, pair_vec::const_iterator vi, ci_set::iterator cii) :
m_run_on_vector(run_on_vector), m_vi(vi), m_ci(cii)
{}
bool operator==(const iterator &other) const {
SASSERT(m_run_on_vector == other.m_run_on_vector);
return m_run_on_vector? m_vi == other.m_vi : m_ci == other.m_ci;
}
bool operator!=(const iterator &other) const { return !(*this == other); }
};
iterator begin() const {
return iterator( !m_vector.empty(), m_vector.begin(), m_set.begin());
}
iterator end() const {
return iterator(!m_vector.empty(), m_vector.end(), m_set.end());
}
};
}