mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 19:52:29 +00:00 
			
		
		
		
	add int_solver class
Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
		
							parent
							
								
									4eec8cbadd
								
							
						
					
					
						commit
						06e1151ca0
					
				
					 7 changed files with 1677 additions and 1292 deletions
				
			
		|  | @ -8,7 +8,7 @@ z3_add_component(lp | |||
|     dense_matrix_instances.cpp | ||||
|     eta_matrix_instances.cpp | ||||
|     indexed_vector_instances.cpp | ||||
|     lar_solver.cpp | ||||
|     lar_solver_instances.cpp | ||||
|     lar_core_solver_instances.cpp | ||||
|     lp_core_solver_base_instances.cpp | ||||
|     lp_dual_core_solver_instances.cpp | ||||
|  |  | |||
|  | @ -2,14 +2,15 @@ | |||
|   Copyright (c) 2017 Microsoft Corporation | ||||
|   Author: Lev Nachmanson | ||||
| */ | ||||
| #include "util/lp/lar_solver.h" | ||||
| 
 | ||||
| // here we are inside lean::lar_solver class
 | ||||
| namespace lean { | ||||
| 
 | ||||
| bool strategy_is_undecided() const { | ||||
| bool lar_solver::strategy_is_undecided() const { | ||||
|     return m_settings.simplex_strategy() == simplex_strategy_enum::undecided; | ||||
| } | ||||
| 
 | ||||
| var_index add_var(unsigned ext_j) { | ||||
| var_index lar_solver::add_var(unsigned ext_j) { | ||||
|     var_index i; | ||||
|     lean_assert (ext_j < m_terms_start_index);  | ||||
| 
 | ||||
|  | @ -27,7 +28,7 @@ var_index add_var(unsigned ext_j) { | |||
|     return i; | ||||
| } | ||||
| 
 | ||||
| void register_new_ext_var_index(unsigned ext_v) { | ||||
| void lar_solver::register_new_ext_var_index(unsigned ext_v) { | ||||
|     lean_assert(!contains(m_ext_vars_to_columns, ext_v)); | ||||
|     unsigned j = static_cast<unsigned>(m_ext_vars_to_columns.size()); | ||||
|     m_ext_vars_to_columns[ext_v] = j; | ||||
|  | @ -35,7 +36,7 @@ void register_new_ext_var_index(unsigned ext_v) { | |||
|     m_columns_to_ext_vars_or_term_indices.push_back(ext_v); | ||||
| } | ||||
| 
 | ||||
| void add_non_basic_var_to_core_fields(unsigned ext_j) { | ||||
| void lar_solver::add_non_basic_var_to_core_fields(unsigned ext_j) { | ||||
|     register_new_ext_var_index(ext_j); | ||||
|     m_mpq_lar_core_solver.m_column_types.push_back(column_type::free_column); | ||||
|     m_columns_with_changed_bound.increase_size_by_one(); | ||||
|  | @ -44,7 +45,7 @@ void add_non_basic_var_to_core_fields(unsigned ext_j) { | |||
|         add_new_var_to_core_fields_for_doubles(false); | ||||
| } | ||||
| 
 | ||||
| void add_new_var_to_core_fields_for_doubles(bool register_in_basis) { | ||||
| void lar_solver::add_new_var_to_core_fields_for_doubles(bool register_in_basis) { | ||||
|     unsigned j = A_d().column_count(); | ||||
|     A_d().add_column(); | ||||
|     lean_assert(m_mpq_lar_core_solver.m_d_x.size() == j); | ||||
|  | @ -63,7 +64,7 @@ void add_new_var_to_core_fields_for_doubles(bool register_in_basis) { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void add_new_var_to_core_fields_for_mpq(bool register_in_basis) { | ||||
| void lar_solver::add_new_var_to_core_fields_for_mpq(bool register_in_basis) { | ||||
|     unsigned j = A_r().column_count(); | ||||
|     A_r().add_column(); | ||||
|     lean_assert(m_mpq_lar_core_solver.m_r_x.size() == j); | ||||
|  | @ -88,7 +89,7 @@ void add_new_var_to_core_fields_for_mpq(bool register_in_basis) { | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| var_index add_term_undecided(const vector<std::pair<mpq, var_index>> & coeffs, | ||||
| var_index lar_solver::add_term_undecided(const vector<std::pair<mpq, var_index>> & coeffs, | ||||
|                              const mpq &m_v) { | ||||
|     m_terms.push_back(new lar_term(coeffs, m_v)); | ||||
|     m_orig_terms.push_back(new lar_term(coeffs, m_v)); | ||||
|  | @ -96,7 +97,7 @@ var_index add_term_undecided(const vector<std::pair<mpq, var_index>> & coeffs, | |||
| } | ||||
| 
 | ||||
| // terms
 | ||||
| var_index add_term(const vector<std::pair<mpq, var_index>> & coeffs, | ||||
| var_index lar_solver::add_term(const vector<std::pair<mpq, var_index>> & coeffs, | ||||
|                    const mpq &m_v) { | ||||
|     if (strategy_is_undecided()) | ||||
|         return add_term_undecided(coeffs, m_v); | ||||
|  | @ -114,13 +115,13 @@ var_index add_term(const vector<std::pair<mpq, var_index>> & coeffs, | |||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| void add_row_for_term(const lar_term * term, unsigned term_ext_index) { | ||||
| void lar_solver::add_row_for_term(const lar_term * term, unsigned term_ext_index) { | ||||
|     lean_assert(sizes_are_correct()); | ||||
|     add_row_from_term_no_constraint(term, term_ext_index); | ||||
|     lean_assert(sizes_are_correct()); | ||||
| } | ||||
| 
 | ||||
| void add_row_from_term_no_constraint(const lar_term * term, unsigned term_ext_index) { | ||||
| void lar_solver::add_row_from_term_no_constraint(const lar_term * term, unsigned term_ext_index) { | ||||
|     register_new_ext_var_index(term_ext_index); | ||||
|     // j will be a new variable
 | ||||
| 	unsigned j = A_r().column_count(); | ||||
|  | @ -140,7 +141,7 @@ void add_row_from_term_no_constraint(const lar_term * term, unsigned term_ext_in | |||
|         fill_last_row_of_A_d(A_d(), term); | ||||
| } | ||||
| 
 | ||||
| void add_basic_var_to_core_fields() { | ||||
| void lar_solver::add_basic_var_to_core_fields() { | ||||
|     bool use_lu = m_mpq_lar_core_solver.need_to_presolve_with_double_solver(); | ||||
|     lean_assert(!use_lu || A_r().column_count() == A_d().column_count()); | ||||
|     m_mpq_lar_core_solver.m_column_types.push_back(column_type::free_column); | ||||
|  | @ -151,7 +152,7 @@ void add_basic_var_to_core_fields() { | |||
|         add_new_var_to_core_fields_for_doubles(true); | ||||
| } | ||||
| 
 | ||||
| constraint_index add_var_bound(var_index j, lconstraint_kind kind, const mpq & right_side)  { | ||||
| constraint_index lar_solver::add_var_bound(var_index j, lconstraint_kind kind, const mpq & right_side)  { | ||||
| 	constraint_index ci = m_constraints.size(); | ||||
|     if (!is_term(j)) { // j is a var
 | ||||
|         auto vc = new lar_var_constraint(j, kind, right_side); | ||||
|  | @ -164,7 +165,7 @@ constraint_index add_var_bound(var_index j, lconstraint_kind kind, const mpq & r | |||
|     return ci; | ||||
| } | ||||
| 
 | ||||
| void update_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_index) { | ||||
| void lar_solver::update_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_index) { | ||||
|     switch(m_mpq_lar_core_solver.m_column_types[j]) { | ||||
|     case column_type::free_column: | ||||
|         update_free_column_type_and_bound(j, kind, right_side, constr_index); | ||||
|  | @ -186,7 +187,7 @@ void update_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void add_var_bound_on_constraint_for_term(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { | ||||
| void lar_solver::add_var_bound_on_constraint_for_term(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { | ||||
|     lean_assert(is_term(j)); | ||||
|     unsigned adjusted_term_index = adjust_term_index(j); | ||||
|     unsigned term_j; | ||||
|  | @ -201,7 +202,7 @@ void add_var_bound_on_constraint_for_term(var_index j, lconstraint_kind kind, co | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| void add_constraint_from_term_and_create_new_column_row(unsigned term_j, const lar_term* term, | ||||
| void lar_solver::add_constraint_from_term_and_create_new_column_row(unsigned term_j, const lar_term* term, | ||||
|                                                         lconstraint_kind kind, const mpq & right_side) { | ||||
| 
 | ||||
|     add_row_from_term_no_constraint(term, term_j); | ||||
|  | @ -211,7 +212,7 @@ void add_constraint_from_term_and_create_new_column_row(unsigned term_j, const l | |||
|     lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); | ||||
| } | ||||
| 
 | ||||
| void decide_on_strategy_and_adjust_initial_state() { | ||||
| void lar_solver::decide_on_strategy_and_adjust_initial_state() { | ||||
| 	lean_assert(strategy_is_undecided()); | ||||
| 	if (m_vars_to_ul_pairs.size() > m_settings.column_number_threshold_for_using_lu_in_lar_solver) { | ||||
|         m_settings.simplex_strategy() = simplex_strategy_enum::lu; | ||||
|  | @ -221,7 +222,7 @@ void decide_on_strategy_and_adjust_initial_state() { | |||
|     adjust_initial_state(); | ||||
| } | ||||
| 
 | ||||
| void adjust_initial_state() { | ||||
| void lar_solver::adjust_initial_state() { | ||||
|     switch (m_settings.simplex_strategy()) { | ||||
|     case simplex_strategy_enum::lu: | ||||
|         adjust_initial_state_for_lu(); | ||||
|  | @ -237,7 +238,7 @@ void adjust_initial_state() { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void adjust_initial_state_for_lu() { | ||||
| void lar_solver::adjust_initial_state_for_lu() { | ||||
|     copy_from_mpq_matrix(A_d()); | ||||
| 	unsigned n = A_d().column_count(); | ||||
| 	m_mpq_lar_core_solver.m_d_x.resize(n); | ||||
|  | @ -265,7 +266,7 @@ void adjust_initial_state_for_lu() { | |||
|         }*/ | ||||
| } | ||||
| 
 | ||||
| void adjust_initial_state_for_tableau_rows() { | ||||
| void lar_solver::adjust_initial_state_for_tableau_rows() { | ||||
|     for (unsigned j = 0; j < m_terms.size(); j++) { | ||||
|         if (contains(m_ext_vars_to_columns, j + m_terms_start_index)) | ||||
|             continue; | ||||
|  | @ -274,7 +275,7 @@ void adjust_initial_state_for_tableau_rows() { | |||
| } | ||||
| 
 | ||||
| // this fills the last row of A_d and sets the basis column: -1 in the last column of the row
 | ||||
| void fill_last_row_of_A_d(static_matrix<double, double> & A, const lar_term* ls) { | ||||
| void lar_solver::fill_last_row_of_A_d(static_matrix<double, double> & A, const lar_term* ls) { | ||||
|     lean_assert(A.row_count() > 0); | ||||
|     lean_assert(A.column_count() > 0); | ||||
|     unsigned last_row = A.row_count() - 1; | ||||
|  | @ -290,7 +291,7 @@ void fill_last_row_of_A_d(static_matrix<double, double> & A, const lar_term* ls) | |||
|     A.set(last_row, basis_j, - 1 ); | ||||
| } | ||||
| 
 | ||||
| void update_free_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_ind) { | ||||
| void lar_solver::update_free_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_ind) { | ||||
|     mpq y_of_bound(0); | ||||
|     switch (kind) { | ||||
|     case LT: | ||||
|  | @ -330,7 +331,7 @@ void update_free_column_type_and_bound(var_index j, lconstraint_kind kind, const | |||
|     m_columns_with_changed_bound.insert(j); | ||||
| } | ||||
| 
 | ||||
| void update_upper_bound_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { | ||||
| void lar_solver::update_upper_bound_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { | ||||
|     lean_assert(m_mpq_lar_core_solver.m_column_types()[j] == column_type::upper_bound); | ||||
|     mpq y_of_bound(0); | ||||
|     switch (kind) { | ||||
|  | @ -387,7 +388,7 @@ void update_upper_bound_column_type_and_bound(var_index j, lconstraint_kind kind | |||
|     } | ||||
| } | ||||
|      | ||||
| void update_boxed_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { | ||||
| void lar_solver::update_boxed_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { | ||||
|     lean_assert(m_status == INFEASIBLE || (m_mpq_lar_core_solver.m_column_types()[j] == column_type::boxed && m_mpq_lar_core_solver.m_r_low_bounds()[j] < m_mpq_lar_core_solver.m_r_upper_bounds()[j])); | ||||
|     mpq y_of_bound(0); | ||||
|     switch (kind) { | ||||
|  | @ -457,7 +458,7 @@ void update_boxed_column_type_and_bound(var_index j, lconstraint_kind kind, cons | |||
|                  | ||||
|     } | ||||
| } | ||||
| void update_low_bound_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { | ||||
| void lar_solver::update_low_bound_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { | ||||
|     lean_assert(m_mpq_lar_core_solver.m_column_types()[j] == column_type::low_bound); | ||||
|     mpq y_of_bound(0); | ||||
|     switch (kind) { | ||||
|  | @ -513,7 +514,7 @@ void update_low_bound_column_type_and_bound(var_index j, lconstraint_kind kind, | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void update_fixed_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { | ||||
| void lar_solver::update_fixed_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { | ||||
|     lean_assert(m_status == INFEASIBLE || (m_mpq_lar_core_solver.m_column_types()[j] == column_type::fixed && m_mpq_lar_core_solver.m_r_low_bounds()[j] == m_mpq_lar_core_solver.m_r_upper_bounds()[j])); | ||||
|     lean_assert(m_status == INFEASIBLE || (m_mpq_lar_core_solver.m_r_low_bounds()[j].y.is_zero() && m_mpq_lar_core_solver.m_r_upper_bounds()[j].y.is_zero())); | ||||
|     auto v = numeric_pair<mpq>(right_side, mpq(0)); | ||||
|  | @ -574,3 +575,4 @@ void update_fixed_column_type_and_bound(var_index j, lconstraint_kind kind, cons | |||
|     } | ||||
| } | ||||
|      | ||||
| } | ||||
							
								
								
									
										6
									
								
								src/util/lp/int_solver.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/util/lp/int_solver.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| /*
 | ||||
|   Copyright (c) 2017 Microsoft Corporation | ||||
|   Author: Lev Nachmanson | ||||
| */ | ||||
| 
 | ||||
| #include "util/lp/int_solver.h" | ||||
							
								
								
									
										44
									
								
								src/util/lp/int_solver.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/util/lp/int_solver.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | |||
| /*
 | ||||
|   Copyright (c) 2017 Microsoft Corporation | ||||
|   Author: Lev Nachmanson | ||||
| */ | ||||
| #pragma once | ||||
| #include "util/lp/lp_settings.h" | ||||
| class lemma; // forward definition
 | ||||
| namespace lean { | ||||
| class lar_solver; | ||||
| template <typename T, typename X> | ||||
| struct lp_constraint; | ||||
| 
 | ||||
| class int_solver { | ||||
| public: | ||||
|     lar_solver *m_solver; | ||||
|      | ||||
|     int_solver(lar_solver* lp); | ||||
|     bool check();// main function to check that solution provided by lar_solver is valid for integral values or can be adjusted.
 | ||||
| private: | ||||
| 
 | ||||
|     // how to tighten bounds for integer variables.
 | ||||
|      | ||||
|      | ||||
|     // gcd test
 | ||||
|     // 5*x + 3*y + 6*z = 5
 | ||||
|     // suppose x is fixed at 2.
 | ||||
|     // so we have 10 + 3(y + 2z) = 5
 | ||||
|     //             5 = -3(y + 2z)
 | ||||
|     // this is unsolvable because 5/3 is not an integer.
 | ||||
|     // so we create a lemma that rules out this condition.
 | ||||
|     // 
 | ||||
|     bool gcd_test(lemma& lemma); // returns false in case of failure. Creates a theory lemma in case of failure.
 | ||||
| 
 | ||||
|     // create goromy cuts
 | ||||
|     // either creates a conflict or a bound.
 | ||||
| 
 | ||||
|     // branch and bound: 
 | ||||
|     // decide what to branch and bound on
 | ||||
|     // creates a fresh inequality.
 | ||||
| 
 | ||||
|     bool branch(const lp_constraint<mpq, mpq> & new_inequality); | ||||
|      | ||||
| }; | ||||
| } | ||||
							
								
								
									
										1396
									
								
								src/util/lp/lar_solver.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1396
									
								
								src/util/lp/lar_solver.cpp
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										17
									
								
								src/util/lp/lar_solver_instances.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/util/lp/lar_solver_instances.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,17 @@ | |||
| /*
 | ||||
|   Copyright (c) 2017 Microsoft Corporation | ||||
|   Author: Lev Nachmanson | ||||
| */ | ||||
| 
 | ||||
| #include "util/lp/lar_solver.cpp" | ||||
| #include "util/lp/init_lar_solver.cpp" | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| template void  lean::lar_solver::copy_from_mpq_matrix<double,double>(class lean::static_matrix<double,double> &); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue