mirror of
https://github.com/Z3Prover/z3
synced 2025-04-30 20:35:51 +00:00
Merge branch 'master' of https://github.com/z3prover/z3 into polysat
This commit is contained in:
commit
57df45dc16
162 changed files with 2885 additions and 1941 deletions
|
@ -26,9 +26,6 @@ class pdd_eval {
|
|||
std::function<rational (unsigned)> m_var2val;
|
||||
|
||||
public:
|
||||
|
||||
pdd_eval() {}
|
||||
|
||||
std::function<rational (unsigned)>& var2val() { return m_var2val; } // setter
|
||||
const std::function<rational (unsigned)>& var2val() const { return m_var2val; } // getter
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ class simplifier {
|
|||
public:
|
||||
|
||||
simplifier(solver& s): s(s) {}
|
||||
~simplifier() {}
|
||||
|
||||
void operator()();
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@ namespace lp {
|
|||
lia_move cut(lar_term & t, mpq & k, explanation* ex, unsigned basic_inf_int_j, const row_strip<mpq>& row);
|
||||
public:
|
||||
gomory(int_solver& lia);
|
||||
~gomory() {}
|
||||
lia_move operator()();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ namespace lp {
|
|||
|
||||
public:
|
||||
int_branch(int_solver& lia);
|
||||
~int_branch() {}
|
||||
lia_move operator()();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ namespace lp {
|
|||
impq get_cube_delta_for_term(const lar_term& t) const;
|
||||
public:
|
||||
int_cube(int_solver& lia);
|
||||
~int_cube() {}
|
||||
lia_move operator()();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ Accumulative:
|
|||
- Otherwise accumulate x = (c1 * lcm(b1,b2) / b2) + (c2 * lcm(b1,b2) / b1) mod lcm(b,b2)
|
||||
and accumulate the rows from R1, R2
|
||||
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "math/lp/int_solver.h"
|
||||
|
@ -53,10 +55,7 @@ namespace lp {
|
|||
int_gcd_test::int_gcd_test(int_solver& lia): lia(lia), lra(lia.lra), m_next_gcd(0), m_delay(0) {}
|
||||
|
||||
bool int_gcd_test::should_apply() {
|
||||
|
||||
if (!lia.settings().int_run_gcd_test())
|
||||
return false;
|
||||
return true;
|
||||
return lia.settings().int_run_gcd_test();
|
||||
}
|
||||
|
||||
lia_move int_gcd_test::operator()() {
|
||||
|
@ -76,18 +75,36 @@ namespace lp {
|
|||
}
|
||||
|
||||
bool int_gcd_test::gcd_test() {
|
||||
reset_test();
|
||||
const auto & A = lra.A_r(); // getting the matrix
|
||||
for (unsigned i = 0; i < A.row_count(); i++)
|
||||
for (unsigned i = 0; i < A.row_count(); i++) {
|
||||
unsigned basic_var = lra.r_basis()[i];
|
||||
if (!lia.column_is_int(basic_var))
|
||||
continue;
|
||||
if (lia.get_value(basic_var).is_int())
|
||||
continue;
|
||||
if (!gcd_test_for_row(A, i))
|
||||
return false;
|
||||
mark_visited(i);
|
||||
}
|
||||
for (unsigned i = m_inserted_vars.size(); i-- > 0; ) {
|
||||
unsigned j = m_inserted_vars[i];
|
||||
for (const auto & c : lra.get_column(j)) {
|
||||
unsigned r = c.var();
|
||||
if (is_visited(r))
|
||||
continue;
|
||||
mark_visited(r);
|
||||
if (!gcd_test_for_row(A, r))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static mpq get_denominators_lcm(const row_strip<mpq> & row) {
|
||||
mpq r(1);
|
||||
for (auto & c : row) {
|
||||
for (auto & c : row)
|
||||
r = lcm(r, denominator(c.coeff()));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -95,44 +112,50 @@ namespace lp {
|
|||
auto const& row = A.m_rows[i];
|
||||
unsigned basic_var = lra.r_basis()[i];
|
||||
|
||||
if (!lia.column_is_int(basic_var) || lia.get_value(basic_var).is_int())
|
||||
if (!lia.column_is_int(basic_var))
|
||||
return true;
|
||||
mpq lcm_den = get_denominators_lcm(row);
|
||||
mpq consts(0);
|
||||
m_lcm_den = get_denominators_lcm(row);
|
||||
m_consts = 0;
|
||||
mpq gcds(0);
|
||||
mpq least_coeff(0);
|
||||
bool least_coeff_is_bounded = false;
|
||||
unsigned j;
|
||||
m_least_coeff = 0;
|
||||
bool least_coeff_is_bounded = false;
|
||||
bool least_coeff_is_unique = false;
|
||||
unsigned least_coeff_index = 0;
|
||||
for (auto &c : A.m_rows[i]) {
|
||||
j = c.var();
|
||||
unsigned j = c.var();
|
||||
const mpq& a = c.coeff();
|
||||
if (lra.column_is_fixed(j)) {
|
||||
mpq aux = lcm_den * a;
|
||||
consts += aux * lra.column_lower_bound(j).x;
|
||||
mpq aux = m_lcm_den * a;
|
||||
m_consts += aux * lra.column_lower_bound(j).x;
|
||||
}
|
||||
else if (lra.column_is_real(j)) {
|
||||
return true;
|
||||
}
|
||||
else if (gcds.is_zero()) {
|
||||
gcds = abs(lcm_den * a);
|
||||
least_coeff = gcds;
|
||||
gcds = abs(m_lcm_den * a);
|
||||
m_least_coeff = gcds;
|
||||
least_coeff_is_bounded = lra.column_is_bounded(j);
|
||||
least_coeff_is_unique = true;
|
||||
least_coeff_index = j;
|
||||
}
|
||||
else {
|
||||
mpq aux = abs(lcm_den * a);
|
||||
mpq aux = abs(m_lcm_den * a);
|
||||
gcds = gcd(gcds, aux);
|
||||
if (aux < least_coeff) {
|
||||
least_coeff = aux;
|
||||
if (aux < m_least_coeff) {
|
||||
m_least_coeff = aux;
|
||||
least_coeff_is_bounded = lra.column_is_bounded(j);
|
||||
least_coeff_is_unique = true;
|
||||
least_coeff_index = j;
|
||||
}
|
||||
else if (least_coeff_is_bounded && aux == least_coeff) {
|
||||
least_coeff_is_bounded = lra.column_is_bounded(j);
|
||||
else if (aux == m_least_coeff) {
|
||||
least_coeff_is_bounded &= lra.column_is_bounded(j);
|
||||
least_coeff_is_unique = false;
|
||||
}
|
||||
}
|
||||
SASSERT(gcds.is_int());
|
||||
SASSERT(least_coeff.is_int());
|
||||
SASSERT(m_least_coeff.is_int());
|
||||
TRACE("gcd_test_bug", tout << "coeff: " << a << ", gcds: " << gcds
|
||||
<< " least_coeff: " << least_coeff << " consts: " << consts << "\n";);
|
||||
<< " least_coeff: " << m_least_coeff << " consts: " << m_consts << "\n";);
|
||||
|
||||
}
|
||||
|
||||
|
@ -143,31 +166,29 @@ namespace lp {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!(consts / gcds).is_int()) {
|
||||
if (!(m_consts / gcds).is_int()) {
|
||||
TRACE("gcd_test", tout << "row failed the GCD test:\n"; lia.display_row_info(tout, i););
|
||||
fill_explanation_from_fixed_columns(A.m_rows[i]);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (least_coeff.is_one() && !least_coeff_is_bounded) {
|
||||
SASSERT(gcds.is_one());
|
||||
|
||||
if (least_coeff_is_bounded &&
|
||||
!m_least_coeff.is_one() &&
|
||||
!lia.get_value(basic_var).is_int() &&
|
||||
!ext_gcd_test(A.m_rows[i]))
|
||||
return false;
|
||||
|
||||
if (!least_coeff_is_unique)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (least_coeff_is_bounded) {
|
||||
return ext_gcd_test(A.m_rows[i], least_coeff, lcm_den, consts);
|
||||
}
|
||||
return true;
|
||||
|
||||
return accumulate_parity(row, least_coeff_index);
|
||||
}
|
||||
|
||||
bool int_gcd_test::ext_gcd_test(const row_strip<mpq> & row,
|
||||
mpq const & least_coeff,
|
||||
mpq const & lcm_den,
|
||||
mpq const & consts) {
|
||||
bool int_gcd_test::ext_gcd_test(const row_strip<mpq> & row) {
|
||||
TRACE("ext_gcd_test", tout << "row = "; lra.print_row(row, tout););
|
||||
mpq gcds(0);
|
||||
mpq l(consts);
|
||||
mpq u(consts);
|
||||
mpq l(m_consts);
|
||||
mpq u(m_consts);
|
||||
|
||||
mpq a;
|
||||
unsigned j;
|
||||
|
@ -178,10 +199,10 @@ namespace lp {
|
|||
if (lra.column_is_fixed(j))
|
||||
continue;
|
||||
SASSERT(!lra.column_is_real(j));
|
||||
mpq ncoeff = lcm_den * a;
|
||||
mpq ncoeff = m_lcm_den * a;
|
||||
SASSERT(ncoeff.is_int());
|
||||
mpq abs_ncoeff = abs(ncoeff);
|
||||
if (abs_ncoeff == least_coeff) {
|
||||
if (abs_ncoeff == m_least_coeff) {
|
||||
SASSERT(lra.column_is_bounded(j));
|
||||
if (ncoeff.is_pos()) {
|
||||
// l += ncoeff * lra.column_lower_bound(j).x;
|
||||
|
@ -235,4 +256,72 @@ namespace lp {
|
|||
lia.m_ex->push_back(uc);
|
||||
}
|
||||
|
||||
bool int_gcd_test::accumulate_parity(const row_strip<mpq> & row, unsigned least_idx) {
|
||||
|
||||
// remove this line to enable new functionality.
|
||||
// return true;
|
||||
|
||||
mpq modulus(0);
|
||||
bool least_sign = false;
|
||||
for (const auto & c : row) {
|
||||
unsigned j = c.var();
|
||||
const mpq& a = c.coeff();
|
||||
if (j == least_idx)
|
||||
least_sign = a.is_neg();
|
||||
else if (!lra.column_is_fixed(j)) {
|
||||
mpq aux = abs(m_lcm_den * a);
|
||||
if (gcd(m_least_coeff, aux) != m_least_coeff)
|
||||
return true;
|
||||
modulus = modulus == 0 ? aux : gcd(modulus, aux);
|
||||
if (modulus.is_one())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
modulus /= m_least_coeff;
|
||||
if (modulus == 0)
|
||||
return true;
|
||||
SASSERT(modulus.is_int());
|
||||
mpq offset = m_consts / m_least_coeff;
|
||||
if (!offset.is_int())
|
||||
return true;
|
||||
offset = mod(offset, modulus);
|
||||
if (!least_sign && offset != 0)
|
||||
offset = modulus - offset;
|
||||
TRACE("gcd_test", tout << least_idx << " modulus: " << modulus << " consts: " << m_consts << " sign " << least_sign << " offset: " << offset << "\n";);
|
||||
|
||||
SASSERT(0 <= offset && offset < modulus);
|
||||
return insert_parity(least_idx, row, offset, modulus);
|
||||
}
|
||||
|
||||
void int_gcd_test::reset_test() {
|
||||
for (auto j : m_inserted_vars)
|
||||
m_parities[j].pop_back();
|
||||
m_inserted_vars.reset();
|
||||
m_visited_ts++;
|
||||
if (m_visited_ts == 0) {
|
||||
m_visited.reset();
|
||||
m_visited_ts++;
|
||||
}
|
||||
}
|
||||
|
||||
bool int_gcd_test::insert_parity(unsigned j, row_strip<mpq> const& r, mpq const& offset, mpq const& modulo) {
|
||||
m_parities.reserve(j + 1);
|
||||
|
||||
// incomplete parity check.
|
||||
for (auto const& p : m_parities[j]) {
|
||||
if (p.m_modulo != modulo)
|
||||
continue;
|
||||
if (p.m_offset == offset)
|
||||
return true;
|
||||
else {
|
||||
fill_explanation_from_fixed_columns(r);
|
||||
fill_explanation_from_fixed_columns(*p.m_row);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_inserted_vars.push_back(j);
|
||||
m_parities[j].push_back(parity(offset, modulo, r));
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,22 +32,43 @@ namespace lp {
|
|||
class int_solver;
|
||||
class lar_solver;
|
||||
class int_gcd_test {
|
||||
|
||||
struct parity {
|
||||
mpq m_offset;
|
||||
mpq m_modulo;
|
||||
const row_strip<mpq>* m_row = nullptr;
|
||||
parity(mpq const& p, mpq const& m, row_strip<mpq> const& r):
|
||||
m_offset(p),
|
||||
m_modulo(m),
|
||||
m_row(&r)
|
||||
{}
|
||||
};
|
||||
class int_solver& lia;
|
||||
class lar_solver& lra;
|
||||
unsigned m_next_gcd;
|
||||
unsigned m_delay;
|
||||
unsigned m_next_gcd = 0;
|
||||
unsigned m_delay = 0;
|
||||
mpq m_consts;
|
||||
mpq m_least_coeff;
|
||||
mpq m_lcm_den;
|
||||
unsigned_vector m_inserted_vars;
|
||||
vector<vector<parity>> m_parities;
|
||||
unsigned_vector m_visited;
|
||||
unsigned m_visited_ts = 0;
|
||||
|
||||
bool is_visited(unsigned i) { return m_visited.get(i, 0) == m_visited_ts; }
|
||||
void mark_visited(unsigned i) { m_visited.setx(i, m_visited_ts, 0); }
|
||||
|
||||
void reset_test();
|
||||
bool insert_parity(unsigned j, row_strip<mpq> const& r, mpq const& parity, mpq const& modulo);
|
||||
|
||||
bool gcd_test();
|
||||
bool gcd_test_for_row(const static_matrix<mpq, numeric_pair<mpq>> & A, unsigned i);
|
||||
bool ext_gcd_test(const row_strip<mpq> & row,
|
||||
mpq const & least_coeff,
|
||||
mpq const & lcm_den,
|
||||
mpq const & consts);
|
||||
bool ext_gcd_test(const row_strip<mpq> & row);
|
||||
void fill_explanation_from_fixed_columns(const row_strip<mpq> & row);
|
||||
void add_to_explanation_from_fixed_or_boxed_column(unsigned j);
|
||||
bool accumulate_parity(const row_strip<mpq> & row, unsigned least_coeff_index);
|
||||
public:
|
||||
int_gcd_test(int_solver& lia);
|
||||
~int_gcd_test() {}
|
||||
lia_move operator()();
|
||||
bool should_apply();
|
||||
};
|
||||
|
|
|
@ -179,34 +179,33 @@ unsigned lp_primal_core_solver<T, X>::solve_with_tableau() {
|
|||
default:
|
||||
break; // do nothing
|
||||
}
|
||||
if (this->m_settings.get_cancel_flag()
|
||||
||
|
||||
this->iters_with_no_cost_growing() > this->m_settings.max_number_of_iterations_with_no_improvements
|
||||
||
|
||||
this->total_iterations() > this->m_settings.max_total_number_of_iterations
|
||||
) {
|
||||
this->set_status(lp_status::CANCELLED);
|
||||
break; // from the loop
|
||||
}
|
||||
} while (this->get_status() != lp_status::FLOATING_POINT_ERROR
|
||||
&&
|
||||
&&
|
||||
this->get_status() != lp_status::UNBOUNDED
|
||||
&&
|
||||
&&
|
||||
this->get_status() != lp_status::OPTIMAL
|
||||
&&
|
||||
&&
|
||||
this->get_status() != lp_status::INFEASIBLE
|
||||
&&
|
||||
this->iters_with_no_cost_growing() <= this->m_settings.max_number_of_iterations_with_no_improvements
|
||||
&&
|
||||
this->total_iterations() <= this->m_settings.max_total_number_of_iterations
|
||||
&&
|
||||
!(this->current_x_is_feasible() && this->m_look_for_feasible_solution_only)
|
||||
&&
|
||||
this->m_settings.get_cancel_flag() == false);
|
||||
&&
|
||||
!(this->current_x_is_feasible() && this->m_look_for_feasible_solution_only)
|
||||
);
|
||||
|
||||
if (this->m_settings.get_cancel_flag()) {
|
||||
this->set_status(lp_status::CANCELLED);
|
||||
}
|
||||
|
||||
lp_assert(
|
||||
this->get_status() == lp_status::FLOATING_POINT_ERROR
|
||||
||
|
||||
this->get_status() == lp_status::CANCELLED
|
||||
||
|
||||
this->current_x_is_feasible() == false
|
||||
||
|
||||
this->calc_current_x_is_feasible_include_non_basis());
|
||||
lp_assert(this->get_status() == lp_status::FLOATING_POINT_ERROR
|
||||
||
|
||||
this->get_status() == lp_status::CANCELLED
|
||||
||
|
||||
this->current_x_is_feasible() == false
|
||||
||
|
||||
this->calc_current_x_is_feasible_include_non_basis());
|
||||
return this->total_iterations();
|
||||
|
||||
}
|
||||
|
|
|
@ -140,6 +140,7 @@ struct statistics {
|
|||
st.update("arith-patches", m_patches);
|
||||
st.update("arith-patches-success", m_patches_success);
|
||||
st.update("arith-hnf-calls", m_hnf_cutter_calls);
|
||||
st.update("arith-hnf-cuts", m_hnf_cuts);
|
||||
st.update("arith-horner-calls", m_horner_calls);
|
||||
st.update("arith-horner-conflicts", m_horner_conflicts);
|
||||
st.update("arith-horner-cross-nested-forms", m_cross_nested_forms);
|
||||
|
@ -208,7 +209,7 @@ public:
|
|||
double harris_feasibility_tolerance { 1e-7 }; // page 179 of Istvan Maros
|
||||
double ignore_epsilon_of_harris { 10e-5 };
|
||||
unsigned max_number_of_iterations_with_no_improvements { 2000000 };
|
||||
unsigned max_total_number_of_iterations { 2000000 };
|
||||
unsigned max_total_number_of_iterations { 20000000 };
|
||||
double time_limit; // the maximum time limit of the total run time in seconds
|
||||
// dual section
|
||||
double dual_feasibility_tolerance { 1e-7 }; // page 71 of the PhD thesis of Achim Koberstein
|
||||
|
|
|
@ -54,7 +54,6 @@ public:
|
|||
virtual unsigned size() const { return 1; }
|
||||
virtual expr_type type() const = 0;
|
||||
virtual std::ostream& print(std::ostream&) const = 0;
|
||||
nex() {}
|
||||
bool is_elementary() const {
|
||||
switch(type()) {
|
||||
case expr_type::SUM:
|
||||
|
|
|
@ -92,8 +92,6 @@ public:
|
|||
bool operator!=(row_iterator const& other) const { return m_index != other.m_index; }
|
||||
};
|
||||
|
||||
bit_matrix() {}
|
||||
~bit_matrix() {}
|
||||
void reset(unsigned num_columns);
|
||||
|
||||
row_iterator begin() { return row_iterator(*this, true); }
|
||||
|
|
|
@ -166,7 +166,7 @@ namespace opt {
|
|||
return true;
|
||||
}
|
||||
|
||||
#define PASSERT(_e_) if (!(_e_)) { TRACE("opt1", display(tout, r); display(tout);); SASSERT(_e_); }
|
||||
#define PASSERT(_e_) { CTRACE("qe", !(_e_), display(tout, r); display(tout);); SASSERT(_e_); }
|
||||
|
||||
bool model_based_opt::invariant(unsigned index, row const& r) {
|
||||
vector<var> const& vars = r.m_vars;
|
||||
|
@ -378,7 +378,8 @@ namespace opt {
|
|||
}
|
||||
else if ((value == lub_val && r.m_type == opt::t_lt) ||
|
||||
(is_pos && value < lub_val) ||
|
||||
(!is_pos && value > lub_val)) {
|
||||
|
||||
(!is_pos && value > lub_val)) {
|
||||
m_above.push_back(bound_row_index);
|
||||
lub_val = value;
|
||||
bound_row_index = row_id;
|
||||
|
@ -423,6 +424,13 @@ namespace opt {
|
|||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
rational model_based_opt::eval(vector<var> const& coeffs) const {
|
||||
rational val(0);
|
||||
for (var const& v : coeffs)
|
||||
val += v.m_coeff * eval(v.m_id);
|
||||
return val;
|
||||
}
|
||||
|
||||
rational model_based_opt::get_coefficient(unsigned row_id, unsigned var_id) const {
|
||||
return m_rows[row_id].get_coefficient(var_id);
|
||||
|
@ -787,7 +795,7 @@ namespace opt {
|
|||
}
|
||||
|
||||
std::ostream& model_based_opt::display(std::ostream& out, row const& r) {
|
||||
out << (r.m_alive?"+":"-") << " ";
|
||||
out << (r.m_alive?"a":"d") << " ";
|
||||
display(out, r.m_vars, r.m_coeff);
|
||||
if (r.m_type == opt::t_mod) {
|
||||
out << r.m_type << " " << r.m_mod << " = 0; value: " << r.m_value << "\n";
|
||||
|
@ -1002,8 +1010,7 @@ namespace opt {
|
|||
result = solve_for(glb_index, x, true);
|
||||
}
|
||||
else {
|
||||
result = def();
|
||||
m_var2value[x] = rational::zero();
|
||||
result = def() + m_var2value[x];
|
||||
}
|
||||
SASSERT(eval(result) == eval(x));
|
||||
}
|
||||
|
@ -1123,9 +1130,8 @@ namespace opt {
|
|||
}
|
||||
TRACE("opt1", display(tout << "tableau after replace x by y := v" << y << "\n"););
|
||||
def result = project(y, compute_def);
|
||||
if (compute_def) {
|
||||
if (compute_def)
|
||||
result = (result * D) + u;
|
||||
}
|
||||
SASSERT(!compute_def || eval(result) == eval(x));
|
||||
return result;
|
||||
}
|
||||
|
@ -1187,13 +1193,15 @@ namespace opt {
|
|||
SASSERT(a.is_pos());
|
||||
if (ty == t_lt) {
|
||||
SASSERT(compute_def);
|
||||
m_rows[row_id1].m_coeff += a;
|
||||
m_rows[row_id1].m_coeff += a;
|
||||
m_rows[row_id1].m_type = t_le;
|
||||
m_rows[row_id1].m_value += a;
|
||||
}
|
||||
if (m_var2is_int[x] && !a.is_one()) {
|
||||
row& r1 = m_rows[row_id1];
|
||||
vector<var> coeffs;
|
||||
mk_coeffs_without(coeffs, r1.m_vars, x);
|
||||
rational c = r1.m_coeff;
|
||||
rational c = mod(-eval(coeffs), a);
|
||||
add_divides(coeffs, c, a);
|
||||
}
|
||||
unsigned_vector const& row_ids = m_var2row_ids[x];
|
||||
|
@ -1203,19 +1211,19 @@ namespace opt {
|
|||
if (!visited.contains(row_id2)) {
|
||||
visited.insert(row_id2);
|
||||
b = get_coefficient(row_id2, x);
|
||||
if (!b.is_zero()) {
|
||||
row& dst = m_rows[row_id2];
|
||||
switch (dst.m_type) {
|
||||
case t_eq:
|
||||
case t_lt:
|
||||
case t_le:
|
||||
solve(row_id1, a, row_id2, x);
|
||||
break;
|
||||
case t_mod:
|
||||
// mod reduction already done.
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
if (b.is_zero())
|
||||
continue;
|
||||
row& dst = m_rows[row_id2];
|
||||
switch (dst.m_type) {
|
||||
case t_eq:
|
||||
case t_lt:
|
||||
case t_le:
|
||||
solve(row_id1, a, row_id2, x);
|
||||
break;
|
||||
case t_mod:
|
||||
// mod reduction already done.
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,6 +104,8 @@ namespace opt {
|
|||
rational eval(unsigned x) const;
|
||||
|
||||
rational eval(def const& d) const;
|
||||
|
||||
rational eval(vector<var> const& coeffs) const;
|
||||
|
||||
void resolve(unsigned row_src, rational const& a1, unsigned row_dst, unsigned x);
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ class exception {
|
|||
|
||||
class power : public std::pair<var, unsigned> {
|
||||
public:
|
||||
power():std::pair<var, unsigned>() {}
|
||||
power() = default;
|
||||
power(var v, unsigned d):std::pair<var, unsigned>(v, d) {}
|
||||
var x() const { return first; }
|
||||
var get_var() const { return first; }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue