mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 11:42:28 +00:00 
			
		
		
		
	fix solve bug
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
		
							parent
							
								
									3178f7f86d
								
							
						
					
					
						commit
						fee7828b51
					
				
					 2 changed files with 68 additions and 36 deletions
				
			
		|  | @ -175,8 +175,7 @@ namespace opt { | |||
|             rational new_x_val; | ||||
|             rational x_coeff, eps(0); | ||||
|             vector<var> const& vars = r.m_vars; | ||||
|             for (unsigned j = 0; j < vars.size(); ++j) { | ||||
|                 var const& v = vars[j]; | ||||
|             for (var const& v : vars) {                  | ||||
|                 if (x == v.m_id) { | ||||
|                     x_coeff = v.m_coeff; | ||||
|                 } | ||||
|  | @ -227,8 +226,7 @@ namespace opt { | |||
|             --i; | ||||
|             unsigned x = bound_vars[i]; | ||||
|             unsigned_vector const& row_ids = m_var2row_ids[x]; | ||||
|             for (unsigned j = 0; j < row_ids.size(); ++j) {             | ||||
|                 unsigned row_id = row_ids[j]; | ||||
|             for (unsigned row_id : row_ids) {                 | ||||
|                 row & r = m_rows[row_id]; | ||||
|                 r.m_value = get_row_value(r); | ||||
|                 SASSERT(invariant(row_id, r)); | ||||
|  | @ -368,7 +366,7 @@ namespace opt { | |||
|                       tout << a1 << " " << a2 << ": "; | ||||
|                       display(tout, m_rows[row_dst]); | ||||
|                       display(tout, m_rows[row_src]);); | ||||
|                 if (a1.is_pos() != a2.is_pos()) {   | ||||
|                 if (a1.is_pos() != a2.is_pos() || m_rows[row_src].m_type == opt::t_eq) {   | ||||
|                     mul_add(x, a1, row_src, a2, row_dst); | ||||
|                 } | ||||
|                 else { | ||||
|  | @ -384,6 +382,18 @@ namespace opt { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void model_based_opt::solve(unsigned row_src, rational const& a1, unsigned row_dst, unsigned x) { | ||||
|         SASSERT(a1 == get_coefficient(row_src, x)); | ||||
|         SASSERT(a1.is_pos()); | ||||
|         SASSERT(row_src != row_dst);                 | ||||
|         SASSERT(m_rows[row_src].m_type == t_eq); | ||||
|         if (!m_rows[row_dst].m_alive) return; | ||||
|         rational a2 = get_coefficient(row_dst, x); | ||||
|         mul(row_dst, a1); | ||||
|         mul_add(false, row_dst, -a2, row_src); | ||||
|         SASSERT(get_coefficient(row_dst, x).is_zero()); | ||||
|     } | ||||
| 
 | ||||
|     // resolution for integer rows.
 | ||||
|     void model_based_opt::mul_add( | ||||
|         unsigned x, rational const& src_c, unsigned row_src, rational const& dst_c, unsigned row_dst) { | ||||
|  | @ -457,8 +467,8 @@ namespace opt { | |||
|     } | ||||
| 
 | ||||
|     void model_based_opt::mk_coeffs_without(vector<var>& dst, vector<var> const src, unsigned x) { | ||||
|         for (unsigned i = 0; i < src.size(); ++i) { | ||||
|             if (src[i].m_id != x) dst.push_back(src[i]); | ||||
|         for (var const & v : src) { | ||||
|             if (v.m_id != x) dst.push_back(v); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -469,8 +479,8 @@ namespace opt { | |||
|     void model_based_opt::mul(unsigned dst, rational const& c) { | ||||
|         if (c.is_one()) return; | ||||
|         row& r = m_rows[dst]; | ||||
|         for (unsigned i = 0; i < r.m_vars.size(); ++i) { | ||||
|             r.m_vars[i].m_coeff *= c; | ||||
|         for (auto & v : r.m_vars) { | ||||
|             v.m_coeff *= c; | ||||
|         } | ||||
|         r.m_coeff *= c; | ||||
|         r.m_value *= c; | ||||
|  | @ -674,8 +684,8 @@ namespace opt { | |||
|         unsigned dst = new_row(); | ||||
|         row const& r = m_rows[src]; | ||||
|         set_row(dst, r.m_vars, r.m_coeff, r.m_mod, r.m_type); | ||||
|         for (unsigned i = 0; i < r.m_vars.size(); ++i) { | ||||
|             m_var2row_ids[r.m_vars[i].m_id].push_back(dst); | ||||
|         for (auto const& v : r.m_vars) { | ||||
|             m_var2row_ids[v.m_id].push_back(dst); | ||||
|         } | ||||
|         SASSERT(invariant(dst, m_rows[dst])); | ||||
|         return dst; | ||||
|  | @ -692,8 +702,8 @@ namespace opt { | |||
|     void model_based_opt::add_constraint(vector<var> const& coeffs, rational const& c, rational const& m, ineq_type rel) { | ||||
|         unsigned row_id = new_row(); | ||||
|         set_row(row_id, coeffs, c, m, rel); | ||||
|         for (unsigned i = 0; i < coeffs.size(); ++i) { | ||||
|             m_var2row_ids[coeffs[i].m_id].push_back(row_id);  | ||||
|         for (var const& coeff : coeffs) { | ||||
|             m_var2row_ids[coeff.m_id].push_back(row_id);  | ||||
|         } | ||||
|         SASSERT(invariant(row_id, m_rows[row_id])); | ||||
|     } | ||||
|  | @ -703,9 +713,9 @@ namespace opt { | |||
|     } | ||||
| 
 | ||||
|     void model_based_opt::get_live_rows(vector<row>& rows) { | ||||
|         for (unsigned i = 0; i < m_rows.size(); ++i) { | ||||
|             if (m_rows[i].m_alive) { | ||||
|                 rows.push_back(m_rows[i]); | ||||
|         for (row const& r : m_rows) { | ||||
|             if (r.m_alive) { | ||||
|                 rows.push_back(r); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | @ -742,9 +752,9 @@ namespace opt { | |||
|         glb_rows.reset(); | ||||
|         mod_rows.reset(); | ||||
|         bool lub_is_unit = false, glb_is_unit = false; | ||||
|         unsigned eq_row = UINT_MAX; | ||||
|         // select the lub and glb.
 | ||||
|         for (unsigned i = 0; i < row_ids.size(); ++i) { | ||||
|             unsigned row_id = row_ids[i]; | ||||
|         for (unsigned row_id : row_ids) { | ||||
|             if (visited.contains(row_id)) { | ||||
|                 continue; | ||||
|             } | ||||
|  | @ -758,8 +768,8 @@ namespace opt { | |||
|                 continue; | ||||
|             } | ||||
|             if (r.m_type == t_eq) { | ||||
|                 solve_for(row_id, x); | ||||
|                 return; | ||||
|                 eq_row = row_id; | ||||
|                 continue; | ||||
|             } | ||||
|             if (r.m_type == t_mod) { | ||||
|                 mod_rows.push_back(row_id); | ||||
|  | @ -795,6 +805,11 @@ namespace opt { | |||
|             solve_mod(x, mod_rows); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         if (eq_row != UINT_MAX) { | ||||
|             solve_for(eq_row, x); | ||||
|             return; | ||||
|         } | ||||
|          | ||||
|         unsigned lub_size = lub_rows.size(); | ||||
|         unsigned glb_size = glb_rows.size(); | ||||
|  | @ -803,8 +818,7 @@ namespace opt { | |||
|          | ||||
|         // There are only upper or only lower bounds.
 | ||||
|         if (row_index == UINT_MAX) { | ||||
|             for (unsigned i = 0; i < glb_rows.size(); ++i) { | ||||
|                 unsigned row_id = glb_rows[i]; | ||||
|             for (unsigned row_id : glb_rows) { | ||||
|                 SASSERT(m_rows[row_id].m_alive); | ||||
|                 SASSERT(!get_coefficient(row_id, x).is_zero()); | ||||
|                 retire_row(row_id); | ||||
|  | @ -839,8 +853,7 @@ namespace opt { | |||
| 
 | ||||
|         // General case.
 | ||||
|         rational coeff = get_coefficient(row_index, x); | ||||
|         for (unsigned i = 0; i < glb_rows.size(); ++i) { | ||||
|             unsigned row_id = glb_rows[i]; | ||||
|         for (unsigned row_id : glb_rows) { | ||||
|             if (row_id != row_index) { | ||||
|                 resolve(row_index, coeff, row_id, x); | ||||
|             } | ||||
|  | @ -866,8 +879,8 @@ namespace opt { | |||
|     void model_based_opt::solve_mod(unsigned x, unsigned_vector const& mod_rows) { | ||||
|         SASSERT(!mod_rows.empty()); | ||||
|         rational D(1); | ||||
|         for (unsigned i = 0; i < mod_rows.size(); ++i) { | ||||
|             D = lcm(D, m_rows[mod_rows[i]].m_mod);             | ||||
|         for (unsigned idx : mod_rows) { | ||||
|             D = lcm(D, m_rows[idx].m_mod);             | ||||
|         } | ||||
|         if (D.is_zero()) { | ||||
|             throw default_exception("modulo 0 is not defined"); | ||||
|  | @ -876,9 +889,9 @@ namespace opt { | |||
|         rational val_x = m_var2value[x]; | ||||
|         rational u = mod(val_x, D); | ||||
|         SASSERT(u.is_nonneg() && u < D); | ||||
|         for (unsigned i = 0; i < mod_rows.size(); ++i) { | ||||
|             replace_var(mod_rows[i], x, u);             | ||||
|             SASSERT(invariant(mod_rows[i], m_rows[mod_rows[i]])); | ||||
|         for (unsigned idx : mod_rows) { | ||||
|             replace_var(idx, x, u);             | ||||
|             SASSERT(invariant(idx, m_rows[idx])); | ||||
|         } | ||||
|         //
 | ||||
|         // update inequalities such that u is added to t and
 | ||||
|  | @ -894,8 +907,7 @@ namespace opt { | |||
|         unsigned y = add_var(new_val, true); | ||||
|         unsigned_vector const& row_ids = m_var2row_ids[x]; | ||||
|         uint_set visited; | ||||
|         for (unsigned i = 0; i < row_ids.size(); ++i) { | ||||
|             unsigned row_id = row_ids[i]; | ||||
|         for (unsigned row_id : row_ids) {            | ||||
|             if (!visited.contains(row_id)) { | ||||
|                 // x |-> D*y + u
 | ||||
|                 replace_var(row_id, x, D, y, u); | ||||
|  | @ -954,23 +966,39 @@ namespace opt { | |||
|         SASSERT(!a.is_zero()); | ||||
|         SASSERT(m_rows[row_id1].m_type == t_eq); | ||||
|         SASSERT(m_rows[row_id1].m_alive); | ||||
|         if (m_var2is_int[x] && !abs(a).is_one()) { | ||||
|         if (a.is_neg()) { | ||||
|             a.neg(); | ||||
|             m_rows[row_id1].neg(); | ||||
|         } | ||||
|         SASSERT(a.is_pos()); | ||||
|         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; | ||||
|             add_divides(coeffs, c, abs(a)); | ||||
|             add_divides(coeffs, c, a); | ||||
|         } | ||||
|         unsigned_vector const& row_ids = m_var2row_ids[x]; | ||||
|         uint_set visited; | ||||
|         visited.insert(row_id1); | ||||
|         for (unsigned i = 0; i < row_ids.size(); ++i) { | ||||
|             unsigned row_id2 = row_ids[i]; | ||||
|         for (unsigned row_id2 : row_ids) { | ||||
|             if (!visited.contains(row_id2)) {                 | ||||
|                 visited.insert(row_id2); | ||||
|                  | ||||
|                 b = get_coefficient(row_id2, x); | ||||
|                 if (!b.is_zero()) { | ||||
|                     resolve(row_id1, a, row_id2, x);             | ||||
|                     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; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  |  | |||
|  | @ -58,6 +58,8 @@ namespace opt { | |||
|             rational    m_value;        // value of m_vars + m_coeff under interpretation of m_var2value.
 | ||||
|             bool        m_alive;        // rows can be marked dead if they have been processed.
 | ||||
|             void reset() { m_vars.reset(); m_coeff.reset(); m_value.reset(); } | ||||
| 
 | ||||
|             void neg() { for (var & v : m_vars) v.m_coeff.neg(); m_coeff.neg(); m_value.neg(); } | ||||
|         }; | ||||
| 
 | ||||
|     private: | ||||
|  | @ -85,6 +87,8 @@ namespace opt { | |||
| 
 | ||||
|         void resolve(unsigned row_src, rational const& a1, unsigned row_dst, unsigned x); | ||||
| 
 | ||||
|         void solve(unsigned row_src, rational const& a1, unsigned row_dst, unsigned x); | ||||
| 
 | ||||
|         void mul_add(bool same_sign, unsigned row_id1, rational const& c, unsigned row_id2); | ||||
| 
 | ||||
|         void mul_add(unsigned x, rational const& a1, unsigned row_src, rational const& a2, unsigned row_dst); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue