mirror of
https://github.com/Z3Prover/z3
synced 2025-05-02 21:37:02 +00:00
merge
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
fe1a07a8ee
402 changed files with 7898 additions and 3782 deletions
40
src/util/lp/CMakeLists.txt
Normal file
40
src/util/lp/CMakeLists.txt
Normal file
|
@ -0,0 +1,40 @@
|
|||
z3_add_component(lp
|
||||
SOURCES
|
||||
lp_utils.cpp
|
||||
binary_heap_priority_queue_instances.cpp
|
||||
binary_heap_upair_queue_instances.cpp
|
||||
bound_propagator.cpp
|
||||
core_solver_pretty_printer_instances.cpp
|
||||
dense_matrix_instances.cpp
|
||||
eta_matrix_instances.cpp
|
||||
indexed_vector_instances.cpp
|
||||
int_solver.cpp
|
||||
lar_solver_instances.cpp
|
||||
lar_core_solver_instances.cpp
|
||||
lp_core_solver_base_instances.cpp
|
||||
lp_dual_core_solver_instances.cpp
|
||||
lp_dual_simplex_instances.cpp
|
||||
lp_primal_core_solver_instances.cpp
|
||||
lp_primal_simplex_instances.cpp
|
||||
lp_settings_instances.cpp
|
||||
lp_solver_instances.cpp
|
||||
lu_instances.cpp
|
||||
matrix_instances.cpp
|
||||
nra_solver.cpp
|
||||
permutation_matrix_instances.cpp
|
||||
quick_xplain.cpp
|
||||
row_eta_matrix_instances.cpp
|
||||
scaler_instances.cpp
|
||||
sparse_matrix_instances.cpp
|
||||
square_dense_submatrix_instances.cpp
|
||||
static_matrix_instances.cpp
|
||||
random_updater_instances.cpp
|
||||
COMPONENT_DEPENDENCIES
|
||||
util
|
||||
polynomial
|
||||
nlsat
|
||||
PYG_FILES
|
||||
lp_params.pyg
|
||||
)
|
||||
|
||||
include_directories(${src_SOURCE_DIR})
|
|
@ -7,7 +7,7 @@
|
|||
#include "util/vector.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/lp/lp_utils.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
// the elements with the smallest priority are dequeued first
|
||||
template <typename T>
|
||||
class binary_heap_priority_queue {
|
||||
|
@ -60,7 +60,7 @@ public:
|
|||
/// return the first element of the queue and removes it from the queue
|
||||
unsigned dequeue();
|
||||
unsigned peek() const {
|
||||
lean_assert(m_heap_size > 0);
|
||||
lp_assert(m_heap_size > 0);
|
||||
return m_heap[1];
|
||||
}
|
||||
#ifdef LEAN_DEBUG
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
#include "util/vector.h"
|
||||
#include "util/lp/binary_heap_priority_queue.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
// is is the child place in heap
|
||||
template <typename T> void binary_heap_priority_queue<T>::swap_with_parent(unsigned i) {
|
||||
unsigned parent = m_heap[i >> 1];
|
||||
|
@ -33,8 +33,8 @@ template <typename T> void binary_heap_priority_queue<T>::decrease_priority(unsi
|
|||
template <typename T> bool binary_heap_priority_queue<T>::is_consistent() const {
|
||||
for (int i = 0; i < m_heap_inverse.size(); i++) {
|
||||
int i_index = m_heap_inverse[i];
|
||||
lean_assert(i_index <= static_cast<int>(m_heap_size));
|
||||
lean_assert(i_index == -1 || m_heap[i_index] == i);
|
||||
lp_assert(i_index <= static_cast<int>(m_heap_size));
|
||||
lp_assert(i_index == -1 || m_heap[i_index] == i);
|
||||
}
|
||||
for (unsigned i = 1; i < m_heap_size; i++) {
|
||||
unsigned ch = i << 1;
|
||||
|
@ -55,7 +55,7 @@ template <typename T> void binary_heap_priority_queue<T>::remove(unsigned o) {
|
|||
if (o_in_heap == -1) {
|
||||
return; // nothing to do
|
||||
}
|
||||
lean_assert(static_cast<unsigned>(o_in_heap) <= m_heap_size);
|
||||
lp_assert(static_cast<unsigned>(o_in_heap) <= m_heap_size);
|
||||
if (static_cast<unsigned>(o_in_heap) < m_heap_size) {
|
||||
put_at(o_in_heap, m_heap[m_heap_size--]);
|
||||
if (m_priorities[m_heap[o_in_heap]] > priority_of_o) {
|
||||
|
@ -72,11 +72,11 @@ template <typename T> void binary_heap_priority_queue<T>::remove(unsigned o) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
lean_assert(static_cast<unsigned>(o_in_heap) == m_heap_size);
|
||||
lp_assert(static_cast<unsigned>(o_in_heap) == m_heap_size);
|
||||
m_heap_size--;
|
||||
}
|
||||
m_heap_inverse[o] = -1;
|
||||
// lean_assert(is_consistent());
|
||||
// lp_assert(is_consistent());
|
||||
}
|
||||
// n is the initial queue capacity.
|
||||
// The capacity will be enlarged two times automatically if needed
|
||||
|
@ -102,7 +102,7 @@ template <typename T> void binary_heap_priority_queue<T>::put_to_heap(unsigned i
|
|||
template <typename T> void binary_heap_priority_queue<T>::enqueue_new(unsigned o, const T& priority) {
|
||||
m_heap_size++;
|
||||
int i = m_heap_size;
|
||||
lean_assert(o < m_priorities.size());
|
||||
lp_assert(o < m_priorities.size());
|
||||
m_priorities[o] = priority;
|
||||
put_at(i, o);
|
||||
while (i > 1 && m_priorities[m_heap[i >> 1]] > priority) {
|
||||
|
@ -134,7 +134,7 @@ template <typename T> void binary_heap_priority_queue<T>::change_priority_for_ex
|
|||
|
||||
/// return the first element of the queue and removes it from the queue
|
||||
template <typename T> unsigned binary_heap_priority_queue<T>::dequeue_and_get_priority(T & priority) {
|
||||
lean_assert(m_heap_size != 0);
|
||||
lp_assert(m_heap_size != 0);
|
||||
int ret = m_heap[1];
|
||||
priority = m_priorities[ret];
|
||||
put_the_last_at_the_top_and_fix_the_heap();
|
||||
|
@ -168,7 +168,7 @@ template <typename T> void binary_heap_priority_queue<T>::put_the_last_at_the_to
|
|||
}
|
||||
/// return the first element of the queue and removes it from the queue
|
||||
template <typename T> unsigned binary_heap_priority_queue<T>::dequeue() {
|
||||
lean_assert(m_heap_size > 0);
|
||||
lp_assert(m_heap_size > 0);
|
||||
int ret = m_heap[1];
|
||||
put_the_last_at_the_top_and_fix_the_heap();
|
||||
m_heap_inverse[ret] = -1;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
#include "util/lp/numeric_pair.h"
|
||||
#include "util/lp/binary_heap_priority_queue.hpp"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template binary_heap_priority_queue<int>::binary_heap_priority_queue(unsigned int);
|
||||
template unsigned binary_heap_priority_queue<int>::dequeue();
|
||||
template void binary_heap_priority_queue<int>::enqueue(unsigned int, int const&);
|
||||
|
@ -16,11 +16,11 @@ template unsigned binary_heap_priority_queue<double>::dequeue();
|
|||
template unsigned binary_heap_priority_queue<mpq>::dequeue();
|
||||
template void binary_heap_priority_queue<numeric_pair<mpq> >::enqueue(unsigned int, numeric_pair<mpq> const&);
|
||||
template void binary_heap_priority_queue<numeric_pair<mpq> >::resize(unsigned int);
|
||||
template void lean::binary_heap_priority_queue<double>::resize(unsigned int);
|
||||
template void lp::binary_heap_priority_queue<double>::resize(unsigned int);
|
||||
template binary_heap_priority_queue<unsigned int>::binary_heap_priority_queue(unsigned int);
|
||||
template void binary_heap_priority_queue<unsigned>::resize(unsigned int);
|
||||
template unsigned binary_heap_priority_queue<unsigned int>::dequeue();
|
||||
template void binary_heap_priority_queue<unsigned int>::enqueue(unsigned int, unsigned int const&);
|
||||
template void binary_heap_priority_queue<unsigned int>::remove(unsigned int);
|
||||
template void lean::binary_heap_priority_queue<mpq>::resize(unsigned int);
|
||||
template void lp::binary_heap_priority_queue<mpq>::resize(unsigned int);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
typedef std::pair<unsigned, unsigned> upair;
|
||||
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T>
|
||||
class binary_heap_upair_queue {
|
||||
binary_heap_priority_queue<T> m_q;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <set>
|
||||
#include "util/lp/lp_utils.h"
|
||||
#include "util/lp/binary_heap_upair_queue.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T> binary_heap_upair_queue<T>::binary_heap_upair_queue(unsigned size) : m_q(size), m_pairs(size) {
|
||||
for (unsigned i = 0; i < size; i++)
|
||||
m_available_spots.push_back(i);
|
||||
|
@ -14,7 +14,7 @@ template <typename T> binary_heap_upair_queue<T>::binary_heap_upair_queue(unsign
|
|||
|
||||
template <typename T> unsigned
|
||||
binary_heap_upair_queue<T>::dequeue_available_spot() {
|
||||
lean_assert(m_available_spots.empty() == false);
|
||||
lp_assert(m_available_spots.empty() == false);
|
||||
unsigned ret = m_available_spots.back();
|
||||
m_available_spots.pop_back();
|
||||
return ret;
|
||||
|
@ -54,7 +54,7 @@ template <typename T> void binary_heap_upair_queue<T>::enqueue(unsigned i, unsig
|
|||
m_pairs.resize(new_size);
|
||||
}
|
||||
ij_index = dequeue_available_spot();
|
||||
// lean_assert(ij_index<m_pairs.size() && ij_index_is_new(ij_index));
|
||||
// lp_assert(ij_index<m_pairs.size() && ij_index_is_new(ij_index));
|
||||
m_pairs[ij_index] = p;
|
||||
m_pairs_to_index[p] = ij_index;
|
||||
} else {
|
||||
|
@ -64,7 +64,7 @@ template <typename T> void binary_heap_upair_queue<T>::enqueue(unsigned i, unsig
|
|||
}
|
||||
|
||||
template <typename T> void binary_heap_upair_queue<T>::dequeue(unsigned & i, unsigned &j) {
|
||||
lean_assert(!m_q.is_empty());
|
||||
lp_assert(!m_q.is_empty());
|
||||
unsigned ij_index = m_q.dequeue();
|
||||
upair & p = m_pairs[ij_index];
|
||||
i = p.first;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
Author: Lev Nachmanson
|
||||
*/
|
||||
#include "util/lp/binary_heap_upair_queue.hpp"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template binary_heap_upair_queue<int>::binary_heap_upair_queue(unsigned int);
|
||||
template binary_heap_upair_queue<unsigned int>::binary_heap_upair_queue(unsigned int);
|
||||
template unsigned binary_heap_upair_queue<int>::dequeue_available_spot();
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// We try to pin a var by pushing the total by using the variable bounds
|
||||
// In a loop we drive the partial sum down, denoting the variables of this process by _u.
|
||||
// In the same loop trying to pin variables by pushing the partial sum up, denoting the variable related to it by _l
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
|
||||
class bound_analyzer_on_row {
|
||||
|
||||
|
@ -91,11 +91,11 @@ public :
|
|||
}
|
||||
|
||||
const impq & ub(unsigned j) const {
|
||||
lean_assert(upper_bound_is_available(j));
|
||||
lp_assert(upper_bound_is_available(j));
|
||||
return m_bp.get_upper_bound(j);
|
||||
}
|
||||
const impq & lb(unsigned j) const {
|
||||
lean_assert(low_bound_is_available(j));
|
||||
lp_assert(low_bound_is_available(j));
|
||||
return m_bp.get_low_bound(j);
|
||||
}
|
||||
|
||||
|
@ -153,7 +153,7 @@ public :
|
|||
void limit_all_monoids_from_above() {
|
||||
int strict = 0;
|
||||
mpq total;
|
||||
lean_assert(is_zero(total));
|
||||
lp_assert(is_zero(total));
|
||||
m_it.reset();
|
||||
mpq a; unsigned j;
|
||||
while (m_it.next(a, j)) {
|
||||
|
@ -180,7 +180,7 @@ public :
|
|||
void limit_all_monoids_from_below() {
|
||||
int strict = 0;
|
||||
mpq total;
|
||||
lean_assert(is_zero(total));
|
||||
lp_assert(is_zero(total));
|
||||
m_it.reset();
|
||||
mpq a; unsigned j;
|
||||
while (m_it.next(a, j)) {
|
||||
|
@ -272,7 +272,7 @@ public :
|
|||
// mpq a; unsigned j;
|
||||
// while (it->next(a, j)) {
|
||||
// if (be.m_j == j) continue;
|
||||
// lean_assert(bound_is_available(j, is_neg(a) ? low_bound : !low_bound));
|
||||
// lp_assert(bound_is_available(j, is_neg(a) ? low_bound : !low_bound));
|
||||
// be.m_vector_of_bound_signatures.emplace_back(a, j, numeric_traits<impq>::
|
||||
// is_neg(a)? low_bound: !low_bound);
|
||||
// }
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
Author: Lev Nachmanson
|
||||
*/
|
||||
#include "util/lp/lar_solver.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
bound_propagator::bound_propagator(lar_solver & ls):
|
||||
m_lar_solver(ls) {}
|
||||
column_type bound_propagator::get_column_type(unsigned j) const {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include "util/lp/lp_settings.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
class lar_solver;
|
||||
class bound_propagator {
|
||||
std::unordered_map<unsigned, unsigned> m_improved_low_bounds; // these maps map a column index to the corresponding index in ibounds
|
||||
|
@ -19,7 +19,7 @@ public:
|
|||
const impq & get_upper_bound(unsigned) const;
|
||||
void try_add_bound(const mpq & v, unsigned j, bool is_low, bool coeff_before_j_is_pos, unsigned row_or_term_index, bool strict);
|
||||
virtual bool bound_is_interesting(unsigned vi,
|
||||
lean::lconstraint_kind kind,
|
||||
lp::lconstraint_kind kind,
|
||||
const rational & bval) {return true;}
|
||||
unsigned number_of_found_bounds() const { return m_ibounds.size(); }
|
||||
virtual void consume(mpq const& v, unsigned j) { std::cout << "doh\n"; }
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
enum breakpoint_type {
|
||||
low_break, upper_break, fixed_break
|
||||
};
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include <string>
|
||||
#include <algorithm>
|
||||
#include "util/lp/lp_settings.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
inline bool is_valid(unsigned j) { return static_cast<int>(j) >= 0;}
|
||||
|
||||
template <typename T>
|
||||
|
@ -100,11 +100,11 @@ public:
|
|||
}
|
||||
|
||||
T get_low_bound() const {
|
||||
lean_assert(m_low_bound_is_set);
|
||||
lp_assert(m_low_bound_is_set);
|
||||
return m_low_bound;
|
||||
}
|
||||
T get_upper_bound() const {
|
||||
lean_assert(m_upper_bound_is_set);
|
||||
lp_assert(m_upper_bound_is_set);
|
||||
return m_upper_bound;
|
||||
}
|
||||
|
||||
|
@ -156,7 +156,7 @@ public:
|
|||
}
|
||||
|
||||
T get_fixed_value() const {
|
||||
lean_assert(m_is_fixed);
|
||||
lp_assert(m_is_fixed);
|
||||
return m_fixed_value;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
#include <string>
|
||||
#include "util/lp/linear_combination_iterator.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
class column_namer {
|
||||
public:
|
||||
virtual std::string get_column_name(unsigned j) const = 0;
|
||||
|
@ -15,7 +15,7 @@ public:
|
|||
T a;
|
||||
unsigned i;
|
||||
while (it->next(a, i)) {
|
||||
coeff.emplace_back(a, i);
|
||||
coeff.push_back(std::make_pair(a, i));
|
||||
}
|
||||
print_linear_combination_of_column_indices(coeff, out);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
Author: Lev Nachmanson
|
||||
*/
|
||||
#pragma once
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename V>
|
||||
struct conversion_helper {
|
||||
static V get_low_bound(const column_info<mpq> & ci) {
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include <ostream>
|
||||
#include "util/lp/lp_settings.h"
|
||||
#include "util/lp/indexed_vector.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T, typename X> class lp_core_solver_base; // forward definition
|
||||
|
||||
template <typename T, typename X>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "util/lp/lp_core_solver_base.h"
|
||||
#include "util/lp/core_solver_pretty_printer.h"
|
||||
#include "util/lp/numeric_pair.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
|
||||
|
||||
template <typename T, typename X>
|
||||
|
@ -148,7 +148,7 @@ template <typename T, typename X> void core_solver_pretty_printer<T, X>::adjust_
|
|||
case column_type::free_column:
|
||||
break;
|
||||
default:
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -357,7 +357,7 @@ template <typename T, typename X> void core_solver_pretty_printer<T, X>::print_g
|
|||
unsigned width = m_column_widths[col];
|
||||
string s = row[col];
|
||||
int number_of_blanks = width - static_cast<unsigned>(s.size());
|
||||
lean_assert(number_of_blanks >= 0);
|
||||
lp_assert(number_of_blanks >= 0);
|
||||
print_blanks(number_of_blanks, m_out);
|
||||
m_out << s << ' ';
|
||||
if (col < row.size() - 1) {
|
||||
|
@ -368,7 +368,7 @@ template <typename T, typename X> void core_solver_pretty_printer<T, X>::print_g
|
|||
|
||||
string rs = T_to_string(rst);
|
||||
int nb = m_rs_width - static_cast<int>(rs.size());
|
||||
lean_assert(nb >= 0);
|
||||
lp_assert(nb >= 0);
|
||||
print_blanks(nb + 1, m_out);
|
||||
m_out << rs << std::endl;
|
||||
}
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
*/
|
||||
#include "util/lp/numeric_pair.h"
|
||||
#include "util/lp/core_solver_pretty_printer.hpp"
|
||||
template lean::core_solver_pretty_printer<double, double>::core_solver_pretty_printer(lean::lp_core_solver_base<double, double> &, std::ostream & out);
|
||||
template void lean::core_solver_pretty_printer<double, double>::print();
|
||||
template lean::core_solver_pretty_printer<double, double>::~core_solver_pretty_printer();
|
||||
template lean::core_solver_pretty_printer<lean::mpq, lean::mpq>::core_solver_pretty_printer(lean::lp_core_solver_base<lean::mpq, lean::mpq> &, std::ostream & out);
|
||||
template void lean::core_solver_pretty_printer<lean::mpq, lean::mpq>::print();
|
||||
template lean::core_solver_pretty_printer<lean::mpq, lean::mpq>::~core_solver_pretty_printer();
|
||||
template lean::core_solver_pretty_printer<lean::mpq, lean::numeric_pair<lean::mpq> >::core_solver_pretty_printer(lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> > &, std::ostream & out);
|
||||
template lean::core_solver_pretty_printer<lean::mpq, lean::numeric_pair<lean::mpq> >::~core_solver_pretty_printer();
|
||||
template void lean::core_solver_pretty_printer<lean::mpq, lean::numeric_pair<lean::mpq> >::print();
|
||||
template lp::core_solver_pretty_printer<double, double>::core_solver_pretty_printer(lp::lp_core_solver_base<double, double> &, std::ostream & out);
|
||||
template void lp::core_solver_pretty_printer<double, double>::print();
|
||||
template lp::core_solver_pretty_printer<double, double>::~core_solver_pretty_printer();
|
||||
template lp::core_solver_pretty_printer<lp::mpq, lp::mpq>::core_solver_pretty_printer(lp::lp_core_solver_base<lp::mpq, lp::mpq> &, std::ostream & out);
|
||||
template void lp::core_solver_pretty_printer<lp::mpq, lp::mpq>::print();
|
||||
template lp::core_solver_pretty_printer<lp::mpq, lp::mpq>::~core_solver_pretty_printer();
|
||||
template lp::core_solver_pretty_printer<lp::mpq, lp::numeric_pair<lp::mpq> >::core_solver_pretty_printer(lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> > &, std::ostream & out);
|
||||
template lp::core_solver_pretty_printer<lp::mpq, lp::numeric_pair<lp::mpq> >::~core_solver_pretty_printer();
|
||||
template void lp::core_solver_pretty_printer<lp::mpq, lp::numeric_pair<lp::mpq> >::print();
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#ifdef LEAN_DEBUG
|
||||
#include "util/vector.h"
|
||||
#include "util/lp/matrix.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
// used for debugging purposes only
|
||||
template <typename T, typename X>
|
||||
class dense_matrix: public matrix<T, X> {
|
||||
|
@ -31,7 +31,7 @@ public:
|
|||
dense_matrix(unsigned m, unsigned n);
|
||||
|
||||
dense_matrix operator*=(matrix<T, X> const & a) {
|
||||
lean_assert(column_count() == a.row_count());
|
||||
lp_assert(column_count() == a.row_count());
|
||||
dense_matrix c(row_count(), a.column_count());
|
||||
for (unsigned i = 0; i < row_count(); i++) {
|
||||
for (unsigned j = 0; j < a.column_count(); j++) {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "util/vector.h"
|
||||
#include "util/lp/numeric_pair.h"
|
||||
#include "util/lp/dense_matrix.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T> void print_vector(const vector<T> & t, std::ostream & out);
|
||||
template <typename T, typename X> dense_matrix<T, X>::dense_matrix(unsigned m, unsigned n) : m_m(m), m_n(n), m_values(m * n, numeric_traits<T>::zero()) {
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ template <typename T, typename X> void dense_matrix<T, X>::multiply_row_by_const
|
|||
|
||||
template <typename T, typename X>
|
||||
dense_matrix<T, X> operator* (matrix<T, X> & a, matrix<T, X> & b){
|
||||
lean_assert(a.column_count() == b.row_count());
|
||||
lp_assert(a.column_count() == b.row_count());
|
||||
dense_matrix<T, X> ret(a.row_count(), b.column_count());
|
||||
for (unsigned i = 0; i < ret.m_m; i++)
|
||||
for (unsigned j = 0; j< ret.m_n; j++) {
|
||||
|
|
|
@ -6,19 +6,20 @@
|
|||
#include "util/lp/dense_matrix.hpp"
|
||||
#ifdef LEAN_DEBUG
|
||||
#include "util/vector.h"
|
||||
template lean::dense_matrix<double, double> lean::operator*<double, double>(lean::matrix<double, double>&, lean::matrix<double, double>&);
|
||||
template void lean::dense_matrix<double, double>::apply_from_left(vector<double> &);
|
||||
template lean::dense_matrix<double, double>::dense_matrix(lean::matrix<double, double> const*);
|
||||
template lean::dense_matrix<double, double>::dense_matrix(unsigned int, unsigned int);
|
||||
template lean::dense_matrix<double, double>& lean::dense_matrix<double, double>::operator=(lean::dense_matrix<double, double> const&);
|
||||
template lean::dense_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::dense_matrix(lean::matrix<lean::mpq, lean::numeric_pair<lean::mpq> > const*);
|
||||
template void lean::dense_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::apply_from_left(vector<lean::mpq>&);
|
||||
template lean::dense_matrix<lean::mpq, lean::mpq> lean::operator*<lean::mpq, lean::mpq>(lean::matrix<lean::mpq, lean::mpq>&, lean::matrix<lean::mpq, lean::mpq>&);
|
||||
template lean::dense_matrix<lean::mpq, lean::mpq> & lean::dense_matrix<lean::mpq, lean::mpq>::operator=(lean::dense_matrix<lean::mpq, lean::mpq> const&);
|
||||
template lean::dense_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::dense_matrix(unsigned int, unsigned int);
|
||||
template lean::dense_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >& lean::dense_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::operator=(lean::dense_matrix<lean::mpq, lean::numeric_pair<lean::mpq> > const&);
|
||||
template lean::dense_matrix<lean::mpq, lean::numeric_pair<lean::mpq> > lean::operator*<lean::mpq, lean::numeric_pair<lean::mpq> >(lean::matrix<lean::mpq, lean::numeric_pair<lean::mpq> >&, lean::matrix<lean::mpq, lean::numeric_pair<lean::mpq> >&);
|
||||
template void lean::dense_matrix<lean::mpq, lean::numeric_pair< lean::mpq> >::apply_from_right( vector< lean::mpq> &);
|
||||
template void lean::dense_matrix<double,double>::apply_from_right(class vector<double> &);
|
||||
template void lean::dense_matrix<lean::mpq, lean::mpq>::apply_from_left(vector<lean::mpq>&);
|
||||
template lp::dense_matrix<double, double> lp::operator*<double, double>(lp::matrix<double, double>&, lp::matrix<double, double>&);
|
||||
template void lp::dense_matrix<double, double>::apply_from_left(vector<double> &);
|
||||
template lp::dense_matrix<double, double>::dense_matrix(lp::matrix<double, double> const*);
|
||||
template lp::dense_matrix<double, double>::dense_matrix(unsigned int, unsigned int);
|
||||
template lp::dense_matrix<double, double>& lp::dense_matrix<double, double>::operator=(lp::dense_matrix<double, double> const&);
|
||||
template lp::dense_matrix<lp::mpq, lp::mpq>::dense_matrix(unsigned int, unsigned int);
|
||||
template lp::dense_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::dense_matrix(lp::matrix<lp::mpq, lp::numeric_pair<lp::mpq> > const*);
|
||||
template void lp::dense_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::apply_from_left(vector<lp::mpq>&);
|
||||
template lp::dense_matrix<lp::mpq, lp::mpq> lp::operator*<lp::mpq, lp::mpq>(lp::matrix<lp::mpq, lp::mpq>&, lp::matrix<lp::mpq, lp::mpq>&);
|
||||
template lp::dense_matrix<lp::mpq, lp::mpq> & lp::dense_matrix<lp::mpq, lp::mpq>::operator=(lp::dense_matrix<lp::mpq, lp::mpq> const&);
|
||||
template lp::dense_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::dense_matrix(unsigned int, unsigned int);
|
||||
template lp::dense_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >& lp::dense_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::operator=(lp::dense_matrix<lp::mpq, lp::numeric_pair<lp::mpq> > const&);
|
||||
template lp::dense_matrix<lp::mpq, lp::numeric_pair<lp::mpq> > lp::operator*<lp::mpq, lp::numeric_pair<lp::mpq> >(lp::matrix<lp::mpq, lp::numeric_pair<lp::mpq> >&, lp::matrix<lp::mpq, lp::numeric_pair<lp::mpq> >&);
|
||||
template void lp::dense_matrix<lp::mpq, lp::numeric_pair< lp::mpq> >::apply_from_right( vector< lp::mpq> &);
|
||||
template void lp::dense_matrix<double,double>::apply_from_right(class vector<double> &);
|
||||
template void lp::dense_matrix<lp::mpq, lp::mpq>::apply_from_left(vector<lp::mpq>&);
|
||||
#endif
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "util/vector.h"
|
||||
#include "util/lp/tail_matrix.h"
|
||||
#include "util/lp/permutation_matrix.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
|
||||
// This is the sum of a unit matrix and a one-column matrix
|
||||
template <typename T, typename X>
|
||||
|
@ -61,7 +61,7 @@ public:
|
|||
|
||||
|
||||
void push_back(unsigned row_index, T val ) {
|
||||
lean_assert(row_index != m_column_index);
|
||||
lp_assert(row_index != m_column_index);
|
||||
m_column_vector.push_back(row_index, val);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#pragma once
|
||||
#include "util/vector.h"
|
||||
#include "util/lp/eta_matrix.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
|
||||
// This is the sum of a unit matrix and a one-column matrix
|
||||
template <typename T, typename X>
|
||||
|
@ -60,7 +60,7 @@ void eta_matrix<T, X>::apply_from_right(vector<T> & w) {
|
|||
}
|
||||
w[m_column_index] = t;
|
||||
#ifdef LEAN_DEBUG
|
||||
// lean_assert(vectors_are_equal<T>(clone_w, w, get_number_of_rows()));
|
||||
// lp_assert(vectors_are_equal<T>(clone_w, w, get_number_of_rows()));
|
||||
// delete clone_w;
|
||||
#endif
|
||||
}
|
||||
|
@ -100,8 +100,8 @@ void eta_matrix<T, X>::apply_from_right(indexed_vector<T> & w) {
|
|||
}
|
||||
|
||||
#ifdef LEAN_DEBUG
|
||||
// lean_assert(w.is_OK());
|
||||
// lean_assert(vectors_are_equal<T>(wcopy, w.m_data));
|
||||
// lp_assert(w.is_OK());
|
||||
// lp_assert(vectors_are_equal<T>(wcopy, w.m_data));
|
||||
#endif
|
||||
}
|
||||
#ifdef LEAN_DEBUG
|
||||
|
@ -130,7 +130,7 @@ void eta_matrix<T, X>::conjugate_by_permutation(permutation_matrix<T, X> & p) {
|
|||
pair.first = p.get_rev(pair.first);
|
||||
}
|
||||
#ifdef LEAN_DEBUG
|
||||
// lean_assert(deb == *this);
|
||||
// lp_assert(deb == *this);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,22 +7,22 @@
|
|||
#include "util/lp/numeric_pair.h"
|
||||
#include "util/lp/eta_matrix.hpp"
|
||||
#ifdef LEAN_DEBUG
|
||||
template double lean::eta_matrix<double, double>::get_elem(unsigned int, unsigned int) const;
|
||||
template lean::mpq lean::eta_matrix<lean::mpq, lean::mpq>::get_elem(unsigned int, unsigned int) const;
|
||||
template lean::mpq lean::eta_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::get_elem(unsigned int, unsigned int) const;
|
||||
template double lp::eta_matrix<double, double>::get_elem(unsigned int, unsigned int) const;
|
||||
template lp::mpq lp::eta_matrix<lp::mpq, lp::mpq>::get_elem(unsigned int, unsigned int) const;
|
||||
template lp::mpq lp::eta_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::get_elem(unsigned int, unsigned int) const;
|
||||
#endif
|
||||
template void lean::eta_matrix<double, double>::apply_from_left(vector<double>&, lean::lp_settings&);
|
||||
template void lean::eta_matrix<double, double>::apply_from_right(vector<double>&);
|
||||
template void lean::eta_matrix<double, double>::conjugate_by_permutation(lean::permutation_matrix<double, double>&);
|
||||
template void lean::eta_matrix<lean::mpq, lean::mpq>::apply_from_left(vector<lean::mpq>&, lean::lp_settings&);
|
||||
template void lean::eta_matrix<lean::mpq, lean::mpq>::apply_from_right(vector<lean::mpq>&);
|
||||
template void lean::eta_matrix<lean::mpq, lean::mpq>::conjugate_by_permutation(lean::permutation_matrix<lean::mpq, lean::mpq>&);
|
||||
template void lean::eta_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::apply_from_left(vector<lean::numeric_pair<lean::mpq> >&, lean::lp_settings&);
|
||||
template void lean::eta_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::apply_from_right(vector<lean::mpq>&);
|
||||
template void lean::eta_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::conjugate_by_permutation(lean::permutation_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >&);
|
||||
template void lean::eta_matrix<double, double>::apply_from_left_local<double>(lean::indexed_vector<double>&, lean::lp_settings&);
|
||||
template void lean::eta_matrix<lean::mpq, lean::mpq>::apply_from_left_local<lean::mpq>(lean::indexed_vector<lean::mpq>&, lean::lp_settings&);
|
||||
template void lean::eta_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::apply_from_left_local<lean::mpq>(lean::indexed_vector<lean::mpq>&, lean::lp_settings&);
|
||||
template void lean::eta_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::apply_from_right(lean::indexed_vector<lean::mpq>&);
|
||||
template void lean::eta_matrix<lean::mpq, lean::mpq>::apply_from_right(lean::indexed_vector<lean::mpq>&);
|
||||
template void lean::eta_matrix<double, double>::apply_from_right(lean::indexed_vector<double>&);
|
||||
template void lp::eta_matrix<double, double>::apply_from_left(vector<double>&, lp::lp_settings&);
|
||||
template void lp::eta_matrix<double, double>::apply_from_right(vector<double>&);
|
||||
template void lp::eta_matrix<double, double>::conjugate_by_permutation(lp::permutation_matrix<double, double>&);
|
||||
template void lp::eta_matrix<lp::mpq, lp::mpq>::apply_from_left(vector<lp::mpq>&, lp::lp_settings&);
|
||||
template void lp::eta_matrix<lp::mpq, lp::mpq>::apply_from_right(vector<lp::mpq>&);
|
||||
template void lp::eta_matrix<lp::mpq, lp::mpq>::conjugate_by_permutation(lp::permutation_matrix<lp::mpq, lp::mpq>&);
|
||||
template void lp::eta_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::apply_from_left(vector<lp::numeric_pair<lp::mpq> >&, lp::lp_settings&);
|
||||
template void lp::eta_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::apply_from_right(vector<lp::mpq>&);
|
||||
template void lp::eta_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::conjugate_by_permutation(lp::permutation_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >&);
|
||||
template void lp::eta_matrix<double, double>::apply_from_left_local<double>(lp::indexed_vector<double>&, lp::lp_settings&);
|
||||
template void lp::eta_matrix<lp::mpq, lp::mpq>::apply_from_left_local<lp::mpq>(lp::indexed_vector<lp::mpq>&, lp::lp_settings&);
|
||||
template void lp::eta_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::apply_from_left_local<lp::mpq>(lp::indexed_vector<lp::mpq>&, lp::lp_settings&);
|
||||
template void lp::eta_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::apply_from_right(lp::indexed_vector<lp::mpq>&);
|
||||
template void lp::eta_matrix<lp::mpq, lp::mpq>::apply_from_right(lp::indexed_vector<lp::mpq>&);
|
||||
template void lp::eta_matrix<double, double>::apply_from_right(lp::indexed_vector<double>&);
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
#endif
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<lean::mpq> {
|
||||
inline size_t operator()(const lean::mpq & v) const {
|
||||
struct hash<lp::mpq> {
|
||||
inline size_t operator()(const lp::mpq & v) const {
|
||||
return v.hash();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#pragma once
|
||||
#include "util/lp/lp_settings.h"
|
||||
#include "util/lp/lar_constraints.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
struct implied_bound {
|
||||
mpq m_bound;
|
||||
unsigned m_j; // the column for which the bound has been found
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T>
|
||||
class indexed_value {
|
||||
public:
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include "util/lp/lp_utils.h"
|
||||
#include "util/lp/lp_settings.h"
|
||||
#include <unordered_set>
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
|
||||
template <typename T> void print_vector(const vector<T> & t, std::ostream & out);
|
||||
template <typename T> void print_vector(const buffer<T> & t, std::ostream & out);
|
||||
|
@ -75,16 +75,7 @@ public:
|
|||
}
|
||||
|
||||
void set_value(const T& value, unsigned index);
|
||||
void set_value_as_in_dictionary(unsigned index) {
|
||||
lean_assert(index < m_data.size());
|
||||
T & loc = m_data[index];
|
||||
if (is_zero(loc)) {
|
||||
m_index.push_back(index);
|
||||
loc = one_of_type<T>(); // use as a characteristic function
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void clear();
|
||||
void clear_all();
|
||||
const T& operator[] (unsigned i) const {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "util/vector.h"
|
||||
#include "util/lp/indexed_vector.h"
|
||||
#include "util/lp/lp_settings.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
|
||||
template <typename T>
|
||||
void print_vector(const vector<T> & t, std::ostream & out) {
|
||||
|
@ -41,13 +41,13 @@ template <typename T>
|
|||
void indexed_vector<T>::resize(unsigned data_size) {
|
||||
clear();
|
||||
m_data.resize(data_size, numeric_traits<T>::zero());
|
||||
lean_assert(is_OK());
|
||||
lp_assert(is_OK());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void indexed_vector<T>::set_value(const T& value, unsigned index) {
|
||||
m_data[index] = value;
|
||||
lean_assert(std::find(m_index.begin(), m_index.end(), index) == m_index.end());
|
||||
lp_assert(std::find(m_index.begin(), m_index.end(), index) == m_index.end());
|
||||
m_index.push_back(index);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
#include "util/vector.h"
|
||||
#include "util/lp/indexed_vector.hpp"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template void indexed_vector<double>::clear();
|
||||
template void indexed_vector<double>::clear_all();
|
||||
template void indexed_vector<double>::erase_from_index(unsigned int);
|
||||
|
@ -20,17 +20,17 @@ template void indexed_vector<unsigned>::set_value(const unsigned&, unsigned int)
|
|||
#ifdef LEAN_DEBUG
|
||||
template bool indexed_vector<double>::is_OK() const;
|
||||
template bool indexed_vector<mpq>::is_OK() const;
|
||||
template bool indexed_vector<lean::numeric_pair<mpq> >::is_OK() const;
|
||||
template void lean::indexed_vector< lean::mpq>::print(std::basic_ostream<char,struct std::char_traits<char> > &);
|
||||
template void lean::indexed_vector<double>::print(std::basic_ostream<char,struct std::char_traits<char> > &);
|
||||
template void lean::indexed_vector<lean::numeric_pair<lean::mpq> >::print(std::ostream&);
|
||||
template bool indexed_vector<lp::numeric_pair<mpq> >::is_OK() const;
|
||||
template void lp::indexed_vector< lp::mpq>::print(std::basic_ostream<char,struct std::char_traits<char> > &);
|
||||
template void lp::indexed_vector<double>::print(std::basic_ostream<char,struct std::char_traits<char> > &);
|
||||
template void lp::indexed_vector<lp::numeric_pair<lp::mpq> >::print(std::ostream&);
|
||||
#endif
|
||||
}
|
||||
template void lean::print_vector<double>(vector<double> const&, std::ostream&);
|
||||
template void lean::print_vector<unsigned int>(vector<unsigned int> const&, std::ostream&);
|
||||
template void lean::print_vector<std::string>(vector<std::string> const&, std::ostream&);
|
||||
template void lean::print_vector<lean::numeric_pair<lean::mpq> >(vector<lean::numeric_pair<lean::mpq>> const&, std::ostream&);
|
||||
template void lean::indexed_vector<double>::resize(unsigned int);
|
||||
template void lean::print_vector< lean::mpq>(vector< lean::mpq> const &, std::basic_ostream<char, std::char_traits<char> > &);
|
||||
template void lean::print_vector<std::pair<lean::mpq, unsigned int> >(vector<std::pair<lean::mpq, unsigned int>> const&, std::ostream&);
|
||||
template void lean::indexed_vector<lean::numeric_pair<lean::mpq> >::erase_from_index(unsigned int);
|
||||
template void lp::print_vector<double>(vector<double> const&, std::ostream&);
|
||||
template void lp::print_vector<unsigned int>(vector<unsigned int> const&, std::ostream&);
|
||||
template void lp::print_vector<std::string>(vector<std::string> const&, std::ostream&);
|
||||
template void lp::print_vector<lp::numeric_pair<lp::mpq> >(vector<lp::numeric_pair<lp::mpq>> const&, std::ostream&);
|
||||
template void lp::indexed_vector<double>::resize(unsigned int);
|
||||
template void lp::print_vector< lp::mpq>(vector< lp::mpq> const &, std::basic_ostream<char, std::char_traits<char> > &);
|
||||
template void lp::print_vector<std::pair<lp::mpq, unsigned int> >(vector<std::pair<lp::mpq, unsigned int>> const&, std::ostream&);
|
||||
template void lp::indexed_vector<lp::numeric_pair<lp::mpq> >::erase_from_index(unsigned int);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "util/vector.h"
|
||||
#include "util/lp/indexed_vector.h"
|
||||
#include <ostream>
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
// serves at a set of non-negative integers smaller than the set size
|
||||
class int_set {
|
||||
vector<int> m_data;
|
||||
|
@ -20,7 +20,7 @@ public:
|
|||
return m_data[j] >= 0;
|
||||
}
|
||||
void insert(unsigned j) {
|
||||
lean_assert(j < m_data.size());
|
||||
lp_assert(j < m_data.size());
|
||||
if (contains(j)) return;
|
||||
m_data[j] = m_index.size();
|
||||
m_index.push_back(j);
|
||||
|
|
|
@ -4,3 +4,963 @@
|
|||
*/
|
||||
|
||||
#include "util/lp/int_solver.h"
|
||||
#include "util/lp/lar_solver.h"
|
||||
namespace lp {
|
||||
|
||||
void int_solver::fix_non_base_columns() {
|
||||
lp_assert(is_feasible() && inf_int_set_is_correct());
|
||||
auto & lcs = m_lar_solver->m_mpq_lar_core_solver;
|
||||
bool change = false;
|
||||
for (unsigned j : lcs.m_r_nbasis) {
|
||||
if (column_is_int_inf(j)) {
|
||||
change = true;
|
||||
set_value_for_nbasic_column(j, floor(lcs.m_r_x[j].x));
|
||||
}
|
||||
}
|
||||
if (!change)
|
||||
return;
|
||||
if (m_lar_solver->find_feasible_solution() == lp_status::INFEASIBLE)
|
||||
failed();
|
||||
lp_assert(is_feasible() && inf_int_set_is_correct());
|
||||
}
|
||||
|
||||
void int_solver::failed() {
|
||||
auto & lcs = m_lar_solver->m_mpq_lar_core_solver;
|
||||
|
||||
for (unsigned j : m_old_values_set.m_index) {
|
||||
lcs.m_r_x[j] = m_old_values_data[j];
|
||||
lp_assert(lcs.m_r_solver.column_is_feasible(j));
|
||||
lcs.m_r_solver.remove_column_from_inf_set(j);
|
||||
}
|
||||
lp_assert(lcs.m_r_solver.calc_current_x_is_feasible_include_non_basis());
|
||||
lp_assert(lcs.m_r_solver.current_x_is_feasible());
|
||||
m_old_values_set.clear();
|
||||
}
|
||||
|
||||
void int_solver::trace_inf_rows() const {
|
||||
TRACE("arith_int_rows",
|
||||
unsigned num = m_lar_solver->A_r().column_count();
|
||||
for (unsigned v = 0; v < num; v++) {
|
||||
if (is_int(v) && !get_value(v).is_int()) {
|
||||
display_column(tout, v);
|
||||
}
|
||||
}
|
||||
|
||||
num = 0;
|
||||
for (unsigned i = 0; i < m_lar_solver->A_r().row_count(); i++) {
|
||||
unsigned j = m_lar_solver->m_mpq_lar_core_solver.m_r_basis[i];
|
||||
if (column_is_int_inf(j)) {
|
||||
num++;
|
||||
iterator_on_row<mpq> it(m_lar_solver->A_r().m_rows[i]);
|
||||
m_lar_solver->print_linear_iterator(&it, tout);
|
||||
tout << "\n";
|
||||
}
|
||||
}
|
||||
tout << "num of int infeasible: " << num << "\n";
|
||||
);
|
||||
}
|
||||
|
||||
int_set& int_solver::inf_int_set() {
|
||||
return m_lar_solver->m_inf_int_set;
|
||||
}
|
||||
|
||||
const int_set& int_solver::inf_int_set() const {
|
||||
return m_lar_solver->m_inf_int_set;
|
||||
}
|
||||
|
||||
int int_solver::find_inf_int_base_column() {
|
||||
if (inf_int_set().is_empty())
|
||||
return -1;
|
||||
int j = find_inf_int_boxed_base_column_with_smallest_range();
|
||||
if (j != -1)
|
||||
return j;
|
||||
unsigned k = settings().random_next() % inf_int_set().m_index.size();
|
||||
return inf_int_set().m_index[k];
|
||||
}
|
||||
|
||||
int int_solver::find_inf_int_boxed_base_column_with_smallest_range() {
|
||||
int result = -1;
|
||||
mpq range;
|
||||
mpq new_range;
|
||||
mpq small_range_thresold(1024);
|
||||
unsigned n = 0;
|
||||
lar_core_solver & lcs = m_lar_solver->m_mpq_lar_core_solver;
|
||||
|
||||
for (int j : inf_int_set().m_index) {
|
||||
lp_assert(is_base(j) && column_is_int_inf(j));
|
||||
if (!is_boxed(j))
|
||||
continue;
|
||||
new_range = lcs.m_r_upper_bounds()[j].x - lcs.m_r_low_bounds()[j].x;
|
||||
if (new_range > small_range_thresold)
|
||||
continue;
|
||||
if (result == -1) {
|
||||
result = j;
|
||||
range = new_range;
|
||||
n = 1;
|
||||
continue;
|
||||
}
|
||||
if (new_range < range) {
|
||||
n = 1;
|
||||
result = j;
|
||||
range = new_range;
|
||||
continue;
|
||||
}
|
||||
if (new_range == range) {
|
||||
n++;
|
||||
if (settings().random_next() % n == 0) {
|
||||
result = j;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
bool int_solver::is_gomory_cut_target() {
|
||||
m_iter_on_gomory_row->reset();
|
||||
unsigned j;
|
||||
TRACE("gomory_cut", m_lar_solver->print_linear_iterator(m_iter_on_gomory_row, tout);
|
||||
m_iter_on_gomory_row->reset();
|
||||
);
|
||||
|
||||
while (m_iter_on_gomory_row->next(j)) {
|
||||
// All non base variables must be at their bounds and assigned to rationals (that is, infinitesimals are not allowed).
|
||||
if (j != m_gomory_cut_inf_column && (!at_bound(j) || !is_zero(get_value(j).y))) {
|
||||
TRACE("gomory_cut", tout << "row is not gomory cut target:\n";
|
||||
display_column(tout, j);
|
||||
tout << "at_bound: " << at_bound(j) << "\n";
|
||||
tout << "infinitesimal: " << !is_zero(get_value(j).y) << "\n";);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_iter_on_gomory_row->reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void int_solver::real_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, lar_term& pol, explanation & expl) {
|
||||
mpq f_0 = fractional_part(get_value(m_gomory_cut_inf_column));
|
||||
mpq new_a;
|
||||
if (at_lower(x_j)) {
|
||||
if (a.is_pos()) {
|
||||
new_a = a / (1 - f_0);
|
||||
}
|
||||
else {
|
||||
new_a = a / f_0;
|
||||
new_a.neg();
|
||||
}
|
||||
k += lower_bound(x_j).x * k; // k.addmul(new_a, lower_bound(x_j).x); // is it a faster operation
|
||||
|
||||
expl.push_justification(column_low_bound_constraint(x_j), new_a);
|
||||
}
|
||||
else {
|
||||
lp_assert(at_upper(x_j));
|
||||
if (a.is_pos()) {
|
||||
new_a = a / f_0;
|
||||
new_a.neg(); // the upper terms are inverted.
|
||||
}
|
||||
else {
|
||||
new_a = a / (mpq(1) - f_0);
|
||||
}
|
||||
k += upper_bound(x_j).x * k; // k.addmul(new_a, upper_bound(x_j).get_rational());
|
||||
expl.push_justification(column_upper_bound_constraint(x_j), new_a);
|
||||
}
|
||||
TRACE("gomory_cut_detail", tout << a << "*v" << x_j << " k: " << k << "\n";);
|
||||
pol.add_monoid(new_a, x_j);
|
||||
}
|
||||
|
||||
constraint_index int_solver::column_upper_bound_constraint(unsigned j) const {
|
||||
return m_lar_solver->get_column_upper_bound_witness(j);
|
||||
}
|
||||
|
||||
constraint_index int_solver::column_low_bound_constraint(unsigned j) const {
|
||||
return m_lar_solver->get_column_low_bound_witness(j);
|
||||
}
|
||||
|
||||
|
||||
void int_solver::int_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, lar_term & pol, explanation& expl, mpq & lcm_den) {
|
||||
mpq f_0 = fractional_part(get_value(m_gomory_cut_inf_column));
|
||||
lp_assert(is_int(x_j));
|
||||
mpq f_j = fractional_part(a);
|
||||
TRACE("gomory_cut_detail",
|
||||
tout << a << "*v" << x_j << "\n";
|
||||
tout << "fractional_part: " << fractional_part(a) << "\n";
|
||||
tout << "f_j: " << f_j << "\n";
|
||||
tout << "f_0: " << f_0 << "\n";
|
||||
tout << "one_minus_f_0: " << 1 - f_0 << "\n";);
|
||||
if (!f_j.is_zero()) {
|
||||
mpq new_a;
|
||||
if (at_lower(x_j)) {
|
||||
auto one_minus_f_0 = 1 - f_0;
|
||||
if (f_j <= one_minus_f_0) {
|
||||
new_a = f_j / one_minus_f_0;
|
||||
}
|
||||
else {
|
||||
new_a = (1 - f_j) / f_0;
|
||||
}
|
||||
k.addmul(new_a, lower_bound(x_j).x);
|
||||
expl.push_justification(column_low_bound_constraint(x_j), new_a);
|
||||
}
|
||||
else {
|
||||
SASSERT(at_upper(x_j));
|
||||
if (f_j <= f_0) {
|
||||
new_a = f_j / f_0;
|
||||
}
|
||||
else {
|
||||
new_a = (mpq(1) - f_j) / 1 - f_0;
|
||||
}
|
||||
new_a.neg(); // the upper terms are inverted
|
||||
k.addmul(new_a, upper_bound(x_j).x);
|
||||
expl.push_justification(column_upper_bound_constraint(x_j), new_a);
|
||||
}
|
||||
TRACE("gomory_cut_detail", tout << "new_a: " << new_a << " k: " << k << "\n";);
|
||||
pol.add_monoid(new_a, x_j);
|
||||
lcm_den = lcm(lcm_den, denominator(new_a));
|
||||
}
|
||||
}
|
||||
|
||||
lia_move int_solver::report_conflict_from_gomory_cut(mpq & k) {
|
||||
TRACE("empty_pol",
|
||||
display_row_info(tout,
|
||||
m_lar_solver->m_mpq_lar_core_solver.m_r_heading[m_gomory_cut_inf_column]););
|
||||
lp_assert(k.is_pos());
|
||||
// conflict 0 >= k where k is positive
|
||||
k.neg(); // returning 0 <= -k
|
||||
return lia_move::conflict;
|
||||
}
|
||||
|
||||
void int_solver::gomory_cut_adjust_t_and_k_for_size_gt_1(
|
||||
vector<std::pair<mpq, unsigned>> & pol,
|
||||
lar_term & t,
|
||||
mpq &k,
|
||||
unsigned num_ints,
|
||||
mpq & lcm_den) {
|
||||
if (num_ints > 0) {
|
||||
lcm_den = lcm(lcm_den, denominator(k));
|
||||
TRACE("gomory_cut_detail", tout << "k: " << k << " lcm_den: " << lcm_den << "\n";
|
||||
linear_combination_iterator_on_vector<mpq> pi(pol);
|
||||
m_lar_solver->print_linear_iterator(&pi, tout);
|
||||
tout << "\nk: " << k << "\n";);
|
||||
lp_assert(lcm_den.is_pos());
|
||||
if (!lcm_den.is_one()) {
|
||||
// normalize coefficients of integer parameters to be integers.
|
||||
for (auto & pi: pol) {
|
||||
pi.first *= lcm_den;
|
||||
SASSERT(!is_int(pi.second) || pi.first.is_int());
|
||||
}
|
||||
k *= lcm_den;
|
||||
}
|
||||
TRACE("gomory_cut_detail", tout << "after *lcm_den\n";
|
||||
for (unsigned i = 0; i < pol.size(); i++) {
|
||||
tout << pol[i].first << " * v" << pol[i].second << "\n";
|
||||
}
|
||||
tout << "k: " << k << "\n";);
|
||||
}
|
||||
t.clear();
|
||||
// negate everything to return -pol <= -k
|
||||
for (const auto & pi: pol)
|
||||
t.add_monoid(-pi.first, pi.second);
|
||||
k.neg();
|
||||
}
|
||||
|
||||
|
||||
void int_solver::gomory_cut_adjust_t_and_k_for_size_1(const vector<std::pair<mpq, unsigned>> & pol, lar_term& t, mpq &k) {
|
||||
lp_assert(pol.size() == 1);
|
||||
unsigned j = pol[0].second;
|
||||
k /= pol[0].first;
|
||||
bool is_lower = pol[0].first.is_pos();
|
||||
if (is_int(j) && !k.is_int()) {
|
||||
k = is_lower?ceil(k):floor(k);
|
||||
}
|
||||
if (is_lower) { // returning -t <= -k which is equivalent to t >= k
|
||||
k.neg();
|
||||
t.negate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool int_solver::current_solution_is_inf_on_cut(const lar_term& t, const mpq& k) const {
|
||||
const auto & x = m_lar_solver->m_mpq_lar_core_solver.m_r_x;
|
||||
impq v = t.apply(x);
|
||||
TRACE("gomory_cut", tout << "v = " << v << " k = " << k << std::endl;);
|
||||
return v > k;
|
||||
}
|
||||
|
||||
lia_move int_solver::report_gomory_cut(lar_term& t, mpq& k, mpq &lcm_den, unsigned num_ints) {
|
||||
lp_assert(!t.is_empty());
|
||||
auto pol = t.coeffs_as_vector();
|
||||
if (pol.size() == 1)
|
||||
gomory_cut_adjust_t_and_k_for_size_1(pol, t, k);
|
||||
else
|
||||
gomory_cut_adjust_t_and_k_for_size_gt_1(pol, t, k, num_ints, lcm_den);
|
||||
return lia_move::cut;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
lia_move int_solver::mk_gomory_cut(lar_term& t, mpq& k, explanation & expl) {
|
||||
|
||||
lp_assert(column_is_int_inf(m_gomory_cut_inf_column));
|
||||
|
||||
TRACE("gomory_cut", tout << "applying cut at:\n"; m_lar_solver->print_linear_iterator(m_iter_on_gomory_row, tout); tout << std::endl; m_iter_on_gomory_row->reset(););
|
||||
|
||||
// gomory will be t >= k
|
||||
k = 1;
|
||||
mpq lcm_den(1);
|
||||
unsigned num_ints = 0;
|
||||
unsigned x_j;
|
||||
mpq a;
|
||||
while (m_iter_on_gomory_row->next(a, x_j)) {
|
||||
if (x_j == m_gomory_cut_inf_column)
|
||||
continue;
|
||||
// make the format compatible with the format used in: Integrating Simplex with DPLL(T)
|
||||
a.neg();
|
||||
if (is_real(x_j))
|
||||
real_case_in_gomory_cut(a, x_j, k, t, expl);
|
||||
else {
|
||||
num_ints++;
|
||||
int_case_in_gomory_cut(a, x_j, k, t, expl, lcm_den);
|
||||
}
|
||||
}
|
||||
|
||||
if (t.is_empty())
|
||||
return report_conflict_from_gomory_cut(k);
|
||||
|
||||
auto ret = report_gomory_cut(t, k, lcm_den, num_ints);
|
||||
|
||||
// remove this call later :todo
|
||||
m_lar_solver->subs_term_columns(t);
|
||||
lp_assert(current_solution_is_inf_on_cut(t, k));
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
void int_solver::init_check_data() {
|
||||
unsigned n = m_lar_solver->A_r().column_count();
|
||||
m_old_values_set.resize(n);
|
||||
m_old_values_data.resize(n);
|
||||
}
|
||||
|
||||
int int_solver::find_next_free_var_in_gomory_row() {
|
||||
lp_assert(m_iter_on_gomory_row != nullptr);
|
||||
unsigned j;
|
||||
while(m_iter_on_gomory_row->next(j)) {
|
||||
if (j != m_gomory_cut_inf_column && is_free(j))
|
||||
return static_cast<int>(j);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
lia_move int_solver::proceed_with_gomory_cut(lar_term& t, mpq& k, explanation& ex) {
|
||||
int j = find_next_free_var_in_gomory_row();
|
||||
if (j != -1) {
|
||||
m_found_free_var_in_gomory_row = true;
|
||||
lp_assert(t.is_empty());
|
||||
t.add_monoid(mpq(1), j);
|
||||
k = zero_of_type<mpq>();
|
||||
return lia_move::branch; // branch on a free column
|
||||
}
|
||||
if (m_found_free_var_in_gomory_row || !is_gomory_cut_target()) {
|
||||
m_found_free_var_in_gomory_row = false;
|
||||
delete m_iter_on_gomory_row;
|
||||
m_iter_on_gomory_row = nullptr;
|
||||
return lia_move::continue_with_check;
|
||||
}
|
||||
|
||||
lia_move ret = mk_gomory_cut(t, k, ex);
|
||||
delete m_iter_on_gomory_row;
|
||||
m_iter_on_gomory_row = nullptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) {
|
||||
if (m_iter_on_gomory_row != nullptr) {
|
||||
auto ret = proceed_with_gomory_cut(t, k, ex);
|
||||
TRACE("gomory_cut", tout << "term t = "; m_lar_solver->print_term_as_indices(t, tout););
|
||||
if (ret != lia_move::continue_with_check)
|
||||
return ret;
|
||||
}
|
||||
|
||||
init_check_data();
|
||||
lp_assert(inf_int_set_is_correct());
|
||||
// currently it is a reimplementation of
|
||||
// final_check_status theory_arith<Ext>::check_int_feasibility()
|
||||
// from theory_arith_int.h
|
||||
if (m_lar_solver->model_is_int_feasible())
|
||||
return lia_move::ok;
|
||||
if (!gcd_test(ex))
|
||||
return lia_move::conflict;
|
||||
/*
|
||||
if (m_params.m_arith_euclidean_solver)
|
||||
apply_euclidean_solver();
|
||||
|
||||
*/
|
||||
m_lar_solver->pivot_fixed_vars_from_basis();
|
||||
patch_int_infeasible_columns();
|
||||
fix_non_base_columns();
|
||||
TRACE("arith_int_rows", trace_inf_rows(););
|
||||
|
||||
if (find_inf_int_base_column() == -1)
|
||||
return lia_move::ok;
|
||||
|
||||
|
||||
if ((++m_branch_cut_counter) % settings().m_int_branch_cut_threshold == 0) {
|
||||
move_non_base_vars_to_bounds(); // todo track changed variables
|
||||
lp_status st = m_lar_solver->find_feasible_solution();
|
||||
if (st != lp_status::FEASIBLE && st != lp_status::OPTIMAL) {
|
||||
return lia_move::give_up;
|
||||
}
|
||||
lp_assert(inf_int_set_is_correct());
|
||||
// init_inf_int_set(); // todo - can we avoid this call?
|
||||
int j = find_inf_int_base_column();
|
||||
if (j != -1) {
|
||||
// setup the call for gomory cut
|
||||
TRACE("arith_int", tout << "j = " << j << " does not have an integer assignment: " << get_value(j) << "\n";);
|
||||
unsigned row_index = m_lar_solver->m_mpq_lar_core_solver.m_r_heading[j];
|
||||
m_iter_on_gomory_row = m_lar_solver->get_iterator_on_row(row_index);
|
||||
m_gomory_cut_inf_column = j;
|
||||
return check(t, k, ex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
int j = find_inf_int_base_column();
|
||||
if (j != -1) {
|
||||
TRACE("arith_int", tout << "j" << j << " does not have an integer assignment: " << get_value(j) << "\n";);
|
||||
|
||||
lp_assert(t.is_empty());
|
||||
t.add_monoid(mpq(1), j);
|
||||
k = floor(get_value(j));
|
||||
TRACE("arith_int", tout << "branching v" << j << " = " << get_value(j) << "\n";
|
||||
display_column(tout, j);
|
||||
tout << "k = " << k << std::endl;
|
||||
);
|
||||
// todo: remove this call later when theory_lra handles term indices
|
||||
m_lar_solver->subs_term_columns(t);
|
||||
lp_assert(current_solution_is_inf_on_cut(t, k));
|
||||
return lia_move::branch;
|
||||
}
|
||||
}
|
||||
|
||||
lp_assert(m_lar_solver->m_mpq_lar_core_solver.r_basis_is_OK());
|
||||
// return true;
|
||||
return lia_move::give_up;
|
||||
}
|
||||
|
||||
void int_solver::move_non_base_vars_to_bounds() {
|
||||
auto & lcs = m_lar_solver->m_mpq_lar_core_solver;
|
||||
for (unsigned j : lcs.m_r_nbasis) {
|
||||
auto & val = lcs.m_r_x[j];
|
||||
switch (lcs.m_column_types()[j]) {
|
||||
case column_type::boxed:
|
||||
if (val != lcs.m_r_low_bounds()[j] && val != lcs.m_r_upper_bounds()[j])
|
||||
set_value_for_nbasic_column(j, lcs.m_r_low_bounds()[j]);
|
||||
break;
|
||||
case column_type::low_bound:
|
||||
if (val != lcs.m_r_low_bounds()[j])
|
||||
set_value_for_nbasic_column(j, lcs.m_r_low_bounds()[j]);
|
||||
break;
|
||||
case column_type::upper_bound:
|
||||
if (val != lcs.m_r_upper_bounds()[j])
|
||||
set_value_for_nbasic_column(j, lcs.m_r_upper_bounds()[j]);
|
||||
break;
|
||||
default:
|
||||
if (is_int(j) && !val.is_int()) {
|
||||
set_value_for_nbasic_column(j, impq(floor(val)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void int_solver::set_value_for_nbasic_column(unsigned j, const impq & new_val) {
|
||||
lp_assert(!is_base(j));
|
||||
auto & x = m_lar_solver->m_mpq_lar_core_solver.m_r_x[j];
|
||||
if (!m_old_values_set.contains(j)) {
|
||||
m_old_values_set.insert(j);
|
||||
m_old_values_data[j] = x;
|
||||
}
|
||||
auto delta = new_val - x;
|
||||
x = new_val;
|
||||
m_lar_solver->change_basic_x_by_delta_on_column(j, delta);
|
||||
|
||||
auto * it = get_column_iterator(j);
|
||||
update_column_in_int_inf_set(j);
|
||||
unsigned i;
|
||||
while (it->next(i))
|
||||
update_column_in_int_inf_set(m_lar_solver->m_mpq_lar_core_solver.m_r_basis[i]);
|
||||
delete it;
|
||||
}
|
||||
|
||||
void int_solver::patch_int_infeasible_columns() {
|
||||
bool inf_l, inf_u;
|
||||
impq l, u;
|
||||
mpq m;
|
||||
auto & lcs = m_lar_solver->m_mpq_lar_core_solver;
|
||||
for (unsigned j : lcs.m_r_nbasis) {
|
||||
if (!is_int(j))
|
||||
continue;
|
||||
get_freedom_interval_for_column(j, inf_l, l, inf_u, u, m);
|
||||
impq & val = lcs.m_r_x[j];
|
||||
bool val_is_int = val.is_int();
|
||||
bool m_is_one = m.is_one();
|
||||
if (m.is_one() && val_is_int)
|
||||
continue;
|
||||
// check whether value of j is already a multiple of m.
|
||||
if (val_is_int && (val.x / m).is_int())
|
||||
continue;
|
||||
TRACE("patch_int",
|
||||
tout << "TARGET j" << j << " -> [";
|
||||
if (inf_l) tout << "-oo"; else tout << l;
|
||||
tout << ", ";
|
||||
if (inf_u) tout << "oo"; else tout << u;
|
||||
tout << "]";
|
||||
tout << ", m: " << m << ", val: " << val << ", is_int: " << m_lar_solver->column_is_int(j) << "\n";);
|
||||
if (!inf_l) {
|
||||
l = m_is_one? ceil(l) : m * ceil(l / m);
|
||||
if (inf_u || l <= u) {
|
||||
TRACE("patch_int",
|
||||
tout << "patching with l: " << l << '\n';);
|
||||
|
||||
set_value_for_nbasic_column(j, l);
|
||||
} else {
|
||||
TRACE("patch_int",
|
||||
tout << "not patching " << l << "\n";);
|
||||
}
|
||||
} else if (!inf_u) {
|
||||
u = m_is_one? floor(u) : m * floor(u / m);
|
||||
set_value_for_nbasic_column(j, u);
|
||||
TRACE("patch_int",
|
||||
tout << "patching with u: " << u << '\n';);
|
||||
} else {
|
||||
set_value_for_nbasic_column(j, impq(0));
|
||||
TRACE("patch_int",
|
||||
tout << "patching with 0\n";);
|
||||
}
|
||||
lp_assert(is_feasible() && inf_int_set_is_correct());
|
||||
}
|
||||
}
|
||||
|
||||
mpq get_denominators_lcm(iterator_on_row<mpq> &it) {
|
||||
mpq r(1);
|
||||
mpq a;
|
||||
unsigned j;
|
||||
while (it.next(a, j)) {
|
||||
r = lcm(r, denominator(a));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
bool int_solver::gcd_test_for_row(static_matrix<mpq, numeric_pair<mpq>> & A, unsigned i, explanation & ex) {
|
||||
iterator_on_row<mpq> it(A.m_rows[i]);
|
||||
mpq lcm_den = get_denominators_lcm(it);
|
||||
mpq consts(0);
|
||||
mpq gcds(0);
|
||||
mpq least_coeff(0);
|
||||
bool least_coeff_is_bounded = false;
|
||||
mpq a;
|
||||
unsigned j;
|
||||
while (it.next(a, j)) {
|
||||
if (m_lar_solver->column_is_fixed(j)) {
|
||||
mpq aux = lcm_den * a;
|
||||
consts += aux * m_lar_solver->column_low_bound(j).x;
|
||||
}
|
||||
else if (m_lar_solver->column_is_real(j)) {
|
||||
return true;
|
||||
}
|
||||
else if (gcds.is_zero()) {
|
||||
gcds = abs(lcm_den * a);
|
||||
least_coeff = gcds;
|
||||
least_coeff_is_bounded = m_lar_solver->column_is_bounded(j);
|
||||
}
|
||||
else {
|
||||
mpq aux = abs(lcm_den * a);
|
||||
gcds = gcd(gcds, aux);
|
||||
if (aux < least_coeff) {
|
||||
least_coeff = aux;
|
||||
least_coeff_is_bounded = m_lar_solver->column_is_bounded(j);
|
||||
}
|
||||
else if (least_coeff_is_bounded && aux == least_coeff) {
|
||||
least_coeff_is_bounded = m_lar_solver->column_is_bounded(j);
|
||||
}
|
||||
}
|
||||
SASSERT(gcds.is_int());
|
||||
SASSERT(least_coeff.is_int());
|
||||
TRACE("gcd_test_bug", tout << "coeff: " << a << ", gcds: " << gcds
|
||||
<< " least_coeff: " << least_coeff << " consts: " << consts << "\n";);
|
||||
|
||||
}
|
||||
|
||||
if (gcds.is_zero()) {
|
||||
// All variables are fixed.
|
||||
// This theory guarantees that the assignment satisfies each row, and
|
||||
// fixed integer variables are assigned to integer values.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(consts / gcds).is_int())
|
||||
fill_explanation_from_fixed_columns(it, ex);
|
||||
|
||||
if (least_coeff.is_one() && !least_coeff_is_bounded) {
|
||||
SASSERT(gcds.is_one());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (least_coeff_is_bounded) {
|
||||
return ext_gcd_test(it, least_coeff, lcm_den, consts, ex);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void int_solver::add_to_explanation_from_fixed_or_boxed_column(unsigned j, explanation & ex) {
|
||||
constraint_index lc, uc;
|
||||
m_lar_solver->get_bound_constraint_witnesses_for_column(j, lc, uc);
|
||||
ex.m_explanation.push_back(std::make_pair(mpq(1), lc));
|
||||
ex.m_explanation.push_back(std::make_pair(mpq(1), uc));
|
||||
}
|
||||
void int_solver::fill_explanation_from_fixed_columns(iterator_on_row<mpq> & it, explanation & ex) {
|
||||
it.reset();
|
||||
unsigned j;
|
||||
while (it.next(j)) {
|
||||
if (!m_lar_solver->column_is_fixed(j))
|
||||
continue;
|
||||
add_to_explanation_from_fixed_or_boxed_column(j, ex);
|
||||
}
|
||||
}
|
||||
|
||||
bool int_solver::gcd_test(explanation & ex) {
|
||||
auto & A = m_lar_solver->A_r(); // getting the matrix
|
||||
for (unsigned i = 0; i < A.row_count(); i++)
|
||||
if (!gcd_test_for_row(A, i, ex)) {
|
||||
std::cout << "false from gcd_test\n" ;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool int_solver::ext_gcd_test(iterator_on_row<mpq> & it,
|
||||
mpq const & least_coeff,
|
||||
mpq const & lcm_den,
|
||||
mpq const & consts, explanation& ex) {
|
||||
mpq gcds(0);
|
||||
mpq l(consts);
|
||||
mpq u(consts);
|
||||
|
||||
it.reset();
|
||||
mpq a;
|
||||
unsigned j;
|
||||
while (it.next(a, j)) {
|
||||
if (m_lar_solver->column_is_fixed(j))
|
||||
continue;
|
||||
SASSERT(!m_lar_solver->column_is_real(j));
|
||||
mpq ncoeff = lcm_den * a;
|
||||
SASSERT(ncoeff.is_int());
|
||||
mpq abs_ncoeff = abs(ncoeff);
|
||||
if (abs_ncoeff == least_coeff) {
|
||||
SASSERT(m_lar_solver->column_is_bounded(j));
|
||||
if (ncoeff.is_pos()) {
|
||||
// l += ncoeff * m_lar_solver->column_low_bound(j).x;
|
||||
l.addmul(ncoeff, m_lar_solver->column_low_bound(j).x);
|
||||
// u += ncoeff * m_lar_solver->column_upper_bound(j).x;
|
||||
u.addmul(ncoeff, m_lar_solver->column_upper_bound(j).x);
|
||||
}
|
||||
else {
|
||||
// l += ncoeff * upper_bound(j).get_rational();
|
||||
l.addmul(ncoeff, m_lar_solver->column_upper_bound(j).x);
|
||||
// u += ncoeff * lower_bound(j).get_rational();
|
||||
u.addmul(ncoeff, m_lar_solver->column_low_bound(j).x);
|
||||
}
|
||||
add_to_explanation_from_fixed_or_boxed_column(j, ex);
|
||||
}
|
||||
else if (gcds.is_zero()) {
|
||||
gcds = abs_ncoeff;
|
||||
}
|
||||
else {
|
||||
gcds = gcd(gcds, abs_ncoeff);
|
||||
}
|
||||
SASSERT(gcds.is_int());
|
||||
}
|
||||
|
||||
if (gcds.is_zero()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
mpq l1 = ceil(l/gcds);
|
||||
mpq u1 = floor(u/gcds);
|
||||
|
||||
if (u1 < l1) {
|
||||
fill_explanation_from_fixed_columns(it, ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
linear_combination_iterator<mpq> * int_solver::get_column_iterator(unsigned j) {
|
||||
if (m_lar_solver->use_tableau())
|
||||
return new iterator_on_column<mpq, impq>(m_lar_solver->A_r().m_columns[j], m_lar_solver->A_r());
|
||||
return new iterator_on_indexed_vector<mpq>(m_lar_solver->get_column_in_lu_mode(j));
|
||||
}
|
||||
|
||||
|
||||
int_solver::int_solver(lar_solver* lar_slv) :
|
||||
m_lar_solver(lar_slv),
|
||||
m_branch_cut_counter(0),
|
||||
m_iter_on_gomory_row(nullptr),
|
||||
m_found_free_var_in_gomory_row(false) {
|
||||
lp_assert(m_old_values_set.size() == 0);
|
||||
m_old_values_set.resize(lar_slv->A_r().column_count());
|
||||
m_old_values_data.resize(lar_slv->A_r().column_count(), zero_of_type<impq>());
|
||||
}
|
||||
|
||||
bool int_solver::lower(unsigned j) const {
|
||||
switch (m_lar_solver->m_mpq_lar_core_solver.m_column_types()[j]) {
|
||||
case column_type::fixed:
|
||||
case column_type::boxed:
|
||||
case column_type::low_bound:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool int_solver::upper(unsigned j) const {
|
||||
switch (m_lar_solver->m_mpq_lar_core_solver.m_column_types()[j]) {
|
||||
case column_type::fixed:
|
||||
case column_type::boxed:
|
||||
case column_type::upper_bound:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const impq& int_solver::lower_bound(unsigned j) const {
|
||||
return m_lar_solver->m_mpq_lar_core_solver.m_r_low_bounds()[j];
|
||||
}
|
||||
|
||||
const impq& int_solver::upper_bound(unsigned j) const {
|
||||
return m_lar_solver->m_mpq_lar_core_solver.m_r_upper_bounds()[j];
|
||||
}
|
||||
|
||||
|
||||
void set_lower(impq & l,
|
||||
bool & inf_l,
|
||||
impq const & v ) {
|
||||
if (inf_l || v > l) {
|
||||
l = v;
|
||||
inf_l = false;
|
||||
}
|
||||
}
|
||||
|
||||
void set_upper(impq & u,
|
||||
bool & inf_u,
|
||||
impq const & v) {
|
||||
if (inf_u || v < u) {
|
||||
u = v;
|
||||
inf_u = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool int_solver::get_freedom_interval_for_column(unsigned x_j, bool & inf_l, impq & l, bool & inf_u, impq & u, mpq & m) {
|
||||
auto & lcs = m_lar_solver->m_mpq_lar_core_solver;
|
||||
if (lcs.m_r_heading[x_j] >= 0) // the basic var
|
||||
return false;
|
||||
|
||||
impq const & x_j_val = lcs.m_r_x[x_j];
|
||||
linear_combination_iterator<mpq> *it = get_column_iterator(x_j);
|
||||
|
||||
inf_l = true;
|
||||
inf_u = true;
|
||||
l = u = zero_of_type<impq>();
|
||||
m = mpq(1);
|
||||
|
||||
if (lower(x_j)) {
|
||||
set_lower(l, inf_l, lower_bound(x_j));
|
||||
}
|
||||
if (upper(x_j)) {
|
||||
set_upper(u, inf_u, upper_bound(x_j));
|
||||
}
|
||||
|
||||
mpq a_ij; unsigned i;
|
||||
while (it->next(a_ij, i)) {
|
||||
unsigned x_i = lcs.m_r_basis[i];
|
||||
impq const & x_i_val = lcs.m_r_x[x_i];
|
||||
if (is_int(x_i) && is_int(x_j) && !a_ij.is_int())
|
||||
m = lcm(m, denominator(a_ij));
|
||||
bool x_i_lower = lower(x_i);
|
||||
bool x_i_upper = upper(x_i);
|
||||
if (a_ij.is_neg()) {
|
||||
if (x_i_lower) {
|
||||
impq new_l = x_j_val + ((x_i_val - lcs.m_r_low_bounds()[x_i]) / a_ij);
|
||||
set_lower(l, inf_l, new_l);
|
||||
if (!inf_l && !inf_u && l == u) break;;
|
||||
}
|
||||
if (x_i_upper) {
|
||||
impq new_u = x_j_val + ((x_i_val - lcs.m_r_upper_bounds()[x_i]) / a_ij);
|
||||
set_upper(u, inf_u, new_u);
|
||||
if (!inf_l && !inf_u && l == u) break;;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (x_i_upper) {
|
||||
impq new_l = x_j_val + ((x_i_val - lcs.m_r_upper_bounds()[x_i]) / a_ij);
|
||||
set_lower(l, inf_l, new_l);
|
||||
if (!inf_l && !inf_u && l == u) break;;
|
||||
}
|
||||
if (x_i_lower) {
|
||||
impq new_u = x_j_val + ((x_i_val - lcs.m_r_low_bounds()[x_i]) / a_ij);
|
||||
set_upper(u, inf_u, new_u);
|
||||
if (!inf_l && !inf_u && l == u) break;;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete it;
|
||||
TRACE("freedom_interval",
|
||||
tout << "freedom variable for:\n";
|
||||
tout << m_lar_solver->get_column_name(x_j);
|
||||
tout << "[";
|
||||
if (inf_l) tout << "-oo"; else tout << l;
|
||||
tout << "; ";
|
||||
if (inf_u) tout << "oo"; else tout << u;
|
||||
tout << "]\n";
|
||||
tout << "val = " << get_value(x_j) << "\n";
|
||||
);
|
||||
lp_assert(inf_l || l <= get_value(x_j));
|
||||
lp_assert(inf_u || u >= get_value(x_j));
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool int_solver::is_int(unsigned j) const {
|
||||
return m_lar_solver->column_is_int(j);
|
||||
}
|
||||
|
||||
bool int_solver::is_real(unsigned j) const {
|
||||
return !is_int(j);
|
||||
}
|
||||
|
||||
bool int_solver::value_is_int(unsigned j) const {
|
||||
return m_lar_solver->m_mpq_lar_core_solver.m_r_x[j].is_int();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool int_solver::is_feasible() const {
|
||||
auto & lcs = m_lar_solver->m_mpq_lar_core_solver;
|
||||
lp_assert(
|
||||
lcs.m_r_solver.calc_current_x_is_feasible_include_non_basis() ==
|
||||
lcs.m_r_solver.current_x_is_feasible());
|
||||
return lcs.m_r_solver.current_x_is_feasible();
|
||||
}
|
||||
const impq & int_solver::get_value(unsigned j) const {
|
||||
return m_lar_solver->m_mpq_lar_core_solver.m_r_x[j];
|
||||
}
|
||||
|
||||
void int_solver::display_column(std::ostream & out, unsigned j) const {
|
||||
m_lar_solver->m_mpq_lar_core_solver.m_r_solver.print_column_info(j, out);
|
||||
}
|
||||
|
||||
bool int_solver::inf_int_set_is_correct() const {
|
||||
for (unsigned j = 0; j < m_lar_solver->A_r().column_count(); j++) {
|
||||
if (inf_int_set().contains(j) != (is_int(j) && (!value_is_int(j))))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool int_solver::column_is_int_inf(unsigned j) const {
|
||||
return is_int(j) && (!value_is_int(j));
|
||||
}
|
||||
|
||||
void int_solver::update_column_in_int_inf_set(unsigned j) {
|
||||
if (is_int(j) && (!value_is_int(j)))
|
||||
inf_int_set().insert(j);
|
||||
else
|
||||
inf_int_set().erase(j);
|
||||
}
|
||||
|
||||
bool int_solver::is_base(unsigned j) const {
|
||||
return m_lar_solver->m_mpq_lar_core_solver.m_r_heading[j] >= 0;
|
||||
}
|
||||
|
||||
bool int_solver::is_boxed(unsigned j) const {
|
||||
return m_lar_solver->m_mpq_lar_core_solver.m_column_types[j] == column_type::boxed;
|
||||
}
|
||||
|
||||
bool int_solver::is_free(unsigned j) const {
|
||||
return m_lar_solver->m_mpq_lar_core_solver.m_column_types[j] == column_type::free_column;
|
||||
}
|
||||
|
||||
bool int_solver::at_bound(unsigned j) const {
|
||||
auto & mpq_solver = m_lar_solver->m_mpq_lar_core_solver.m_r_solver;
|
||||
switch (mpq_solver.m_column_types[j] ) {
|
||||
case column_type::fixed:
|
||||
case column_type::boxed:
|
||||
return
|
||||
mpq_solver.m_low_bounds[j] == get_value(j) ||
|
||||
mpq_solver.m_upper_bounds[j] == get_value(j);
|
||||
case column_type::low_bound:
|
||||
return mpq_solver.m_low_bounds[j] == get_value(j);
|
||||
case column_type::upper_bound:
|
||||
return mpq_solver.m_upper_bounds[j] == get_value(j);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool int_solver::at_lower(unsigned j) const {
|
||||
auto & mpq_solver = m_lar_solver->m_mpq_lar_core_solver.m_r_solver;
|
||||
switch (mpq_solver.m_column_types[j] ) {
|
||||
case column_type::fixed:
|
||||
case column_type::boxed:
|
||||
case column_type::low_bound:
|
||||
return mpq_solver.m_low_bounds[j] == get_value(j);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool int_solver::at_upper(unsigned j) const {
|
||||
auto & mpq_solver = m_lar_solver->m_mpq_lar_core_solver.m_r_solver;
|
||||
switch (mpq_solver.m_column_types[j] ) {
|
||||
case column_type::fixed:
|
||||
case column_type::boxed:
|
||||
case column_type::upper_bound:
|
||||
return mpq_solver.m_upper_bounds[j] == get_value(j);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
lp_settings& int_solver::settings() {
|
||||
return m_lar_solver->settings();
|
||||
}
|
||||
|
||||
void int_solver::display_row_info(std::ostream & out, unsigned row_index) const {
|
||||
auto & rslv = m_lar_solver->m_mpq_lar_core_solver.m_r_solver;
|
||||
auto it = m_lar_solver->get_iterator_on_row(row_index);
|
||||
mpq a;
|
||||
unsigned j;
|
||||
while (it->next(a, j)) {
|
||||
if (numeric_traits<mpq>::is_pos(a))
|
||||
out << "+";
|
||||
out << a << rslv.column_name(j) << " ";
|
||||
}
|
||||
|
||||
it->reset();
|
||||
while(it->next(j)) {
|
||||
rslv.print_column_bound_info(j, out);
|
||||
}
|
||||
rslv.print_column_bound_info(rslv.m_basis[row_index], out);
|
||||
delete it;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,22 +4,53 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include "util/lp/lp_settings.h"
|
||||
class lemma; // forward definition
|
||||
namespace lean {
|
||||
#include "util/lp/static_matrix.h"
|
||||
#include "util/lp/iterator_on_row.h"
|
||||
#include "util/lp/int_set.h"
|
||||
#include "util/lp/lar_term.h"
|
||||
namespace lp {
|
||||
class lar_solver;
|
||||
template <typename T, typename X>
|
||||
struct lp_constraint;
|
||||
enum class lia_move {
|
||||
ok,
|
||||
branch,
|
||||
cut,
|
||||
conflict,
|
||||
continue_with_check,
|
||||
give_up
|
||||
};
|
||||
|
||||
struct explanation {
|
||||
vector<std::pair<mpq, constraint_index>> m_explanation;
|
||||
void push_justification(constraint_index j, const mpq& v) {
|
||||
m_explanation.push_back(std::make_pair(v, j));
|
||||
}
|
||||
};
|
||||
|
||||
class int_solver {
|
||||
public:
|
||||
lar_solver *m_solver;
|
||||
// fields
|
||||
lar_solver *m_lar_solver;
|
||||
int_set m_old_values_set;
|
||||
vector<impq> m_old_values_data;
|
||||
unsigned m_branch_cut_counter;
|
||||
linear_combination_iterator<mpq>* m_iter_on_gomory_row;
|
||||
unsigned m_gomory_cut_inf_column;
|
||||
bool m_found_free_var_in_gomory_row;
|
||||
|
||||
// methods
|
||||
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.
|
||||
int_set& inf_int_set();
|
||||
const int_set& inf_int_set() const;
|
||||
// main function to check that solution provided by lar_solver is valid for integral values,
|
||||
// or provide a way of how it can be adjusted.
|
||||
lia_move check(lar_term& t, mpq& k, explanation& ex);
|
||||
private:
|
||||
|
||||
// how to tighten bounds for integer variables.
|
||||
|
||||
|
||||
bool gcd_test_for_row(static_matrix<mpq, numeric_pair<mpq>> & A, unsigned i, explanation &);
|
||||
|
||||
// gcd test
|
||||
// 5*x + 3*y + 6*z = 5
|
||||
|
@ -29,7 +60,7 @@ private:
|
|||
// 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.
|
||||
bool gcd_test(explanation & ); // returns false in case of failure. Creates a theory lemma in case of failure.
|
||||
|
||||
// create goromy cuts
|
||||
// either creates a conflict or a bound.
|
||||
|
@ -39,6 +70,70 @@ private:
|
|||
// creates a fresh inequality.
|
||||
|
||||
bool branch(const lp_constraint<mpq, mpq> & new_inequality);
|
||||
|
||||
bool ext_gcd_test(iterator_on_row<mpq> & it,
|
||||
mpq const & least_coeff,
|
||||
mpq const & lcm_den,
|
||||
mpq const & consts,
|
||||
explanation & ex);
|
||||
void fill_explanation_from_fixed_columns(iterator_on_row<mpq> & it, explanation &);
|
||||
void add_to_explanation_from_fixed_or_boxed_column(unsigned j, explanation &);
|
||||
void remove_fixed_vars_from_base();
|
||||
void patch_int_infeasible_columns();
|
||||
bool get_freedom_interval_for_column(unsigned j, bool & inf_l, impq & l, bool & inf_u, impq & u, mpq & m);
|
||||
linear_combination_iterator<mpq> * get_column_iterator(unsigned j);
|
||||
bool lower(unsigned j) const;
|
||||
bool upper(unsigned j) const;
|
||||
const impq & lower_bound(unsigned j) const;
|
||||
const impq & upper_bound(unsigned j) const;
|
||||
bool is_int(unsigned j) const;
|
||||
bool is_real(unsigned j) const;
|
||||
bool is_base(unsigned j) const;
|
||||
bool is_boxed(unsigned j) const;
|
||||
bool is_free(unsigned j) const;
|
||||
bool value_is_int(unsigned j) const;
|
||||
void set_value_for_nbasic_column(unsigned j, const impq & new_val);
|
||||
void fix_non_base_columns();
|
||||
void failed();
|
||||
bool is_feasible() const;
|
||||
const impq & get_value(unsigned j) const;
|
||||
void display_column(std::ostream & out, unsigned j) const;
|
||||
bool inf_int_set_is_correct() const;
|
||||
void update_column_in_int_inf_set(unsigned j);
|
||||
bool column_is_int_inf(unsigned j) const;
|
||||
void trace_inf_rows() const;
|
||||
int find_inf_int_base_column();
|
||||
int find_inf_int_boxed_base_column_with_smallest_range();
|
||||
lp_settings& settings();
|
||||
void move_non_base_vars_to_bounds();
|
||||
void branch_infeasible_int_var(unsigned);
|
||||
lia_move mk_gomory_cut(lar_term& t, mpq& k,explanation & ex);
|
||||
lia_move report_conflict_from_gomory_cut(mpq & k);
|
||||
lia_move report_gomory_cut(lar_term& t, mpq& k, mpq& lcm_den, unsigned num_ints);
|
||||
void init_check_data();
|
||||
bool constrain_free_vars(linear_combination_iterator<mpq> * r);
|
||||
lia_move proceed_with_gomory_cut(lar_term& t, mpq& k, explanation& ex);
|
||||
int find_next_free_var_in_gomory_row();
|
||||
bool is_gomory_cut_target();
|
||||
bool at_bound(unsigned j) const;
|
||||
bool at_lower(unsigned j) const;
|
||||
bool at_upper(unsigned j) const;
|
||||
|
||||
inline static bool is_rational(const impq & n) {
|
||||
return is_zero(n.y);
|
||||
}
|
||||
|
||||
inline static
|
||||
mpq fractional_part(const impq & n) {
|
||||
lp_assert(is_rational);
|
||||
return n.x - floor(n.x);
|
||||
}
|
||||
void real_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, lar_term& t, explanation & ex);
|
||||
void int_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, lar_term& t, explanation& ex, mpq & lcm_den);
|
||||
constraint_index column_upper_bound_constraint(unsigned j) const;
|
||||
constraint_index column_low_bound_constraint(unsigned j) const;
|
||||
void display_row_info(std::ostream & out, unsigned row_index) const;
|
||||
void gomory_cut_adjust_t_and_k_for_size_1(const vector<std::pair<mpq, unsigned>> & pol, lar_term & t, mpq &k);
|
||||
void gomory_cut_adjust_t_and_k_for_size_gt_1(vector<std::pair<mpq, unsigned>> & pol, lar_term & t, mpq &k, unsigned num_ints, mpq &lcm_den);
|
||||
bool current_solution_is_inf_on_cut(const lar_term& t, const mpq& k) const;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "util/lp/linear_combination_iterator.h"
|
||||
#include "util/lp/static_matrix.h"
|
||||
#include "util/lp/lar_term.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T, typename X>
|
||||
struct iterator_on_column:linear_combination_iterator<T> {
|
||||
const vector<column_cell>& m_column; // the offset in term coeffs
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include "util/lp/linear_combination_iterator.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T>
|
||||
struct iterator_on_indexed_vector:linear_combination_iterator<T> {
|
||||
const indexed_vector<T> & m_v;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include "util/lp/iterator_on_indexed_vector.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T>
|
||||
struct iterator_on_pivot_row:linear_combination_iterator<T> {
|
||||
bool m_basis_returned;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include "util/lp/linear_combination_iterator.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T>
|
||||
struct iterator_on_row:linear_combination_iterator<T> {
|
||||
const vector<row_cell<T>> & m_row;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "util/lp/linear_combination_iterator.h"
|
||||
#include "util/lp/numeric_pair.h"
|
||||
#include "util/lp/lar_term.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
struct iterator_on_term_with_basis_var:linear_combination_iterator<mpq> {
|
||||
const lar_term & m_term;
|
||||
std::unordered_map<unsigned, mpq>::const_iterator m_i; // the offset in term coeffs
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include "util/lp/lp_utils.h"
|
||||
#include "util/lp/ul_pair.h"
|
||||
#include "util/lp/lar_term.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
inline lconstraint_kind flip_kind(lconstraint_kind t) {
|
||||
return static_cast<lconstraint_kind>( - static_cast<int>(t));
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ inline std::string lconstraint_kind_string(lconstraint_kind t) {
|
|||
case GT: return std::string(">");
|
||||
case EQ: return std::string("=");
|
||||
}
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
return std::string(); // it is unreachable
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ public:
|
|||
: lar_base_constraint(kind, right_side), m_coeffs(left_side) {}
|
||||
|
||||
lar_constraint(const lar_base_constraint & c) {
|
||||
lean_assert(false); // should not be called : todo!
|
||||
lp_assert(false); // should not be called : todo!
|
||||
}
|
||||
|
||||
unsigned size() const {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "util/lp/iterator_on_column.h"
|
||||
#include "util/lp/iterator_on_indexed_vector.h"
|
||||
#include "util/lp/stacked_value.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
|
||||
class lar_core_solver {
|
||||
// m_sign_of_entering is set to 1 if the entering variable needs
|
||||
|
@ -168,9 +168,9 @@ public:
|
|||
}
|
||||
|
||||
void push() {
|
||||
lean_assert(m_r_solver.basis_heading_is_correct());
|
||||
lean_assert(!need_to_presolve_with_double_solver() || m_d_solver.basis_heading_is_correct());
|
||||
lean_assert(m_column_types.size() == m_r_A.column_count());
|
||||
lp_assert(m_r_solver.basis_heading_is_correct());
|
||||
lp_assert(!need_to_presolve_with_double_solver() || m_d_solver.basis_heading_is_correct());
|
||||
lp_assert(m_column_types.size() == m_r_A.column_count());
|
||||
m_stacked_simplex_strategy = settings().simplex_strategy();
|
||||
m_stacked_simplex_strategy.push();
|
||||
m_column_types.push();
|
||||
|
@ -192,7 +192,7 @@ public:
|
|||
|
||||
template <typename K>
|
||||
void push_vector(stacked_vector<K> & pushed_vector, const vector<K> & vector) {
|
||||
lean_assert(pushed_vector.size() <= vector.size());
|
||||
lp_assert(pushed_vector.size() <= vector.size());
|
||||
for (unsigned i = 0; i < vector.size();i++) {
|
||||
if (i == pushed_vector.size()) {
|
||||
pushed_vector.push_back(vector[i]);
|
||||
|
@ -242,8 +242,8 @@ public:
|
|||
pop_basis(k);
|
||||
m_stacked_simplex_strategy.pop(k);
|
||||
settings().simplex_strategy() = m_stacked_simplex_strategy;
|
||||
lean_assert(m_r_solver.basis_heading_is_correct());
|
||||
lean_assert(!need_to_presolve_with_double_solver() || m_d_solver.basis_heading_is_correct());
|
||||
lp_assert(m_r_solver.basis_heading_is_correct());
|
||||
lp_assert(!need_to_presolve_with_double_solver() || m_d_solver.basis_heading_is_correct());
|
||||
}
|
||||
|
||||
bool need_to_presolve_with_double_solver() const {
|
||||
|
@ -304,11 +304,11 @@ public:
|
|||
break;
|
||||
|
||||
default:
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
}
|
||||
m_r_solver.remove_column_from_inf_set(j);
|
||||
return true;
|
||||
|
@ -317,7 +317,7 @@ public:
|
|||
|
||||
|
||||
void prepare_solver_x_with_signature_tableau(const lar_solution_signature & signature) {
|
||||
lean_assert(m_r_solver.inf_set_is_correct());
|
||||
lp_assert(m_r_solver.inf_set_is_correct());
|
||||
for (auto &t : signature) {
|
||||
unsigned j = t.first;
|
||||
if (m_r_heading[j] >= 0)
|
||||
|
@ -332,9 +332,9 @@ public:
|
|||
m_r_solver.m_x[jb] -= delta * m_r_solver.m_A.get_val(cc);
|
||||
m_r_solver.update_column_in_inf_set(jb);
|
||||
}
|
||||
lean_assert(m_r_solver.A_mult_x_is_off() == false);
|
||||
lp_assert(m_r_solver.A_mult_x_is_off() == false);
|
||||
}
|
||||
lean_assert(m_r_solver.inf_set_is_correct());
|
||||
lp_assert(m_r_solver.inf_set_is_correct());
|
||||
}
|
||||
|
||||
|
||||
|
@ -342,7 +342,7 @@ public:
|
|||
void prepare_solver_x_with_signature(const lar_solution_signature & signature, lp_primal_core_solver<L,K> & s) {
|
||||
for (auto &t : signature) {
|
||||
unsigned j = t.first;
|
||||
lean_assert(m_r_heading[j] < 0);
|
||||
lp_assert(m_r_heading[j] < 0);
|
||||
auto pos_type = t.second;
|
||||
switch (pos_type) {
|
||||
case at_low_bound:
|
||||
|
@ -359,7 +359,7 @@ public:
|
|||
case not_at_bound:
|
||||
switch (m_column_types[j]) {
|
||||
case column_type::free_column:
|
||||
lean_assert(false); // unreachable
|
||||
lp_assert(false); // unreachable
|
||||
case column_type::upper_bound:
|
||||
s.m_x[j] = s.m_upper_bounds[j];
|
||||
break;
|
||||
|
@ -377,15 +377,15 @@ public:
|
|||
s.m_x[j] = s.m_low_bounds[j];
|
||||
break;
|
||||
default:
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
lean_assert(is_zero_vector(s.m_b));
|
||||
lp_assert(is_zero_vector(s.m_b));
|
||||
s.solve_Ax_eq_b();
|
||||
}
|
||||
|
||||
|
@ -418,7 +418,7 @@ public:
|
|||
// the queues of delayed indices
|
||||
std::queue<unsigned> entr_q, leav_q;
|
||||
auto * l = cs.m_factorization;
|
||||
lean_assert(l->get_status() == LU_status::OK);
|
||||
lp_assert(l->get_status() == LU_status::OK);
|
||||
for (unsigned i = 0; i < trace_of_basis_change.size(); i+= 2) {
|
||||
unsigned entering = trace_of_basis_change[i];
|
||||
unsigned leaving = trace_of_basis_change[i+1];
|
||||
|
@ -446,8 +446,8 @@ public:
|
|||
continue;
|
||||
}
|
||||
}
|
||||
lean_assert(cs.m_basis_heading[entering] < 0);
|
||||
lean_assert(cs.m_basis_heading[leaving] >= 0);
|
||||
lp_assert(cs.m_basis_heading[entering] < 0);
|
||||
lp_assert(cs.m_basis_heading[leaving] >= 0);
|
||||
if (l->get_status() == LU_status::OK) {
|
||||
l->prepare_entering(entering, w); // to init vector w
|
||||
l->replace_column(zero_of_type<L>(), w, cs.m_basis_heading[leaving]);
|
||||
|
@ -471,7 +471,7 @@ public:
|
|||
|
||||
void solve_on_signature_tableau(const lar_solution_signature & signature, const vector<unsigned> & changes_of_basis) {
|
||||
r_basis_is_OK();
|
||||
lean_assert(settings().use_tableau());
|
||||
lp_assert(settings().use_tableau());
|
||||
bool r = catch_up_in_lu_tableau(changes_of_basis, m_d_solver.m_basis_heading);
|
||||
|
||||
if (!r) { // it is the case where m_d_solver gives a degenerated basis
|
||||
|
@ -490,10 +490,10 @@ public:
|
|||
return;
|
||||
m_r_solver.stop_tracing_basis_changes();
|
||||
// and now catch up in the double solver
|
||||
lean_assert(m_r_solver.total_iterations() >= m_r_solver.m_trace_of_basis_change_vector.size() /2);
|
||||
lp_assert(m_r_solver.total_iterations() >= m_r_solver.m_trace_of_basis_change_vector.size() /2);
|
||||
catch_up_in_lu(m_r_solver.m_trace_of_basis_change_vector, m_r_solver.m_basis_heading, m_d_solver);
|
||||
}
|
||||
lean_assert(r_basis_is_OK());
|
||||
lp_assert(r_basis_is_OK());
|
||||
}
|
||||
|
||||
bool adjust_x_of_column(unsigned j) {
|
||||
|
@ -507,16 +507,16 @@ public:
|
|||
}
|
||||
|
||||
m_r_solver.snap_column_to_bound_tableau(j);
|
||||
lean_assert(m_r_solver.column_is_feasible(j));
|
||||
lp_assert(m_r_solver.column_is_feasible(j));
|
||||
m_r_solver.m_inf_set.erase(j);
|
||||
*/
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool catch_up_in_lu_tableau(const vector<unsigned> & trace_of_basis_change, const vector<int> & basis_heading) {
|
||||
lean_assert(r_basis_is_OK());
|
||||
lp_assert(r_basis_is_OK());
|
||||
// the queues of delayed indices
|
||||
std::queue<unsigned> entr_q, leav_q;
|
||||
for (unsigned i = 0; i < trace_of_basis_change.size(); i+= 2) {
|
||||
|
@ -546,8 +546,8 @@ public:
|
|||
continue;
|
||||
}
|
||||
}
|
||||
lean_assert(m_r_solver.m_basis_heading[entering] < 0);
|
||||
lean_assert(m_r_solver.m_basis_heading[leaving] >= 0);
|
||||
lp_assert(m_r_solver.m_basis_heading[entering] < 0);
|
||||
lp_assert(m_r_solver.m_basis_heading[leaving] >= 0);
|
||||
m_r_solver.change_basis_unconditionally(entering, leaving);
|
||||
if(!m_r_solver.pivot_column_tableau(entering, m_r_solver.m_basis_heading[entering])) {
|
||||
// unroll the last step
|
||||
|
@ -557,12 +557,12 @@ public:
|
|||
#endif
|
||||
m_r_solver.pivot_column_tableau(leaving, m_r_solver.m_basis_heading[leaving]);
|
||||
#ifdef LEAN_DEBUG
|
||||
lean_assert(t);
|
||||
lp_assert(t);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
lean_assert(r_basis_is_OK());
|
||||
lp_assert(r_basis_is_OK());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -572,21 +572,21 @@ public:
|
|||
if (!m_r_solver.m_settings.use_tableau())
|
||||
return true;
|
||||
for (unsigned j : m_r_solver.m_basis) {
|
||||
lean_assert(m_r_solver.m_A.m_columns[j].size() == 1);
|
||||
lean_assert(m_r_solver.m_A.get_val(m_r_solver.m_A.m_columns[j][0]) == one_of_type<mpq>());
|
||||
lp_assert(m_r_solver.m_A.m_columns[j].size() == 1);
|
||||
lp_assert(m_r_solver.m_A.get_val(m_r_solver.m_A.m_columns[j][0]) == one_of_type<mpq>());
|
||||
}
|
||||
for (unsigned j =0; j < m_r_solver.m_basis_heading.size(); j++) {
|
||||
if (m_r_solver.m_basis_heading[j] >= 0) continue;
|
||||
if (m_r_solver.m_column_types[j] == column_type::fixed) continue;
|
||||
lean_assert(static_cast<unsigned>(- m_r_solver.m_basis_heading[j] - 1) < m_r_solver.m_column_types.size());
|
||||
lean_assert( m_r_solver.m_basis_heading[j] <= -1);
|
||||
lp_assert(static_cast<unsigned>(- m_r_solver.m_basis_heading[j] - 1) < m_r_solver.m_column_types.size());
|
||||
lp_assert( m_r_solver.m_basis_heading[j] <= -1);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void solve_on_signature(const lar_solution_signature & signature, const vector<unsigned> & changes_of_basis) {
|
||||
lean_assert(!settings().use_tableau());
|
||||
lp_assert(!settings().use_tableau());
|
||||
if (m_r_solver.m_factorization == nullptr) {
|
||||
for (unsigned j = 0; j < changes_of_basis.size(); j+=2) {
|
||||
unsigned entering = changes_of_basis[j];
|
||||
|
@ -615,7 +615,7 @@ public:
|
|||
return;
|
||||
m_r_solver.stop_tracing_basis_changes();
|
||||
// and now catch up in the double solver
|
||||
lean_assert(m_r_solver.total_iterations() >= m_r_solver.m_trace_of_basis_change_vector.size() /2);
|
||||
lp_assert(m_r_solver.total_iterations() >= m_r_solver.m_trace_of_basis_change_vector.size() /2);
|
||||
catch_up_in_lu(m_r_solver.m_trace_of_basis_change_vector, m_r_solver.m_basis_heading, m_d_solver);
|
||||
}
|
||||
}
|
||||
|
@ -641,7 +641,7 @@ public:
|
|||
template <typename L, typename K>
|
||||
void extract_signature_from_lp_core_solver(const lp_primal_core_solver<L, K> & solver, lar_solution_signature & signature) {
|
||||
signature.clear();
|
||||
lean_assert(signature.size() == 0);
|
||||
lp_assert(signature.size() == 0);
|
||||
for (unsigned j = 0; j < solver.m_basis_heading.size(); j++) {
|
||||
if (solver.m_basis_heading[j] < 0) {
|
||||
signature[j] = solver.get_non_basic_column_value_position(j);
|
||||
|
@ -664,7 +664,7 @@ public:
|
|||
if (upper_bound_is_set(j)) {
|
||||
const auto & ub = m_r_solver.m_upper_bounds[j];
|
||||
m_d_upper_bounds[j] = ub.x.get_double() + delta * ub.y.get_double();
|
||||
lean_assert(!low_bound_is_set(j) || (m_d_upper_bounds[j] >= m_d_low_bounds[j]));
|
||||
lp_assert(!low_bound_is_set(j) || (m_d_upper_bounds[j] >= m_d_low_bounds[j]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -729,7 +729,7 @@ public:
|
|||
case column_type::fixed:
|
||||
return true;
|
||||
default:
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -744,20 +744,20 @@ public:
|
|||
case column_type::fixed:
|
||||
return true;
|
||||
default:
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void update_delta(mpq& delta, numeric_pair<mpq> const& l, numeric_pair<mpq> const& u) const {
|
||||
lean_assert(l <= u);
|
||||
lp_assert(l <= u);
|
||||
if (l.x < u.x && l.y > u.y) {
|
||||
mpq delta1 = (u.x - l.x) / (l.y - u.y);
|
||||
if (delta1 < delta) {
|
||||
delta = delta1;
|
||||
}
|
||||
}
|
||||
lean_assert(l.x + delta * l.y <= u.x + delta * u.y);
|
||||
lp_assert(l.x + delta * l.y <= u.x + delta * u.y);
|
||||
}
|
||||
|
||||
|
||||
|
@ -796,6 +796,37 @@ public:
|
|||
return new iterator_on_indexed_vector<mpq>(m_r_solver.m_ed);
|
||||
}
|
||||
}
|
||||
|
||||
bool column_is_fixed(unsigned j) const {
|
||||
return m_column_types()[j] == column_type::fixed ||
|
||||
( m_column_types()[j] == column_type::boxed &&
|
||||
m_r_solver.m_low_bounds[j] == m_r_solver.m_upper_bounds[j]);
|
||||
}
|
||||
|
||||
const impq & low_bound(unsigned j) const {
|
||||
lp_assert(m_column_types()[j] == column_type::fixed ||
|
||||
m_column_types()[j] == column_type::boxed ||
|
||||
m_column_types()[j] == column_type::low_bound);
|
||||
return m_r_low_bounds[j];
|
||||
}
|
||||
|
||||
const impq & upper_bound(unsigned j) const {
|
||||
lp_assert(m_column_types()[j] == column_type::fixed ||
|
||||
m_column_types()[j] == column_type::boxed ||
|
||||
m_column_types()[j] == column_type::upper_bound);
|
||||
return m_r_upper_bounds[j];
|
||||
}
|
||||
|
||||
|
||||
const bool column_is_bounded(unsigned j) const {
|
||||
switch(m_column_types()[j]) {
|
||||
case column_type::fixed:
|
||||
case column_type::boxed:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "util/vector.h"
|
||||
#include "util/lp/lar_core_solver.h"
|
||||
#include "util/lp/lar_solution_signature.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
lar_core_solver::lar_core_solver(
|
||||
lp_settings & settings,
|
||||
const column_namer & column_names
|
||||
|
@ -42,9 +42,9 @@ lar_core_solver::lar_core_solver(
|
|||
column_names){}
|
||||
|
||||
void lar_core_solver::init_costs(bool first_time) {
|
||||
lean_assert(false); // should not be called
|
||||
// lean_assert(this->m_x.size() >= this->m_n());
|
||||
// lean_assert(this->m_column_types.size() >= this->m_n());
|
||||
lp_assert(false); // should not be called
|
||||
// lp_assert(this->m_x.size() >= this->m_n());
|
||||
// lp_assert(this->m_column_types.size() >= this->m_n());
|
||||
// if (first_time)
|
||||
// this->m_costs.resize(this->m_n());
|
||||
// X inf = this->m_infeasibility;
|
||||
|
@ -54,7 +54,7 @@ void lar_core_solver::init_costs(bool first_time) {
|
|||
// if (!(first_time || inf >= this->m_infeasibility)) {
|
||||
// LP_OUT(this->m_settings, "iter = " << this->total_iterations() << std::endl);
|
||||
// LP_OUT(this->m_settings, "inf was " << T_to_string(inf) << " and now " << T_to_string(this->m_infeasibility) << std::endl);
|
||||
// lean_assert(false);
|
||||
// lp_assert(false);
|
||||
// }
|
||||
// if (inf == this->m_infeasibility)
|
||||
// this->m_iters_with_no_cost_growing++;
|
||||
|
@ -105,7 +105,7 @@ void lar_core_solver::init_cost_for_column(unsigned j) {
|
|||
this->m_costs[j] = numeric_traits<T>::zero();
|
||||
break;
|
||||
default:
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
break;
|
||||
}*/
|
||||
}
|
||||
|
@ -138,30 +138,14 @@ int lar_core_solver::column_is_out_of_bounds(unsigned j) {
|
|||
return 0;
|
||||
break;
|
||||
}*/
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void lar_core_solver::calculate_pivot_row(unsigned i) {
|
||||
lean_assert(!m_r_solver.use_tableau());
|
||||
lean_assert(m_r_solver.m_pivot_row.is_OK());
|
||||
m_r_solver.m_pivot_row_of_B_1.clear();
|
||||
m_r_solver.m_pivot_row_of_B_1.resize(m_r_solver.m_m());
|
||||
m_r_solver.m_pivot_row.clear();
|
||||
m_r_solver.m_pivot_row.resize(m_r_solver.m_n());
|
||||
if (m_r_solver.m_settings.use_tableau()) {
|
||||
unsigned basis_j = m_r_solver.m_basis[i];
|
||||
for (auto & c : m_r_solver.m_A.m_rows[i]) {
|
||||
if (c.m_j != basis_j)
|
||||
m_r_solver.m_pivot_row.set_value(c.get_val(), c.m_j);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
m_r_solver.calculate_pivot_row_of_B_1(i);
|
||||
m_r_solver.calculate_pivot_row_when_pivot_row_of_B1_is_ready(i);
|
||||
m_r_solver.calculate_pivot_row(i);
|
||||
}
|
||||
|
||||
|
||||
|
@ -208,7 +192,7 @@ void lar_core_solver::calculate_pivot_row(unsigned i) {
|
|||
}
|
||||
|
||||
void lar_core_solver::fill_not_improvable_zero_sum_from_inf_row() {
|
||||
lean_assert(m_r_solver.A_mult_x_is_off() == false);
|
||||
lp_assert(m_r_solver.A_mult_x_is_off() == false);
|
||||
unsigned bj = m_r_basis[m_r_solver.m_inf_row_index_for_tableau];
|
||||
m_infeasible_sum_sign = m_r_solver.inf_sign_of_column(bj);
|
||||
m_infeasible_linear_combination.clear();
|
||||
|
@ -243,32 +227,32 @@ void lar_core_solver::fill_not_improvable_zero_sum() {
|
|||
|
||||
|
||||
void lar_core_solver::solve() {
|
||||
lean_assert(m_r_solver.non_basic_columns_are_set_correctly());
|
||||
lean_assert(m_r_solver.inf_set_is_correct());
|
||||
lp_assert(m_r_solver.non_basic_columns_are_set_correctly());
|
||||
lp_assert(m_r_solver.inf_set_is_correct());
|
||||
if (m_r_solver.current_x_is_feasible() && m_r_solver.m_look_for_feasible_solution_only) {
|
||||
m_r_solver.set_status(OPTIMAL);
|
||||
m_r_solver.set_status(lp_status::OPTIMAL);
|
||||
return;
|
||||
}
|
||||
++settings().st().m_need_to_solve_inf;
|
||||
lean_assert(!m_r_solver.A_mult_x_is_off());
|
||||
lean_assert((!settings().use_tableau()) || r_basis_is_OK());
|
||||
lp_assert(!m_r_solver.A_mult_x_is_off());
|
||||
lp_assert((!settings().use_tableau()) || r_basis_is_OK());
|
||||
if (need_to_presolve_with_double_solver()) {
|
||||
prefix_d();
|
||||
lar_solution_signature solution_signature;
|
||||
vector<unsigned> changes_of_basis = find_solution_signature_with_doubles(solution_signature);
|
||||
if (m_d_solver.get_status() == TIME_EXHAUSTED) {
|
||||
m_r_solver.set_status(TIME_EXHAUSTED);
|
||||
if (m_d_solver.get_status() == lp_status::TIME_EXHAUSTED) {
|
||||
m_r_solver.set_status(lp_status::TIME_EXHAUSTED);
|
||||
return;
|
||||
}
|
||||
if (settings().use_tableau())
|
||||
solve_on_signature_tableau(solution_signature, changes_of_basis);
|
||||
else
|
||||
solve_on_signature(solution_signature, changes_of_basis);
|
||||
lean_assert(!settings().use_tableau() || r_basis_is_OK());
|
||||
lp_assert(!settings().use_tableau() || r_basis_is_OK());
|
||||
} else {
|
||||
if (!settings().use_tableau()) {
|
||||
bool snapped = m_r_solver.snap_non_basic_x_to_bound();
|
||||
lean_assert(m_r_solver.non_basic_columns_are_set_correctly());
|
||||
lp_assert(m_r_solver.non_basic_columns_are_set_correctly());
|
||||
if (snapped)
|
||||
m_r_solver.solve_Ax_eq_b();
|
||||
}
|
||||
|
@ -276,16 +260,16 @@ void lar_core_solver::solve() {
|
|||
m_r_solver.find_feasible_solution();
|
||||
else
|
||||
m_r_solver.solve();
|
||||
lean_assert(!settings().use_tableau() || r_basis_is_OK());
|
||||
lp_assert(!settings().use_tableau() || r_basis_is_OK());
|
||||
}
|
||||
if (m_r_solver.get_status() == INFEASIBLE) {
|
||||
if (m_r_solver.get_status() == lp_status::INFEASIBLE) {
|
||||
fill_not_improvable_zero_sum();
|
||||
} else if (m_r_solver.get_status() != UNBOUNDED) {
|
||||
m_r_solver.set_status(OPTIMAL);
|
||||
} else if (m_r_solver.get_status() != lp_status::UNBOUNDED) {
|
||||
m_r_solver.set_status(lp_status::OPTIMAL);
|
||||
}
|
||||
lean_assert(r_basis_is_OK());
|
||||
lean_assert(m_r_solver.non_basic_columns_are_set_correctly());
|
||||
lean_assert(m_r_solver.inf_set_is_correct());
|
||||
lp_assert(r_basis_is_OK());
|
||||
lp_assert(m_r_solver.non_basic_columns_are_set_correctly());
|
||||
lp_assert(m_r_solver.inf_set_is_correct());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -8,6 +8,6 @@
|
|||
#include "util/debug.h"
|
||||
#include "util/lp/lp_settings.h"
|
||||
#include <unordered_map>
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
typedef std::unordered_map<unsigned, non_basic_column_value_position> lar_solution_signature;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (c) 2017 Microsoft Corporation
|
||||
Author: Lev Nachmanson
|
||||
Author: Nikolaj Bjorner, Lev Nachmanson
|
||||
*/
|
||||
#pragma once
|
||||
#include "util/vector.h"
|
||||
|
@ -33,7 +33,8 @@
|
|||
#include "util/lp/int_solver.h"
|
||||
#include "util/lp/nra_solver.h"
|
||||
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
|
||||
|
||||
|
||||
class lar_solver : public column_namer {
|
||||
|
@ -48,11 +49,11 @@ class lar_solver : public column_namer {
|
|||
};
|
||||
//////////////////// fields //////////////////////////
|
||||
lp_settings m_settings;
|
||||
stacked_value<lp_status> m_status;
|
||||
lp_status m_status;
|
||||
stacked_value<simplex_strategy_enum> m_simplex_strategy;
|
||||
std::unordered_map<unsigned, ext_var_info> m_ext_vars_to_columns;
|
||||
vector<unsigned> m_columns_to_ext_vars_or_term_indices;
|
||||
stacked_vector<ul_pair> m_vars_to_ul_pairs;
|
||||
stacked_vector<ul_pair> m_columns_to_ul_pairs;
|
||||
vector<lar_base_constraint*> m_constraints;
|
||||
stacked_value<unsigned> m_constraint_count;
|
||||
// the set of column indices j such that bounds have changed for j
|
||||
|
@ -68,7 +69,8 @@ public:
|
|||
lar_core_solver m_mpq_lar_core_solver;
|
||||
unsigned constraint_count() const;
|
||||
const lar_base_constraint& get_constraint(unsigned ci) const;
|
||||
|
||||
std::function<void (unsigned, const impq&)> m_tracker_of_x_change;
|
||||
int_set m_inf_int_set;
|
||||
////////////////// methods ////////////////////////////////
|
||||
static_matrix<mpq, numeric_pair<mpq>> & A_r();
|
||||
static_matrix<mpq, numeric_pair<mpq>> const & A_r() const;
|
||||
|
@ -77,7 +79,8 @@ public:
|
|||
|
||||
static bool valid_index(unsigned j){ return static_cast<int>(j) >= 0;}
|
||||
|
||||
|
||||
bool column_is_int(unsigned j) const;
|
||||
bool column_is_fixed(unsigned j) const;
|
||||
public:
|
||||
|
||||
// init region
|
||||
|
@ -85,9 +88,15 @@ public:
|
|||
|
||||
var_index add_var(unsigned ext_j, bool is_integer);
|
||||
|
||||
void register_new_ext_var_index(unsigned ext_v);
|
||||
void register_new_ext_var_index(unsigned ext_v, bool is_int);
|
||||
|
||||
void add_non_basic_var_to_core_fields(unsigned ext_j);
|
||||
bool term_is_int(const lar_term * t) const;
|
||||
|
||||
bool var_is_int(var_index v) const;
|
||||
|
||||
bool ext_var_is_int(var_index ext_var) const;
|
||||
|
||||
void add_non_basic_var_to_core_fields(unsigned ext_j, bool is_int);
|
||||
|
||||
void add_new_var_to_core_fields_for_doubles(bool register_in_basis);
|
||||
|
||||
|
@ -143,7 +152,6 @@ public:
|
|||
|
||||
void clear();
|
||||
|
||||
|
||||
lar_solver();
|
||||
void set_propagate_bounds_on_pivoted_rows_mode(bool v);
|
||||
|
||||
|
@ -215,7 +223,7 @@ public:
|
|||
vector<unsigned> get_list_of_all_var_indices() const;
|
||||
void push();
|
||||
|
||||
static void clean_large_elements_after_pop(unsigned n, int_set& set);
|
||||
static void clean_popped_elements(unsigned n, int_set& set);
|
||||
|
||||
static void shrink_inf_set_after_pop(unsigned n, int_set & set);
|
||||
|
||||
|
@ -256,7 +264,7 @@ public:
|
|||
|
||||
|
||||
void substitute_terms_in_linear_expression( const vector<std::pair<mpq, var_index>>& left_side_with_terms,
|
||||
vector<std::pair<mpq, var_index>> &left_side, mpq & right_side) const;
|
||||
vector<std::pair<mpq, var_index>> &left_side, mpq & free_coeff) const;
|
||||
|
||||
|
||||
void detect_rows_of_bound_change_column_for_nbasic_column(unsigned j);
|
||||
|
@ -321,11 +329,10 @@ public:
|
|||
template <typename U, typename V>
|
||||
void copy_from_mpq_matrix(static_matrix<U, V> & matr);
|
||||
|
||||
column_type get_column_type(const column_info<mpq> & ci);
|
||||
|
||||
bool try_to_set_fixed(column_info<mpq> & ci);
|
||||
|
||||
column_type get_column_type(const column_info<mpq> & ci);
|
||||
|
||||
std::string get_column_name(unsigned j) const;
|
||||
|
||||
bool all_constrained_variables_are_registered(const vector<std::pair<mpq, var_index>>& left_side);
|
||||
|
@ -336,7 +343,7 @@ public:
|
|||
bool the_relations_are_of_same_type(const vector<std::pair<mpq, unsigned>> & evidence, lconstraint_kind & the_kind_of_sum) const;
|
||||
|
||||
static void register_in_map(std::unordered_map<var_index, mpq> & coeffs, const lar_base_constraint & cn, const mpq & a);
|
||||
static void register_one_coeff_in_map(std::unordered_map<var_index, mpq> & coeffs, const mpq & a, unsigned j);
|
||||
static void register_monoid_in_map(std::unordered_map<var_index, mpq> & coeffs, const mpq & a, unsigned j);
|
||||
|
||||
|
||||
bool the_left_sides_sum_to_zero(const vector<std::pair<mpq, unsigned>> & evidence) const;
|
||||
|
@ -362,9 +369,9 @@ public:
|
|||
int inf_sign) const;
|
||||
|
||||
|
||||
|
||||
void get_model(std::unordered_map<var_index, mpq> & variable_values) const;
|
||||
|
||||
void get_model_do_not_care_about_diff_vars(std::unordered_map<var_index, mpq> & variable_values) const;
|
||||
|
||||
std::string get_variable_name(var_index vi) const;
|
||||
|
||||
|
@ -373,12 +380,14 @@ public:
|
|||
|
||||
void print_constraints(std::ostream& out) const ;
|
||||
|
||||
void print_terms(std::ostream& out) const ;
|
||||
void print_terms(std::ostream& out) const;
|
||||
|
||||
void print_left_side_of_constraint(const lar_base_constraint * c, std::ostream & out) const;
|
||||
|
||||
void print_term(lar_term const& term, std::ostream & out) const;
|
||||
|
||||
void print_term_as_indices(lar_term const& term, std::ostream & out) const;
|
||||
|
||||
mpq get_left_side_val(const lar_base_constraint & cns, const std::unordered_map<var_index, mpq> & var_map) const;
|
||||
|
||||
void print_constraint(const lar_base_constraint * c, std::ostream & out) const;
|
||||
|
@ -386,7 +395,7 @@ public:
|
|||
void fill_var_set_for_random_update(unsigned sz, var_index const * vars, vector<unsigned>& column_list);
|
||||
|
||||
void random_update(unsigned sz, var_index const * vars);
|
||||
void try_pivot_fixed_vars_from_basis();
|
||||
void pivot_fixed_vars_from_basis();
|
||||
void pop();
|
||||
bool column_represents_row_in_tableau(unsigned j);
|
||||
void make_sure_that_the_bottom_right_elem_not_zero_in_tableau(unsigned i, unsigned j);
|
||||
|
@ -398,23 +407,74 @@ public:
|
|||
void pop_tableau();
|
||||
void clean_inf_set_of_r_solver_after_pop();
|
||||
void shrink_explanation_to_minimum(vector<std::pair<mpq, constraint_index>> & explanation) const;
|
||||
inline
|
||||
bool column_is_integer(unsigned j) const {
|
||||
unsigned ext_var = m_columns_to_ext_vars_or_term_indices[j];
|
||||
return m_ext_vars_to_columns.find(ext_var)->second.is_integer();
|
||||
}
|
||||
|
||||
static bool impq_is_int(const impq& v) {
|
||||
return v.x.is_int() && is_zero(v.y);
|
||||
}
|
||||
|
||||
inline
|
||||
|
||||
bool column_value_is_integer(unsigned j) const {
|
||||
const impq & v = m_mpq_lar_core_solver.m_r_x[j];
|
||||
return impq_is_int(v);
|
||||
return v.is_int();
|
||||
}
|
||||
|
||||
inline bool column_is_real(unsigned j) const { return !column_is_integer(j); }
|
||||
final_check_status check_int_feasibility();
|
||||
bool column_is_real(unsigned j) const {
|
||||
return !column_is_int(j);
|
||||
}
|
||||
|
||||
bool model_is_int_feasible() const;
|
||||
|
||||
const impq & column_low_bound(unsigned j) const {
|
||||
return m_mpq_lar_core_solver.low_bound(j);
|
||||
}
|
||||
|
||||
const impq & column_upper_bound(unsigned j) const {
|
||||
return m_mpq_lar_core_solver.upper_bound(j);
|
||||
}
|
||||
|
||||
bool column_is_bounded(unsigned j) const {
|
||||
return m_mpq_lar_core_solver.column_is_bounded(j);
|
||||
}
|
||||
|
||||
void get_bound_constraint_witnesses_for_column(unsigned j, constraint_index & lc, constraint_index & uc) const {
|
||||
const ul_pair & ul = m_columns_to_ul_pairs[j];
|
||||
lc = ul.low_bound_witness();
|
||||
uc = ul.upper_bound_witness();
|
||||
}
|
||||
indexed_vector<mpq> & get_column_in_lu_mode(unsigned j) {
|
||||
m_column_buffer.clear();
|
||||
m_column_buffer.resize(A_r().row_count());
|
||||
m_mpq_lar_core_solver.m_r_solver.solve_Bd(j, m_column_buffer);
|
||||
return m_column_buffer;
|
||||
}
|
||||
|
||||
bool bound_is_integer_if_needed(unsigned j, const mpq & right_side) const;
|
||||
linear_combination_iterator<mpq> * get_iterator_on_row(unsigned i) {
|
||||
return m_mpq_lar_core_solver.m_r_solver.get_iterator_on_row(i);
|
||||
}
|
||||
|
||||
unsigned get_base_column_in_row(unsigned row_index) const {
|
||||
return m_mpq_lar_core_solver.m_r_solver.get_base_column_in_row(row_index);
|
||||
}
|
||||
|
||||
constraint_index get_column_upper_bound_witness(unsigned j) const {
|
||||
return m_columns_to_ul_pairs()[j].upper_bound_witness();
|
||||
}
|
||||
|
||||
constraint_index get_column_low_bound_witness(unsigned j) const {
|
||||
return m_columns_to_ul_pairs()[j].low_bound_witness();
|
||||
}
|
||||
|
||||
void subs_term_columns(lar_term& t) {
|
||||
vector<std::pair<mpq, unsigned> > pol;
|
||||
for (const auto & m : t.m_coeffs) {
|
||||
pol.push_back(std::make_pair(m.second, adjust_column_index_to_term_index(m.first)));
|
||||
}
|
||||
mpq v = t.m_v;
|
||||
vector<std::pair<mpq, unsigned>> pol_after_subs;
|
||||
// todo : remove the call to substitute_terms_in_linear_expression, when theory_lra handles the terms indices
|
||||
substitute_terms_in_linear_expression(pol, pol_after_subs, v);
|
||||
t.clear();
|
||||
t = lar_term(pol_after_subs, v);
|
||||
}
|
||||
|
||||
bool has_int_var() const;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,12 +4,8 @@
|
|||
*/
|
||||
|
||||
#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> &);
|
||||
template void lp::lar_solver::copy_from_mpq_matrix<double,double>(class lp::static_matrix<double,double> &);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include "util/lp/indexed_vector.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
struct lar_term {
|
||||
// the term evaluates to sum of m_coeffs + m_v
|
||||
std::unordered_map<unsigned, mpq> m_coeffs;
|
||||
mpq m_v;
|
||||
lar_term() {}
|
||||
void add_to_map(unsigned j, const mpq& c) {
|
||||
void add_monoid(const mpq& c, unsigned j) {
|
||||
auto it = m_coeffs.find(j);
|
||||
if (it == m_coeffs.end()) {
|
||||
m_coeffs.emplace(j, c);
|
||||
|
@ -21,6 +21,10 @@ struct lar_term {
|
|||
}
|
||||
}
|
||||
|
||||
bool is_empty() const {
|
||||
return m_coeffs.size() == 0 && is_zero(m_v);
|
||||
}
|
||||
|
||||
unsigned size() const { return static_cast<unsigned>(m_coeffs.size()); }
|
||||
|
||||
const std::unordered_map<unsigned, mpq> & coeffs() const {
|
||||
|
@ -30,7 +34,7 @@ struct lar_term {
|
|||
lar_term(const vector<std::pair<mpq, unsigned>>& coeffs,
|
||||
const mpq & v) : m_v(v) {
|
||||
for (const auto & p : coeffs) {
|
||||
add_to_map(p.second, p.first);
|
||||
add_monoid(p.first, p.second);
|
||||
}
|
||||
}
|
||||
bool operator==(const lar_term & a) const { return false; } // take care not to create identical terms
|
||||
|
@ -52,7 +56,7 @@ struct lar_term {
|
|||
if (it == m_coeffs.end()) return;
|
||||
const mpq & b = it->second;
|
||||
for (unsigned it_j :li.m_index) {
|
||||
add_to_map(it_j, - b * li.m_data[it_j]);
|
||||
add_monoid(- b * li.m_data[it_j], it_j);
|
||||
}
|
||||
m_coeffs.erase(it);
|
||||
}
|
||||
|
@ -60,5 +64,26 @@ struct lar_term {
|
|||
bool contains(unsigned j) const {
|
||||
return m_coeffs.find(j) != m_coeffs.end();
|
||||
}
|
||||
|
||||
void negate() {
|
||||
for (auto & t : m_coeffs)
|
||||
t.second.neg();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T apply(const vector<T>& x) const {
|
||||
T ret = T(m_v);
|
||||
for (const auto & t : m_coeffs) {
|
||||
ret += t.second * x[t.first];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void clear() {
|
||||
m_coeffs.clear();
|
||||
m_v = zero_of_type<mpq>();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
Author: Lev Nachmanson
|
||||
*/
|
||||
#pragma once
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T>
|
||||
struct linear_combination_iterator {
|
||||
virtual bool next(T & a, unsigned & i) = 0;
|
||||
|
|
|
@ -13,7 +13,10 @@
|
|||
#include "util/lp/lu.h"
|
||||
#include "util/lp/permutation_matrix.h"
|
||||
#include "util/lp/column_namer.h"
|
||||
namespace lean {
|
||||
#include "util/lp/iterator_on_row.h"
|
||||
#include "util/lp/iterator_on_pivot_row.h"
|
||||
|
||||
namespace lp {
|
||||
|
||||
template <typename T, typename X> // X represents the type of the x variable and the bounds
|
||||
class lp_core_solver_base {
|
||||
|
@ -23,7 +26,14 @@ class lp_core_solver_base {
|
|||
private:
|
||||
lp_status m_status;
|
||||
public:
|
||||
bool current_x_is_feasible() const { return m_inf_set.size() == 0; }
|
||||
bool current_x_is_feasible() const {
|
||||
TRACE("feas",
|
||||
if (m_inf_set.size()) {
|
||||
tout << "column " << m_inf_set.m_index[0] << " is infeasible" << std::endl;
|
||||
}
|
||||
);
|
||||
return m_inf_set.size() == 0;
|
||||
}
|
||||
bool current_x_is_infeasible() const { return m_inf_set.size() != 0; }
|
||||
int_set m_inf_set;
|
||||
bool m_using_infeas_costs;
|
||||
|
@ -59,6 +69,12 @@ public:
|
|||
bool m_tracing_basis_changes;
|
||||
int_set* m_pivoted_rows;
|
||||
bool m_look_for_feasible_solution_only;
|
||||
std::function<void (unsigned, const X &)> * m_tracker_of_x_change;
|
||||
|
||||
void set_tracker_of_x(std::function<void (unsigned, const X&)>* tracker) {
|
||||
m_tracker_of_x_change = tracker;
|
||||
}
|
||||
|
||||
void start_tracing_basis_changes() {
|
||||
m_trace_of_basis_change_vector.resize(0);
|
||||
m_tracing_basis_changes = true;
|
||||
|
@ -182,11 +198,11 @@ public:
|
|||
|
||||
|
||||
bool need_to_pivot_to_basis_tableau() const {
|
||||
lean_assert(m_A.is_correct());
|
||||
lp_assert(m_A.is_correct());
|
||||
unsigned m = m_A.row_count();
|
||||
for (unsigned i = 0; i < m; i++) {
|
||||
unsigned bj = m_basis[i];
|
||||
lean_assert(m_A.m_columns[bj].size() > 0);
|
||||
lp_assert(m_A.m_columns[bj].size() > 0);
|
||||
if (m_A.m_columns[bj].size() > 1 || m_A.get_val(m_A.m_columns[bj][0]) != one_of_type<mpq>()) return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -195,7 +211,7 @@ public:
|
|||
bool reduced_costs_are_correct_tableau() const {
|
||||
if (m_settings.simplex_strategy() == simplex_strategy_enum::tableau_rows)
|
||||
return true;
|
||||
lean_assert(m_A.is_correct());
|
||||
lp_assert(m_A.is_correct());
|
||||
if (m_using_infeas_costs) {
|
||||
if (infeasibility_costs_are_correct() == false) {
|
||||
std::cout << "infeasibility_costs_are_correct() does not hold" << std::endl;
|
||||
|
@ -370,11 +386,11 @@ public:
|
|||
}
|
||||
|
||||
bool make_column_feasible(unsigned j, numeric_pair<mpq> & delta) {
|
||||
lean_assert(m_basis_heading[j] < 0);
|
||||
lp_assert(m_basis_heading[j] < 0);
|
||||
auto & x = m_x[j];
|
||||
switch (m_column_types[j]) {
|
||||
case column_type::fixed:
|
||||
lean_assert(m_low_bounds[j] == m_upper_bounds[j]);
|
||||
lp_assert(m_low_bounds[j] == m_upper_bounds[j]);
|
||||
if (x != m_low_bounds[j]) {
|
||||
delta = m_low_bounds[j] - x;
|
||||
x = m_low_bounds[j];
|
||||
|
@ -410,7 +426,7 @@ public:
|
|||
case column_type::free_column:
|
||||
break;
|
||||
default:
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
|
@ -429,6 +445,7 @@ public:
|
|||
void init_lu();
|
||||
int pivots_in_column_and_row_are_different(int entering, int leaving) const;
|
||||
void pivot_fixed_vars_from_basis();
|
||||
bool pivot_column_general(unsigned j, unsigned j_basic, indexed_vector<T> & w);
|
||||
bool pivot_for_tableau_on_basis();
|
||||
bool pivot_row_for_tableau_on_basis(unsigned row);
|
||||
void init_basic_part_of_basis_heading() {
|
||||
|
@ -458,7 +475,7 @@ public:
|
|||
}
|
||||
|
||||
void change_basis_unconditionally(unsigned entering, unsigned leaving) {
|
||||
lean_assert(m_basis_heading[entering] < 0);
|
||||
lp_assert(m_basis_heading[entering] < 0);
|
||||
int place_in_non_basis = -1 - m_basis_heading[entering];
|
||||
if (static_cast<unsigned>(place_in_non_basis) >= m_nbasis.size()) {
|
||||
// entering variable in not in m_nbasis, we need to put it back;
|
||||
|
@ -477,7 +494,8 @@ public:
|
|||
}
|
||||
|
||||
void change_basis(unsigned entering, unsigned leaving) {
|
||||
lean_assert(m_basis_heading[entering] < 0);
|
||||
lp_assert(m_basis_heading[entering] < 0);
|
||||
lp_assert(m_basis_heading[leaving] >= 0);
|
||||
|
||||
int place_in_basis = m_basis_heading[leaving];
|
||||
int place_in_non_basis = - m_basis_heading[entering] - 1;
|
||||
|
@ -518,7 +536,7 @@ public:
|
|||
case column_type::free_column:
|
||||
break;
|
||||
default:
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
|
@ -566,10 +584,10 @@ public:
|
|||
case column_type::free_column:
|
||||
break;
|
||||
default:
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
}
|
||||
std::cout << "basis heading = " << m_basis_heading[j] << std::endl;
|
||||
std::cout << "x = " << m_x[j] << std::endl;
|
||||
out << "basis heading = " << m_basis_heading[j] << std::endl;
|
||||
out << "x = " << m_x[j] << std::endl;
|
||||
/*
|
||||
std::cout << "cost = " << m_costs[j] << std::endl;
|
||||
std:: cout << "m_d = " << m_d[j] << std::endl;*/
|
||||
|
@ -658,24 +676,28 @@ public:
|
|||
|
||||
void update_column_in_inf_set(unsigned j) {
|
||||
if (column_is_feasible(j)) {
|
||||
m_inf_set.erase(j);
|
||||
remove_column_from_inf_set(j);
|
||||
} else {
|
||||
m_inf_set.insert(j);
|
||||
insert_column_into_inf_set(j);
|
||||
}
|
||||
}
|
||||
void insert_column_into_inf_set(unsigned j) {
|
||||
if (m_tracker_of_x_change != nullptr)
|
||||
(*m_tracker_of_x_change)(j, m_x[j]);
|
||||
m_inf_set.insert(j);
|
||||
lean_assert(!column_is_feasible(j));
|
||||
lp_assert(!column_is_feasible(j));
|
||||
}
|
||||
void remove_column_from_inf_set(unsigned j) {
|
||||
if (m_tracker_of_x_change != nullptr)
|
||||
(*m_tracker_of_x_change)(j, m_x[j]);
|
||||
m_inf_set.erase(j);
|
||||
lean_assert(column_is_feasible(j));
|
||||
lp_assert(column_is_feasible(j));
|
||||
}
|
||||
bool costs_on_nbasis_are_zeros() const {
|
||||
lean_assert(this->basis_heading_is_correct());
|
||||
lp_assert(this->basis_heading_is_correct());
|
||||
for (unsigned j = 0; j < this->m_n(); j++) {
|
||||
if (this->m_basis_heading[j] < 0)
|
||||
lean_assert(is_zero(this->m_costs[j]));
|
||||
lp_assert(is_zero(this->m_costs[j]));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -686,5 +708,17 @@ public:
|
|||
const unsigned & iters_with_no_cost_growing() const {
|
||||
return m_iters_with_no_cost_growing;
|
||||
}
|
||||
|
||||
linear_combination_iterator<T> * get_iterator_on_row(unsigned i) {
|
||||
if (m_settings.use_tableau())
|
||||
return new iterator_on_row<T>(m_A.m_rows[i]);
|
||||
calculate_pivot_row(i);
|
||||
return new iterator_on_pivot_row<T>(m_pivot_row, m_basis[i]);
|
||||
}
|
||||
|
||||
void calculate_pivot_row(unsigned i);
|
||||
unsigned get_base_column_in_row(unsigned row_index) const {
|
||||
return m_basis[row_index];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "util/vector.h"
|
||||
#include "util/lp/lp_utils.h"
|
||||
#include "util/lp/lp_core_solver_base.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
|
||||
template <typename T, typename X> lp_core_solver_base<T, X>::
|
||||
lp_core_solver_base(static_matrix<T, X> & A,
|
||||
|
@ -24,7 +24,7 @@ lp_core_solver_base(static_matrix<T, X> & A,
|
|||
const vector<X> & upper_bound_values):
|
||||
m_total_iterations(0),
|
||||
m_iters_with_no_cost_growing(0),
|
||||
m_status(FEASIBLE),
|
||||
m_status(lp_status::FEASIBLE),
|
||||
m_inf_set(A.column_count()),
|
||||
m_using_infeas_costs(false),
|
||||
m_pivot_row_of_B_1(A.row_count()),
|
||||
|
@ -52,8 +52,9 @@ lp_core_solver_base(static_matrix<T, X> & A,
|
|||
m_steepest_edge_coefficients(A.column_count()),
|
||||
m_tracing_basis_changes(false),
|
||||
m_pivoted_rows(nullptr),
|
||||
m_look_for_feasible_solution_only(false) {
|
||||
lean_assert(bounds_for_boxed_are_set_correctly());
|
||||
m_look_for_feasible_solution_only(false),
|
||||
m_tracker_of_x_change(nullptr) {
|
||||
lp_assert(bounds_for_boxed_are_set_correctly());
|
||||
init();
|
||||
init_basis_heading_and_non_basic_columns_vector();
|
||||
}
|
||||
|
@ -61,7 +62,7 @@ lp_core_solver_base(static_matrix<T, X> & A,
|
|||
template <typename T, typename X> void lp_core_solver_base<T, X>::
|
||||
allocate_basis_heading() { // the rest of initilization will be handled by the factorization class
|
||||
init_basis_heading_and_non_basic_columns_vector();
|
||||
lean_assert(basis_heading_is_correct());
|
||||
lp_assert(basis_heading_is_correct());
|
||||
}
|
||||
template <typename T, typename X> void lp_core_solver_base<T, X>::
|
||||
init() {
|
||||
|
@ -83,8 +84,8 @@ pivot_for_tableau_on_basis() {
|
|||
// i is the pivot row, and j is the pivot column
|
||||
template <typename T, typename X> void lp_core_solver_base<T, X>::
|
||||
pivot_to_reduced_costs_tableau(unsigned i, unsigned j) {
|
||||
if (j >= m_d.size())
|
||||
return;
|
||||
if (j >= m_d.size())
|
||||
return;
|
||||
T &a = m_d[j];
|
||||
if (is_zero(a))
|
||||
return;
|
||||
|
@ -127,7 +128,7 @@ solve_yB(vector<T> & y) {
|
|||
// }
|
||||
// }
|
||||
template <typename T, typename X> void lp_core_solver_base<T, X>::solve_Bd(unsigned entering, indexed_vector<T> & column) {
|
||||
lean_assert(!m_settings.use_tableau());
|
||||
lp_assert(!m_settings.use_tableau());
|
||||
if (m_factorization == nullptr) {
|
||||
init_factorization(m_factorization, m_A, m_basis, m_settings);
|
||||
}
|
||||
|
@ -137,19 +138,19 @@ template <typename T, typename X> void lp_core_solver_base<T, X>::solve_Bd(unsig
|
|||
|
||||
template <typename T, typename X> void lp_core_solver_base<T, X>::
|
||||
solve_Bd(unsigned entering) {
|
||||
lean_assert(m_ed.is_OK());
|
||||
lp_assert(m_ed.is_OK());
|
||||
m_factorization->solve_Bd(entering, m_ed, m_w);
|
||||
if (this->precise())
|
||||
m_columns_nz[entering] = m_ed.m_index.size();
|
||||
lean_assert(m_ed.is_OK());
|
||||
lean_assert(m_w.is_OK());
|
||||
lp_assert(m_ed.is_OK());
|
||||
lp_assert(m_w.is_OK());
|
||||
#ifdef LEAN_DEBUG
|
||||
// auto B = get_B(*m_factorization, m_basis);
|
||||
// vector<T> a(m_m());
|
||||
// m_A.copy_column_to_vector(entering, a);
|
||||
// vector<T> cd(m_ed.m_data);
|
||||
// B.apply_from_left(cd, m_settings);
|
||||
// lean_assert(vectors_are_equal(cd , a));
|
||||
// lp_assert(vectors_are_equal(cd , a));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -208,7 +209,7 @@ restore_m_ed(T * buffer) {
|
|||
|
||||
template <typename T, typename X> bool lp_core_solver_base<T, X>::
|
||||
A_mult_x_is_off() const {
|
||||
lean_assert(m_x.size() == m_A.column_count());
|
||||
lp_assert(m_x.size() == m_A.column_count());
|
||||
if (numeric_traits<T>::precise()) {
|
||||
for (unsigned i = 0; i < m_m(); i++) {
|
||||
X delta = m_b[i] - m_A.dot_product_with_row(i, m_x);
|
||||
|
@ -244,7 +245,7 @@ A_mult_x_is_off() const {
|
|||
}
|
||||
template <typename T, typename X> bool lp_core_solver_base<T, X>::
|
||||
A_mult_x_is_off_on_index(const vector<unsigned> & index) const {
|
||||
lean_assert(m_x.size() == m_A.column_count());
|
||||
lp_assert(m_x.size() == m_A.column_count());
|
||||
if (numeric_traits<T>::precise()) return false;
|
||||
#if RUN_A_MULT_X_IS_OFF_FOR_PRECESE
|
||||
for (unsigned i : index) {
|
||||
|
@ -284,13 +285,13 @@ A_mult_x_is_off_on_index(const vector<unsigned> & index) const {
|
|||
// from page 182 of Istvan Maros's book
|
||||
template <typename T, typename X> void lp_core_solver_base<T, X>::
|
||||
calculate_pivot_row_of_B_1(unsigned pivot_row) {
|
||||
lean_assert(! use_tableau());
|
||||
lean_assert(m_pivot_row_of_B_1.is_OK());
|
||||
lp_assert(! use_tableau());
|
||||
lp_assert(m_pivot_row_of_B_1.is_OK());
|
||||
m_pivot_row_of_B_1.clear();
|
||||
m_pivot_row_of_B_1.set_value(numeric_traits<T>::one(), pivot_row);
|
||||
lean_assert(m_pivot_row_of_B_1.is_OK());
|
||||
lp_assert(m_pivot_row_of_B_1.is_OK());
|
||||
m_factorization->solve_yB_with_error_check_indexed(m_pivot_row_of_B_1, m_basis_heading, m_basis, m_settings);
|
||||
lean_assert(m_pivot_row_of_B_1.is_OK());
|
||||
lp_assert(m_pivot_row_of_B_1.is_OK());
|
||||
}
|
||||
|
||||
|
||||
|
@ -380,11 +381,11 @@ set_non_basic_x_to_correct_bounds() {
|
|||
break;
|
||||
case column_type::low_bound:
|
||||
m_x[j] = m_low_bounds[j];
|
||||
lean_assert(column_is_dual_feasible(j));
|
||||
lp_assert(column_is_dual_feasible(j));
|
||||
break;
|
||||
case column_type::upper_bound:
|
||||
m_x[j] = m_upper_bounds[j];
|
||||
lean_assert(column_is_dual_feasible(j));
|
||||
lp_assert(column_is_dual_feasible(j));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -402,15 +403,15 @@ column_is_dual_feasible(unsigned j) const {
|
|||
return x_is_at_low_bound(j) && d_is_not_negative(j);
|
||||
case column_type::upper_bound:
|
||||
LP_OUT(m_settings, "upper_bound type should be switched to low_bound" << std::endl);
|
||||
lean_assert(false); // impossible case
|
||||
lp_assert(false); // impossible case
|
||||
case column_type::free_column:
|
||||
return numeric_traits<X>::is_zero(m_d[j]);
|
||||
default:
|
||||
LP_OUT(m_settings, "column = " << j << std::endl);
|
||||
LP_OUT(m_settings, "unexpected column type = " << column_type_to_string(m_column_types[j]) << std::endl);
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
}
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
return false;
|
||||
}
|
||||
template <typename T, typename X> bool lp_core_solver_base<T, X>::
|
||||
|
@ -493,7 +494,7 @@ template <typename T, typename X> bool lp_core_solver_base<T, X>::column_is_feas
|
|||
return true;
|
||||
break;
|
||||
default:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
}
|
||||
return false; // it is unreachable
|
||||
}
|
||||
|
@ -534,7 +535,7 @@ update_basis_and_x(int entering, int leaving, X const & tt) {
|
|||
if (!find_x_by_solving()) {
|
||||
restore_x(entering, tt);
|
||||
if(A_mult_x_is_off()) {
|
||||
m_status = FLOATING_POINT_ERROR;
|
||||
m_status = lp_status::FLOATING_POINT_ERROR;
|
||||
m_iters_with_no_cost_growing++;
|
||||
return false;
|
||||
}
|
||||
|
@ -544,7 +545,7 @@ update_basis_and_x(int entering, int leaving, X const & tt) {
|
|||
if (m_factorization->get_status() != LU_status::OK) {
|
||||
std::stringstream s;
|
||||
// s << "failing refactor on off_result for entering = " << entering << ", leaving = " << leaving << " total_iterations = " << total_iterations();
|
||||
m_status = FLOATING_POINT_ERROR;
|
||||
m_status = lp_status::FLOATING_POINT_ERROR;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|
@ -566,19 +567,19 @@ update_basis_and_x(int entering, int leaving, X const & tt) {
|
|||
init_lu();
|
||||
if (m_factorization->get_status() != LU_status::OK) {
|
||||
if (m_look_for_feasible_solution_only && !precise()) {
|
||||
m_status = UNSTABLE;
|
||||
m_status = lp_status::UNSTABLE;
|
||||
delete m_factorization;
|
||||
m_factorization = nullptr;
|
||||
return false;
|
||||
}
|
||||
// LP_OUT(m_settings, "failing refactor for entering = " << entering << ", leaving = " << leaving << " total_iterations = " << total_iterations() << std::endl);
|
||||
restore_x_and_refactor(entering, leaving, tt);
|
||||
if (m_status == FLOATING_POINT_ERROR)
|
||||
if (m_status == lp_status::FLOATING_POINT_ERROR)
|
||||
return false;
|
||||
lean_assert(!A_mult_x_is_off());
|
||||
lp_assert(!A_mult_x_is_off());
|
||||
m_iters_with_no_cost_growing++;
|
||||
// LP_OUT(m_settings, "rolled back after failing of init_factorization()" << std::endl);
|
||||
m_status = UNSTABLE;
|
||||
m_status = lp_status::UNSTABLE;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -587,7 +588,7 @@ update_basis_and_x(int entering, int leaving, X const & tt) {
|
|||
|
||||
template <typename T, typename X> bool lp_core_solver_base<T, X>::
|
||||
divide_row_by_pivot(unsigned pivot_row, unsigned pivot_col) {
|
||||
lean_assert(numeric_traits<T>::precise());
|
||||
lp_assert(numeric_traits<T>::precise());
|
||||
int pivot_index = -1;
|
||||
auto & row = m_A.m_rows[pivot_row];
|
||||
unsigned size = row.size();
|
||||
|
@ -628,7 +629,7 @@ pivot_column_tableau(unsigned j, unsigned piv_row_index) {
|
|||
return false;
|
||||
|
||||
if (pivot_col_cell_index != 0) {
|
||||
lean_assert(column.size() > 1);
|
||||
lp_assert(column.size() > 1);
|
||||
// swap the pivot column cell with the head cell
|
||||
auto c = column[0];
|
||||
column[0] = column[pivot_col_cell_index];
|
||||
|
@ -639,7 +640,7 @@ pivot_column_tableau(unsigned j, unsigned piv_row_index) {
|
|||
}
|
||||
while (column.size() > 1) {
|
||||
auto & c = column.back();
|
||||
lean_assert(c.m_i != piv_row_index);
|
||||
lp_assert(c.m_i != piv_row_index);
|
||||
if(! m_A.pivot_row_to_row_given_cell(piv_row_index, c, j)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -687,7 +688,7 @@ non_basis_is_correctly_represented_in_heading() const {
|
|||
}
|
||||
for (unsigned j = 0; j < m_A.column_count(); j++) {
|
||||
if (m_basis_heading[j] >= 0) {
|
||||
lean_assert(static_cast<unsigned>(m_basis_heading[j]) < m_A.row_count() && m_basis[m_basis_heading[j]] == j);
|
||||
lp_assert(static_cast<unsigned>(m_basis_heading[j]) < m_A.row_count() && m_basis[m_basis_heading[j]] == j);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -695,9 +696,9 @@ non_basis_is_correctly_represented_in_heading() const {
|
|||
|
||||
template <typename T, typename X> bool lp_core_solver_base<T, X>::
|
||||
basis_heading_is_correct() const {
|
||||
lean_assert(m_basis_heading.size() == m_A.column_count());
|
||||
lean_assert(m_basis.size() == m_A.row_count());
|
||||
lean_assert(m_nbasis.size() <= m_A.column_count() - m_A.row_count()); // for the dual the size of non basis can be smaller
|
||||
lp_assert(m_basis_heading.size() == m_A.column_count());
|
||||
lp_assert(m_basis.size() == m_A.row_count());
|
||||
lp_assert(m_nbasis.size() <= m_A.column_count() - m_A.row_count()); // for the dual the size of non basis can be smaller
|
||||
if (!basis_has_no_doubles()) {
|
||||
// std::cout << "basis_has_no_doubles" << std::endl;
|
||||
return false;
|
||||
|
@ -841,7 +842,7 @@ solve_Ax_eq_b() {
|
|||
template <typename T, typename X> void lp_core_solver_base<T, X>::
|
||||
snap_non_basic_x_to_bound_and_free_to_zeroes() {
|
||||
for (unsigned j : non_basis()) {
|
||||
lean_assert(j < m_x.size());
|
||||
lp_assert(j < m_x.size());
|
||||
switch (m_column_types[j]) {
|
||||
case column_type::fixed:
|
||||
case column_type::boxed:
|
||||
|
@ -892,9 +893,9 @@ get_non_basic_column_value_position(unsigned j) const {
|
|||
case column_type::upper_bound:
|
||||
return x_is_at_upper_bound(j)? at_upper_bound : not_at_bound;
|
||||
default:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
}
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
return at_low_bound;
|
||||
}
|
||||
|
||||
|
@ -923,42 +924,55 @@ template <typename T, typename X> void lp_core_solver_base<T, X>::transpose_row
|
|||
transpose_basis(i, j);
|
||||
m_A.transpose_rows(i, j);
|
||||
}
|
||||
// j is the new basic column, j_basic - the leaving column
|
||||
template <typename T, typename X> bool lp_core_solver_base<T, X>::pivot_column_general(unsigned j, unsigned j_basic, indexed_vector<T> & w) {
|
||||
lp_assert(m_basis_heading[j] < 0);
|
||||
lp_assert(m_basis_heading[j_basic] >= 0);
|
||||
unsigned row_index = m_basis_heading[j_basic];
|
||||
if (m_settings.m_simplex_strategy == simplex_strategy_enum::lu) {
|
||||
if (m_factorization->need_to_refactor()) {
|
||||
init_lu();
|
||||
}
|
||||
else {
|
||||
m_factorization->prepare_entering(j, w); // to init vector w
|
||||
m_factorization->replace_column(zero_of_type<T>(), w, row_index);
|
||||
}
|
||||
if (m_factorization->get_status() != LU_status::OK) {
|
||||
init_lu();
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
change_basis(j, j_basic);
|
||||
}
|
||||
}
|
||||
else { // the tableau case
|
||||
if (pivot_column_tableau(j, row_index))
|
||||
change_basis(j, j_basic);
|
||||
else return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T, typename X> void lp_core_solver_base<T, X>::pivot_fixed_vars_from_basis() {
|
||||
// run over basis and non-basis at the same time
|
||||
indexed_vector<T> w(m_basis.size()); // the buffer
|
||||
unsigned i = 0; // points to basis
|
||||
unsigned j = 0; // points to nonbasis
|
||||
for (; i < m_basis.size() && j < m_nbasis.size(); i++) {
|
||||
unsigned ii = m_basis[i];
|
||||
unsigned jj;
|
||||
for (; i < m_basis.size(); i++) {
|
||||
unsigned basic_j = m_basis[i];
|
||||
|
||||
if (get_column_type(ii) != column_type::fixed) continue;
|
||||
while (j < m_nbasis.size()) {
|
||||
for (; j < m_nbasis.size(); j++) {
|
||||
jj = m_nbasis[j];
|
||||
if (get_column_type(jj) != column_type::fixed)
|
||||
if (get_column_type(basic_j) != column_type::fixed) continue;
|
||||
T a;
|
||||
unsigned j;
|
||||
auto * it = get_iterator_on_row(i);
|
||||
while (it->next(a, j)) {
|
||||
if (j == basic_j)
|
||||
continue;
|
||||
if (get_column_type(j) != column_type::fixed) {
|
||||
if (pivot_column_general(j, basic_j, w))
|
||||
break;
|
||||
}
|
||||
if (j >= m_nbasis.size())
|
||||
break;
|
||||
j++;
|
||||
if (m_factorization->need_to_refactor()) {
|
||||
change_basis(jj, ii);
|
||||
init_lu();
|
||||
} else {
|
||||
m_factorization->prepare_entering(jj, w); // to init vector w
|
||||
m_factorization->replace_column(zero_of_type<T>(), w, m_basis_heading[ii]);
|
||||
change_basis(jj, ii);
|
||||
}
|
||||
if (m_factorization->get_status() != LU_status::OK) {
|
||||
change_basis(ii, jj);
|
||||
init_lu();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
lean_assert(m_factorization->get_status()== LU_status::OK);
|
||||
delete it;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -966,7 +980,7 @@ template <typename T, typename X> bool
|
|||
lp_core_solver_base<T, X>::infeasibility_costs_are_correct() const {
|
||||
if (! this->m_using_infeas_costs)
|
||||
return true;
|
||||
lean_assert(costs_on_nbasis_are_zeros());
|
||||
lp_assert(costs_on_nbasis_are_zeros());
|
||||
for (unsigned j :this->m_basis) {
|
||||
if (!infeasibility_cost_is_correct_for_column(j)) {
|
||||
std::cout << "infeasibility_cost_is_correct_for_column does not hold\n";
|
||||
|
@ -1011,9 +1025,31 @@ lp_core_solver_base<T, X>::infeasibility_cost_is_correct_for_column(unsigned j)
|
|||
case column_type::free_column:
|
||||
return is_zero(this->m_costs[j]);
|
||||
default:
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename X>
|
||||
void lp_core_solver_base<T, X>::calculate_pivot_row(unsigned i) {
|
||||
lp_assert(!use_tableau());
|
||||
lp_assert(m_pivot_row.is_OK());
|
||||
m_pivot_row_of_B_1.clear();
|
||||
m_pivot_row_of_B_1.resize(m_m());
|
||||
m_pivot_row.clear();
|
||||
m_pivot_row.resize(m_n());
|
||||
if (m_settings.use_tableau()) {
|
||||
unsigned basis_j = m_basis[i];
|
||||
for (auto & c : m_A.m_rows[i]) {
|
||||
if (c.m_j != basis_j)
|
||||
m_pivot_row.set_value(c.get_val(), c.m_j);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
calculate_pivot_row_of_B_1(i);
|
||||
calculate_pivot_row_when_pivot_row_of_B1_is_ready(i);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -8,124 +8,125 @@
|
|||
#include "util/vector.h"
|
||||
#include <functional>
|
||||
#include "util/lp/lp_core_solver_base.hpp"
|
||||
template bool lean::lp_core_solver_base<double, double>::A_mult_x_is_off() const;
|
||||
template bool lean::lp_core_solver_base<double, double>::A_mult_x_is_off_on_index(const vector<unsigned> &) const;
|
||||
template bool lean::lp_core_solver_base<double, double>::basis_heading_is_correct() const;
|
||||
template void lean::lp_core_solver_base<double, double>::calculate_pivot_row_of_B_1(unsigned int);
|
||||
template void lean::lp_core_solver_base<double, double>::calculate_pivot_row_when_pivot_row_of_B1_is_ready(unsigned);
|
||||
template bool lean::lp_core_solver_base<double, double>::column_is_dual_feasible(unsigned int) const;
|
||||
template void lean::lp_core_solver_base<double, double>::fill_reduced_costs_from_m_y_by_rows();
|
||||
template bool lean::lp_core_solver_base<double, double>::find_x_by_solving();
|
||||
template lean::non_basic_column_value_position lean::lp_core_solver_base<double, double>::get_non_basic_column_value_position(unsigned int) const;
|
||||
template lean::non_basic_column_value_position lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::get_non_basic_column_value_position(unsigned int) const;
|
||||
template lean::non_basic_column_value_position lean::lp_core_solver_base<lean::mpq, lean::mpq>::get_non_basic_column_value_position(unsigned int) const;
|
||||
template void lean::lp_core_solver_base<double, double>::init_reduced_costs_for_one_iteration();
|
||||
template lean::lp_core_solver_base<double, double>::lp_core_solver_base(
|
||||
lean::static_matrix<double, double>&, vector<double>&,
|
||||
template bool lp::lp_core_solver_base<double, double>::A_mult_x_is_off() const;
|
||||
template bool lp::lp_core_solver_base<double, double>::A_mult_x_is_off_on_index(const vector<unsigned> &) const;
|
||||
template bool lp::lp_core_solver_base<double, double>::basis_heading_is_correct() const;
|
||||
template void lp::lp_core_solver_base<double, double>::calculate_pivot_row_of_B_1(unsigned int);
|
||||
template void lp::lp_core_solver_base<double, double>::calculate_pivot_row_when_pivot_row_of_B1_is_ready(unsigned);
|
||||
template bool lp::lp_core_solver_base<double, double>::column_is_dual_feasible(unsigned int) const;
|
||||
template void lp::lp_core_solver_base<double, double>::fill_reduced_costs_from_m_y_by_rows();
|
||||
template bool lp::lp_core_solver_base<double, double>::find_x_by_solving();
|
||||
template lp::non_basic_column_value_position lp::lp_core_solver_base<double, double>::get_non_basic_column_value_position(unsigned int) const;
|
||||
template lp::non_basic_column_value_position lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::get_non_basic_column_value_position(unsigned int) const;
|
||||
template lp::non_basic_column_value_position lp::lp_core_solver_base<lp::mpq, lp::mpq>::get_non_basic_column_value_position(unsigned int) const;
|
||||
template void lp::lp_core_solver_base<double, double>::init_reduced_costs_for_one_iteration();
|
||||
template lp::lp_core_solver_base<double, double>::lp_core_solver_base(
|
||||
lp::static_matrix<double, double>&, vector<double>&,
|
||||
vector<unsigned int >&,
|
||||
vector<unsigned> &, vector<int> &,
|
||||
vector<double >&,
|
||||
vector<double >&,
|
||||
lean::lp_settings&, const column_namer&, const vector<lean::column_type >&,
|
||||
lp::lp_settings&, const column_namer&, const vector<lp::column_type >&,
|
||||
const vector<double >&,
|
||||
const vector<double >&);
|
||||
|
||||
template bool lean::lp_core_solver_base<double, double>::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &);
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &);
|
||||
template void lean::lp_core_solver_base<double, double>::restore_x(unsigned int, double const&);
|
||||
template void lean::lp_core_solver_base<double, double>::set_non_basic_x_to_correct_bounds();
|
||||
template void lean::lp_core_solver_base<double, double>::snap_xN_to_bounds_and_free_columns_to_zeroes();
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::snap_xN_to_bounds_and_free_columns_to_zeroes();
|
||||
template void lean::lp_core_solver_base<double, double>::solve_Ax_eq_b();
|
||||
template void lean::lp_core_solver_base<double, double>::solve_Bd(unsigned int);
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq>>::solve_Bd(unsigned int, indexed_vector<lean::mpq>&);
|
||||
template void lean::lp_core_solver_base<double, double>::solve_yB(vector<double >&);
|
||||
template bool lean::lp_core_solver_base<double, double>::update_basis_and_x(int, int, double const&);
|
||||
template void lean::lp_core_solver_base<double, double>::update_x(unsigned int, const double&);
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::mpq>::A_mult_x_is_off() const;
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::mpq>::A_mult_x_is_off_on_index(const vector<unsigned> &) const;
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::mpq>::basis_heading_is_correct() const ;
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::mpq>::calculate_pivot_row_of_B_1(unsigned int);
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::mpq>::calculate_pivot_row_when_pivot_row_of_B1_is_ready(unsigned);
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::mpq>::column_is_dual_feasible(unsigned int) const;
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::mpq>::fill_reduced_costs_from_m_y_by_rows();
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::mpq>::find_x_by_solving();
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::mpq>::init_reduced_costs_for_one_iteration();
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::mpq>::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &);
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::mpq>::restore_x(unsigned int, lean::mpq const&);
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::mpq>::set_non_basic_x_to_correct_bounds();
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::mpq>::solve_Ax_eq_b();
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::mpq>::solve_Bd(unsigned int);
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::mpq>::solve_yB(vector<lean::mpq>&);
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::mpq>::update_basis_and_x(int, int, lean::mpq const&);
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::mpq>::update_x(unsigned int, const lean::mpq&);
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::calculate_pivot_row_of_B_1(unsigned int);
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::calculate_pivot_row_when_pivot_row_of_B1_is_ready(unsigned);
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::init();
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::init_basis_heading_and_non_basic_columns_vector();
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::init_reduced_costs_for_one_iteration();
|
||||
template lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::lp_core_solver_base(lean::static_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >&, vector<lean::numeric_pair<lean::mpq> >&, vector<unsigned int >&, vector<unsigned> &, vector<int> &, vector<lean::numeric_pair<lean::mpq> >&, vector<lean::mpq>&, lean::lp_settings&, const column_namer&, const vector<lean::column_type >&,
|
||||
const vector<lean::numeric_pair<lean::mpq> >&,
|
||||
const vector<lean::numeric_pair<lean::mpq> >&);
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::print_statistics_with_cost_and_check_that_the_time_is_over(lean::numeric_pair<lean::mpq>, std::ostream&);
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::snap_xN_to_bounds_and_fill_xB();
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::solve_Bd(unsigned int);
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::update_basis_and_x(int, int, lean::numeric_pair<lean::mpq> const&);
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::update_x(unsigned int, const lean::numeric_pair<lean::mpq>&);
|
||||
template lean::lp_core_solver_base<lean::mpq, lean::mpq>::lp_core_solver_base(
|
||||
lean::static_matrix<lean::mpq, lean::mpq>&,
|
||||
vector<lean::mpq>&,
|
||||
template bool lp::lp_core_solver_base<double, double>::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &);
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &);
|
||||
template void lp::lp_core_solver_base<double, double>::restore_x(unsigned int, double const&);
|
||||
template void lp::lp_core_solver_base<double, double>::set_non_basic_x_to_correct_bounds();
|
||||
template void lp::lp_core_solver_base<double, double>::snap_xN_to_bounds_and_free_columns_to_zeroes();
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::snap_xN_to_bounds_and_free_columns_to_zeroes();
|
||||
template void lp::lp_core_solver_base<double, double>::solve_Ax_eq_b();
|
||||
template void lp::lp_core_solver_base<double, double>::solve_Bd(unsigned int);
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq>>::solve_Bd(unsigned int, indexed_vector<lp::mpq>&);
|
||||
template void lp::lp_core_solver_base<double, double>::solve_yB(vector<double >&);
|
||||
template bool lp::lp_core_solver_base<double, double>::update_basis_and_x(int, int, double const&);
|
||||
template void lp::lp_core_solver_base<double, double>::update_x(unsigned int, const double&);
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::A_mult_x_is_off() const;
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::A_mult_x_is_off_on_index(const vector<unsigned> &) const;
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::basis_heading_is_correct() const ;
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::calculate_pivot_row_of_B_1(unsigned int);
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::calculate_pivot_row_when_pivot_row_of_B1_is_ready(unsigned);
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::column_is_dual_feasible(unsigned int) const;
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::fill_reduced_costs_from_m_y_by_rows();
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::find_x_by_solving();
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::init_reduced_costs_for_one_iteration();
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &);
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::restore_x(unsigned int, lp::mpq const&);
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::set_non_basic_x_to_correct_bounds();
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::solve_Ax_eq_b();
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::solve_Bd(unsigned int);
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::solve_yB(vector<lp::mpq>&);
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::update_basis_and_x(int, int, lp::mpq const&);
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::update_x(unsigned int, const lp::mpq&);
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::calculate_pivot_row_of_B_1(unsigned int);
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::calculate_pivot_row_when_pivot_row_of_B1_is_ready(unsigned);
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::init();
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::init_basis_heading_and_non_basic_columns_vector();
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::init_reduced_costs_for_one_iteration();
|
||||
template lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::lp_core_solver_base(lp::static_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >&, vector<lp::numeric_pair<lp::mpq> >&, vector<unsigned int >&, vector<unsigned> &, vector<int> &, vector<lp::numeric_pair<lp::mpq> >&, vector<lp::mpq>&, lp::lp_settings&, const column_namer&, const vector<lp::column_type >&,
|
||||
const vector<lp::numeric_pair<lp::mpq> >&,
|
||||
const vector<lp::numeric_pair<lp::mpq> >&);
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::print_statistics_with_cost_and_check_that_the_time_is_over(lp::numeric_pair<lp::mpq>, std::ostream&);
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::snap_xN_to_bounds_and_fill_xB();
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_Bd(unsigned int);
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::update_basis_and_x(int, int, lp::numeric_pair<lp::mpq> const&);
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::update_x(unsigned int, const lp::numeric_pair<lp::mpq>&);
|
||||
template lp::lp_core_solver_base<lp::mpq, lp::mpq>::lp_core_solver_base(
|
||||
lp::static_matrix<lp::mpq, lp::mpq>&,
|
||||
vector<lp::mpq>&,
|
||||
vector<unsigned int >&,
|
||||
vector<unsigned> &, vector<int> &,
|
||||
vector<lean::mpq>&,
|
||||
vector<lean::mpq>&,
|
||||
lean::lp_settings&,
|
||||
vector<lp::mpq>&,
|
||||
vector<lp::mpq>&,
|
||||
lp::lp_settings&,
|
||||
const column_namer&,
|
||||
const vector<lean::column_type >&,
|
||||
const vector<lean::mpq>&,
|
||||
const vector<lean::mpq>&);
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::print_statistics_with_iterations_and_check_that_the_time_is_over(std::ostream &);
|
||||
template std::string lean::lp_core_solver_base<double, double>::column_name(unsigned int) const;
|
||||
template void lean::lp_core_solver_base<double, double>::pretty_print(std::ostream & out);
|
||||
template void lean::lp_core_solver_base<double, double>::restore_state(double*, double*);
|
||||
template void lean::lp_core_solver_base<double, double>::save_state(double*, double*);
|
||||
template std::string lean::lp_core_solver_base<lean::mpq, lean::mpq>::column_name(unsigned int) const;
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::mpq>::pretty_print(std::ostream & out);
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::mpq>::restore_state(lean::mpq*, lean::mpq*);
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::mpq>::save_state(lean::mpq*, lean::mpq*);
|
||||
template std::string lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::column_name(unsigned int) const;
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::pretty_print(std::ostream & out);
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::restore_state(lean::mpq*, lean::mpq*);
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::save_state(lean::mpq*, lean::mpq*);
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::solve_yB(vector<lean::mpq>&);
|
||||
template void lean::lp_core_solver_base<double, double>::init_lu();
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::mpq>::init_lu();
|
||||
template int lean::lp_core_solver_base<double, double>::pivots_in_column_and_row_are_different(int, int) const;
|
||||
template int lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::pivots_in_column_and_row_are_different(int, int) const;
|
||||
template int lean::lp_core_solver_base<lean::mpq, lean::mpq>::pivots_in_column_and_row_are_different(int, int) const;
|
||||
template bool lean::lp_core_solver_base<double, double>::calc_current_x_is_feasible_include_non_basis(void)const;
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::mpq>::calc_current_x_is_feasible_include_non_basis(void)const;
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::calc_current_x_is_feasible_include_non_basis() const;
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::pivot_fixed_vars_from_basis();
|
||||
template bool lean::lp_core_solver_base<double, double>::column_is_feasible(unsigned int) const;
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::mpq>::column_is_feasible(unsigned int) const;
|
||||
// template void lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::print_linear_combination_of_column_indices(vector<std::pair<lean::mpq, unsigned int>, std::allocator<std::pair<lean::mpq, unsigned int> > > const&, std::ostream&) const;
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::column_is_feasible(unsigned int) const;
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::snap_non_basic_x_to_bound();
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::init_lu();
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::A_mult_x_is_off_on_index(vector<unsigned int> const&) const;
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::find_x_by_solving();
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::restore_x(unsigned int, lean::numeric_pair<lean::mpq> const&);
|
||||
template bool lean::lp_core_solver_base<double, double>::pivot_for_tableau_on_basis();
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::mpq>::pivot_for_tableau_on_basis();
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq>>::pivot_for_tableau_on_basis();
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq>>::pivot_column_tableau(unsigned int, unsigned int);
|
||||
template bool lean::lp_core_solver_base<double, double>::pivot_column_tableau(unsigned int, unsigned int);
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::mpq>::pivot_column_tableau(unsigned int, unsigned int);
|
||||
template void lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::transpose_rows_tableau(unsigned int, unsigned int);
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::inf_set_is_correct() const;
|
||||
template bool lean::lp_core_solver_base<double, double>::inf_set_is_correct() const;
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::mpq>::inf_set_is_correct() const;
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::numeric_pair<lean::mpq> >::infeasibility_costs_are_correct() const;
|
||||
template bool lean::lp_core_solver_base<lean::mpq, lean::mpq >::infeasibility_costs_are_correct() const;
|
||||
template bool lean::lp_core_solver_base<double, double >::infeasibility_costs_are_correct() const;
|
||||
const vector<lp::column_type >&,
|
||||
const vector<lp::mpq>&,
|
||||
const vector<lp::mpq>&);
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::print_statistics_with_iterations_and_check_that_the_time_is_over(std::ostream &);
|
||||
template std::string lp::lp_core_solver_base<double, double>::column_name(unsigned int) const;
|
||||
template void lp::lp_core_solver_base<double, double>::pretty_print(std::ostream & out);
|
||||
template void lp::lp_core_solver_base<double, double>::restore_state(double*, double*);
|
||||
template void lp::lp_core_solver_base<double, double>::save_state(double*, double*);
|
||||
template std::string lp::lp_core_solver_base<lp::mpq, lp::mpq>::column_name(unsigned int) const;
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::pretty_print(std::ostream & out);
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::restore_state(lp::mpq*, lp::mpq*);
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::save_state(lp::mpq*, lp::mpq*);
|
||||
template std::string lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::column_name(unsigned int) const;
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::pretty_print(std::ostream & out);
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::restore_state(lp::mpq*, lp::mpq*);
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::save_state(lp::mpq*, lp::mpq*);
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_yB(vector<lp::mpq>&);
|
||||
template void lp::lp_core_solver_base<double, double>::init_lu();
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::init_lu();
|
||||
template int lp::lp_core_solver_base<double, double>::pivots_in_column_and_row_are_different(int, int) const;
|
||||
template int lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::pivots_in_column_and_row_are_different(int, int) const;
|
||||
template int lp::lp_core_solver_base<lp::mpq, lp::mpq>::pivots_in_column_and_row_are_different(int, int) const;
|
||||
template bool lp::lp_core_solver_base<double, double>::calc_current_x_is_feasible_include_non_basis(void)const;
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::calc_current_x_is_feasible_include_non_basis(void)const;
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::calc_current_x_is_feasible_include_non_basis() const;
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::pivot_fixed_vars_from_basis();
|
||||
template bool lp::lp_core_solver_base<double, double>::column_is_feasible(unsigned int) const;
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::column_is_feasible(unsigned int) const;
|
||||
// template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::print_linear_combination_of_column_indices(vector<std::pair<lp::mpq, unsigned int>, std::allocator<std::pair<lp::mpq, unsigned int> > > const&, std::ostream&) const;
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::column_is_feasible(unsigned int) const;
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::snap_non_basic_x_to_bound();
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::init_lu();
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::A_mult_x_is_off_on_index(vector<unsigned int> const&) const;
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::find_x_by_solving();
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::restore_x(unsigned int, lp::numeric_pair<lp::mpq> const&);
|
||||
template bool lp::lp_core_solver_base<double, double>::pivot_for_tableau_on_basis();
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::pivot_for_tableau_on_basis();
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq>>::pivot_for_tableau_on_basis();
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq>>::pivot_column_tableau(unsigned int, unsigned int);
|
||||
template bool lp::lp_core_solver_base<double, double>::pivot_column_tableau(unsigned int, unsigned int);
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::pivot_column_tableau(unsigned int, unsigned int);
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::transpose_rows_tableau(unsigned int, unsigned int);
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::inf_set_is_correct() const;
|
||||
template bool lp::lp_core_solver_base<double, double>::inf_set_is_correct() const;
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::inf_set_is_correct() const;
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::infeasibility_costs_are_correct() const;
|
||||
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq >::infeasibility_costs_are_correct() const;
|
||||
template bool lp::lp_core_solver_base<double, double >::infeasibility_costs_are_correct() const;
|
||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::calculate_pivot_row(unsigned int);
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include <algorithm>
|
||||
#include "util/vector.h"
|
||||
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T, typename X>
|
||||
class lp_dual_core_solver:public lp_core_solver_base<T, X> {
|
||||
public:
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "util/vector.h"
|
||||
#include "util/lp/lp_dual_core_solver.h"
|
||||
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
|
||||
template <typename T, typename X> void lp_dual_core_solver<T, X>::init_a_wave_by_zeros() {
|
||||
unsigned j = this->m_m();
|
||||
|
@ -23,7 +23,7 @@ template <typename T, typename X> void lp_dual_core_solver<T, X>::restore_non_ba
|
|||
while (j--) {
|
||||
if (this->m_basis_heading[j] >= 0 ) continue;
|
||||
if (m_can_enter_basis[j]) {
|
||||
lean_assert(std::find(nb.begin(), nb.end(), j) == nb.end());
|
||||
lp_assert(std::find(nb.begin(), nb.end(), j) == nb.end());
|
||||
nb.push_back(j);
|
||||
this->m_basis_heading[j] = - static_cast<int>(nb.size());
|
||||
}
|
||||
|
@ -82,25 +82,25 @@ template <typename T, typename X> void lp_dual_core_solver<T, X>::start_with_ini
|
|||
}
|
||||
|
||||
template <typename T, typename X> bool lp_dual_core_solver<T, X>::done() {
|
||||
if (this->get_status() == OPTIMAL) {
|
||||
if (this->get_status() == lp_status::OPTIMAL) {
|
||||
return true;
|
||||
}
|
||||
if (this->total_iterations() > this->m_settings.max_total_number_of_iterations) { // debug !!!!
|
||||
this->set_status(ITERATIONS_EXHAUSTED);
|
||||
this->set_status(lp_status::ITERATIONS_EXHAUSTED);
|
||||
return true;
|
||||
}
|
||||
return false; // todo, need to be more cases
|
||||
}
|
||||
|
||||
template <typename T, typename X> T lp_dual_core_solver<T, X>::get_edge_steepness_for_low_bound(unsigned p) {
|
||||
lean_assert(this->m_basis_heading[p] >= 0 && static_cast<unsigned>(this->m_basis_heading[p]) < this->m_m());
|
||||
lp_assert(this->m_basis_heading[p] >= 0 && static_cast<unsigned>(this->m_basis_heading[p]) < this->m_m());
|
||||
T del = this->m_x[p] - this->m_low_bounds[p];
|
||||
del *= del;
|
||||
return del / this->m_betas[this->m_basis_heading[p]];
|
||||
}
|
||||
|
||||
template <typename T, typename X> T lp_dual_core_solver<T, X>::get_edge_steepness_for_upper_bound(unsigned p) {
|
||||
lean_assert(this->m_basis_heading[p] >= 0 && static_cast<unsigned>(this->m_basis_heading[p]) < this->m_m());
|
||||
lp_assert(this->m_basis_heading[p] >= 0 && static_cast<unsigned>(this->m_basis_heading[p]) < this->m_m());
|
||||
T del = this->m_x[p] - this->m_upper_bounds[p];
|
||||
del *= del;
|
||||
return del / this->m_betas[this->m_basis_heading[p]];
|
||||
|
@ -135,12 +135,12 @@ template <typename T, typename X> T lp_dual_core_solver<T, X>::pricing_for_row(u
|
|||
return numeric_traits<T>::zero();
|
||||
break;
|
||||
case column_type::free_column:
|
||||
lean_assert(numeric_traits<T>::is_zero(this->m_d[p]));
|
||||
lp_assert(numeric_traits<T>::is_zero(this->m_d[p]));
|
||||
return numeric_traits<T>::zero();
|
||||
default:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
}
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
return numeric_traits<T>::zero();
|
||||
}
|
||||
|
||||
|
@ -170,8 +170,8 @@ template <typename T, typename X> void lp_dual_core_solver<T, X>::pricing_loop(u
|
|||
}
|
||||
} while (i != initial_offset_in_rows && rows_left);
|
||||
if (m_r == -1) {
|
||||
if (this->get_status() != UNSTABLE) {
|
||||
this->set_status(OPTIMAL);
|
||||
if (this->get_status() != lp_status::UNSTABLE) {
|
||||
this->set_status(lp_status::OPTIMAL);
|
||||
}
|
||||
} else {
|
||||
m_p = this->m_basis[m_r];
|
||||
|
@ -181,10 +181,10 @@ template <typename T, typename X> void lp_dual_core_solver<T, X>::pricing_loop(u
|
|||
return;
|
||||
}
|
||||
// failure in advance_on_known_p
|
||||
if (this->get_status() == FLOATING_POINT_ERROR) {
|
||||
if (this->get_status() == lp_status::FLOATING_POINT_ERROR) {
|
||||
return;
|
||||
}
|
||||
this->set_status(UNSTABLE);
|
||||
this->set_status(lp_status::UNSTABLE);
|
||||
m_forbidden_rows.insert(m_r);
|
||||
}
|
||||
}
|
||||
|
@ -209,9 +209,9 @@ template <typename T, typename X> bool lp_dual_core_solver<T, X>::advance_on_kno
|
|||
int pivot_compare_result = this->pivots_in_column_and_row_are_different(m_q, m_p);
|
||||
if (!pivot_compare_result){;}
|
||||
else if (pivot_compare_result == 2) { // the sign is changed, cannot continue
|
||||
lean_unreachable(); // not implemented yet
|
||||
lp_unreachable(); // not implemented yet
|
||||
} else {
|
||||
lean_assert(pivot_compare_result == 1);
|
||||
lp_assert(pivot_compare_result == 1);
|
||||
this->init_lu();
|
||||
}
|
||||
DSE_FTran();
|
||||
|
@ -228,21 +228,21 @@ template <typename T, typename X> int lp_dual_core_solver<T, X>::define_sign_of_
|
|||
if (this->x_above_upper_bound(m_p)) {
|
||||
return 1;
|
||||
}
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
case column_type::low_bound:
|
||||
if (this->x_below_low_bound(m_p)) {
|
||||
return -1;
|
||||
}
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
case column_type::upper_bound:
|
||||
if (this->x_above_upper_bound(m_p)) {
|
||||
return 1;
|
||||
}
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
default:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
}
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -250,10 +250,10 @@ template <typename T, typename X> bool lp_dual_core_solver<T, X>::can_be_breakpo
|
|||
if (this->pivot_row_element_is_too_small_for_ratio_test(j)) return false;
|
||||
switch (this->m_column_types[j]) {
|
||||
case column_type::low_bound:
|
||||
lean_assert(this->m_settings.abs_val_is_smaller_than_harris_tolerance(this->m_x[j] - this->m_low_bounds[j]));
|
||||
lp_assert(this->m_settings.abs_val_is_smaller_than_harris_tolerance(this->m_x[j] - this->m_low_bounds[j]));
|
||||
return m_sign_of_alpha_r * this->m_pivot_row[j] > 0;
|
||||
case column_type::upper_bound:
|
||||
lean_assert(this->m_settings.abs_val_is_smaller_than_harris_tolerance(this->m_x[j] - this->m_upper_bounds[j]));
|
||||
lp_assert(this->m_settings.abs_val_is_smaller_than_harris_tolerance(this->m_x[j] - this->m_upper_bounds[j]));
|
||||
return m_sign_of_alpha_r * this->m_pivot_row[j] < 0;
|
||||
case column_type::boxed:
|
||||
{
|
||||
|
@ -292,23 +292,23 @@ template <typename T, typename X> T lp_dual_core_solver<T, X>::get_delta() {
|
|||
if (this->x_above_upper_bound(m_p)) {
|
||||
return this->m_x[m_p] - this->m_upper_bounds[m_p];
|
||||
}
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
case column_type::low_bound:
|
||||
if (this->x_below_low_bound(m_p)) {
|
||||
return this->m_x[m_p] - this->m_low_bounds[m_p];
|
||||
}
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
case column_type::upper_bound:
|
||||
if (this->x_above_upper_bound(m_p)) {
|
||||
return get_edge_steepness_for_upper_bound(m_p);
|
||||
}
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
case column_type::fixed:
|
||||
return this->m_x[m_p] - this->m_upper_bounds[m_p];
|
||||
default:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
}
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
return zero_of_type<T>();
|
||||
}
|
||||
|
||||
|
@ -355,7 +355,7 @@ template <typename T, typename X> void lp_dual_core_solver<T, X>::update_betas()
|
|||
|
||||
template <typename T, typename X> void lp_dual_core_solver<T, X>::apply_flips() {
|
||||
for (unsigned j : m_flipped_boxed) {
|
||||
lean_assert(this->x_is_at_bound(j));
|
||||
lp_assert(this->x_is_at_bound(j));
|
||||
if (this->x_is_at_low_bound(j)) {
|
||||
this->m_x[j] = this->m_upper_bounds[j];
|
||||
} else {
|
||||
|
@ -385,7 +385,7 @@ template <typename T, typename X> void lp_dual_core_solver<T, X>::snap_xN_column
|
|||
case column_type::free_column:
|
||||
break;
|
||||
default:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -441,7 +441,7 @@ template <typename T, typename X> bool lp_dual_core_solver<T, X>::basis_change_a
|
|||
return false;
|
||||
}
|
||||
|
||||
lean_assert(d_is_correct());
|
||||
lp_assert(d_is_correct());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -457,7 +457,7 @@ template <typename T, typename X> void lp_dual_core_solver<T, X>::recover_leavin
|
|||
case free_of_bounds:
|
||||
this->m_x[m_q] = zero_of_type<X>();
|
||||
default:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -466,12 +466,12 @@ template <typename T, typename X> void lp_dual_core_solver<T, X>::revert_to_prev
|
|||
this->change_basis_unconditionally(m_p, m_q);
|
||||
init_factorization(this->m_factorization, this->m_A, this->m_basis, this->m_settings);
|
||||
if (this->m_factorization->get_status() != LU_status::OK) {
|
||||
this->set_status(FLOATING_POINT_ERROR); // complete failure
|
||||
this->set_status(lp_status::FLOATING_POINT_ERROR); // complete failure
|
||||
return;
|
||||
}
|
||||
recover_leaving();
|
||||
if (!this->find_x_by_solving()) {
|
||||
this->set_status(FLOATING_POINT_ERROR);
|
||||
this->set_status(lp_status::FLOATING_POINT_ERROR);
|
||||
return;
|
||||
}
|
||||
recalculate_xB_and_d();
|
||||
|
@ -551,10 +551,10 @@ template <typename T, typename X> bool lp_dual_core_solver<T, X>::delta_keeps_th
|
|||
}
|
||||
|
||||
template <typename T, typename X> void lp_dual_core_solver<T, X>::set_status_to_tentative_dual_unbounded_or_dual_unbounded() {
|
||||
if (this->get_status() == TENTATIVE_DUAL_UNBOUNDED) {
|
||||
this->set_status(DUAL_UNBOUNDED);
|
||||
if (this->get_status() == lp_status::TENTATIVE_DUAL_UNBOUNDED) {
|
||||
this->set_status(lp_status::DUAL_UNBOUNDED);
|
||||
} else {
|
||||
this->set_status(TENTATIVE_DUAL_UNBOUNDED);
|
||||
this->set_status(lp_status::TENTATIVE_DUAL_UNBOUNDED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -584,7 +584,7 @@ template <typename T, typename X> bool lp_dual_core_solver<T, X>::tight_breakpoi
|
|||
template <typename T, typename X> T lp_dual_core_solver<T, X>::calculate_harris_delta_on_breakpoint_set() {
|
||||
bool first_time = true;
|
||||
T ret = zero_of_type<T>();
|
||||
lean_assert(m_breakpoint_set.size() > 0);
|
||||
lp_assert(m_breakpoint_set.size() > 0);
|
||||
for (auto j : m_breakpoint_set) {
|
||||
T t;
|
||||
if (this->x_is_at_low_bound(j)) {
|
||||
|
@ -633,7 +633,7 @@ template <typename T, typename X> void lp_dual_core_solver<T, X>::find_q_on_tigh
|
|||
}
|
||||
}
|
||||
m_tight_set.erase(m_q);
|
||||
lean_assert(m_q != -1);
|
||||
lp_assert(m_q != -1);
|
||||
}
|
||||
|
||||
template <typename T, typename X> void lp_dual_core_solver<T, X>::find_q_and_tight_set() {
|
||||
|
@ -660,7 +660,7 @@ template <typename T, typename X> bool lp_dual_core_solver<T, X>::ratio_test() {
|
|||
set_status_to_tentative_dual_unbounded_or_dual_unbounded();
|
||||
return false;
|
||||
}
|
||||
this->set_status(FEASIBLE);
|
||||
this->set_status(lp_status::FEASIBLE);
|
||||
find_q_and_tight_set();
|
||||
if (!tight_breakpoinst_are_all_boxed()) break;
|
||||
T del = m_delta - delta_lost_on_flips_of_tight_breakpoints() * initial_delta_sign;
|
||||
|
@ -716,19 +716,19 @@ template <typename T, typename X> void lp_dual_core_solver<T, X>::update_xb_afte
|
|||
template <typename T, typename X> void lp_dual_core_solver<T, X>::one_iteration() {
|
||||
unsigned number_of_rows_to_try = get_number_of_rows_to_try_for_leaving();
|
||||
unsigned offset_in_rows = this->m_settings.random_next() % this->m_m();
|
||||
if (this->get_status() == TENTATIVE_DUAL_UNBOUNDED) {
|
||||
if (this->get_status() == lp_status::TENTATIVE_DUAL_UNBOUNDED) {
|
||||
number_of_rows_to_try = this->m_m();
|
||||
} else {
|
||||
this->set_status(FEASIBLE);
|
||||
this->set_status(lp_status::FEASIBLE);
|
||||
}
|
||||
pricing_loop(number_of_rows_to_try, offset_in_rows);
|
||||
lean_assert(problem_is_dual_feasible());
|
||||
lp_assert(problem_is_dual_feasible());
|
||||
}
|
||||
|
||||
template <typename T, typename X> void lp_dual_core_solver<T, X>::solve() { // see the page 35
|
||||
lean_assert(d_is_correct());
|
||||
lean_assert(problem_is_dual_feasible());
|
||||
lean_assert(this->basis_heading_is_correct());
|
||||
lp_assert(d_is_correct());
|
||||
lp_assert(problem_is_dual_feasible());
|
||||
lp_assert(this->basis_heading_is_correct());
|
||||
this->set_total_iterations(0);
|
||||
this->iters_with_no_cost_growing() = 0;
|
||||
do {
|
||||
|
@ -736,7 +736,7 @@ template <typename T, typename X> void lp_dual_core_solver<T, X>::solve() { // s
|
|||
return;
|
||||
}
|
||||
one_iteration();
|
||||
} while (this->get_status() != FLOATING_POINT_ERROR && this->get_status() != DUAL_UNBOUNDED && this->get_status() != OPTIMAL &&
|
||||
} while (this->get_status() != lp_status::FLOATING_POINT_ERROR && this->get_status() != lp_status::DUAL_UNBOUNDED && this->get_status() != lp_status::OPTIMAL &&
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -8,22 +8,22 @@
|
|||
#include "util/vector.h"
|
||||
#include <functional>
|
||||
#include "util/lp/lp_dual_core_solver.hpp"
|
||||
template void lean::lp_dual_core_solver<lean::mpq, lean::mpq>::start_with_initial_basis_and_make_it_dual_feasible();
|
||||
template void lean::lp_dual_core_solver<lean::mpq, lean::mpq>::solve();
|
||||
template lean::lp_dual_core_solver<double, double>::lp_dual_core_solver(lean::static_matrix<double, double>&, vector<bool>&,
|
||||
template void lp::lp_dual_core_solver<lp::mpq, lp::mpq>::start_with_initial_basis_and_make_it_dual_feasible();
|
||||
template void lp::lp_dual_core_solver<lp::mpq, lp::mpq>::solve();
|
||||
template lp::lp_dual_core_solver<double, double>::lp_dual_core_solver(lp::static_matrix<double, double>&, vector<bool>&,
|
||||
vector<double>&,
|
||||
vector<double>&,
|
||||
vector<unsigned int>&,
|
||||
vector<unsigned> &,
|
||||
vector<int> &,
|
||||
vector<double>&,
|
||||
vector<lean::column_type>&,
|
||||
vector<lp::column_type>&,
|
||||
vector<double>&,
|
||||
vector<double>&,
|
||||
lean::lp_settings&, const lean::column_namer&);
|
||||
template void lean::lp_dual_core_solver<double, double>::start_with_initial_basis_and_make_it_dual_feasible();
|
||||
template void lean::lp_dual_core_solver<double, double>::solve();
|
||||
template void lean::lp_dual_core_solver<lean::mpq, lean::mpq>::restore_non_basis();
|
||||
template void lean::lp_dual_core_solver<double, double>::restore_non_basis();
|
||||
template void lean::lp_dual_core_solver<double, double>::revert_to_previous_basis();
|
||||
template void lean::lp_dual_core_solver<lean::mpq, lean::mpq>::revert_to_previous_basis();
|
||||
lp::lp_settings&, const lp::column_namer&);
|
||||
template void lp::lp_dual_core_solver<double, double>::start_with_initial_basis_and_make_it_dual_feasible();
|
||||
template void lp::lp_dual_core_solver<double, double>::solve();
|
||||
template void lp::lp_dual_core_solver<lp::mpq, lp::mpq>::restore_non_basis();
|
||||
template void lp::lp_dual_core_solver<double, double>::restore_non_basis();
|
||||
template void lp::lp_dual_core_solver<double, double>::revert_to_previous_basis();
|
||||
template void lp::lp_dual_core_solver<lp::mpq, lp::mpq>::revert_to_previous_basis();
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "util/lp/lp_utils.h"
|
||||
#include "util/lp/lp_solver.h"
|
||||
#include "util/lp/lp_dual_core_solver.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
|
||||
template <typename T, typename X>
|
||||
class lp_dual_simplex: public lp_solver<T, X> {
|
||||
|
|
|
@ -3,35 +3,35 @@
|
|||
Author: Lev Nachmanson
|
||||
*/
|
||||
#include "util/lp/lp_dual_simplex.h"
|
||||
namespace lean{
|
||||
namespace lp{
|
||||
|
||||
template <typename T, typename X> void lp_dual_simplex<T, X>::decide_on_status_after_stage1() {
|
||||
switch (m_core_solver->get_status()) {
|
||||
case OPTIMAL:
|
||||
case lp_status::OPTIMAL:
|
||||
if (this->m_settings.abs_val_is_smaller_than_artificial_tolerance(m_core_solver->get_cost())) {
|
||||
this->m_status = FEASIBLE;
|
||||
this->m_status = lp_status::FEASIBLE;
|
||||
} else {
|
||||
this->m_status = UNBOUNDED;
|
||||
this->m_status = lp_status::UNBOUNDED;
|
||||
}
|
||||
break;
|
||||
case DUAL_UNBOUNDED:
|
||||
lean_unreachable();
|
||||
case ITERATIONS_EXHAUSTED:
|
||||
this->m_status = ITERATIONS_EXHAUSTED;
|
||||
case lp_status::DUAL_UNBOUNDED:
|
||||
lp_unreachable();
|
||||
case lp_status::ITERATIONS_EXHAUSTED:
|
||||
this->m_status = lp_status::ITERATIONS_EXHAUSTED;
|
||||
break;
|
||||
case TIME_EXHAUSTED:
|
||||
this->m_status = TIME_EXHAUSTED;
|
||||
case lp_status::TIME_EXHAUSTED:
|
||||
this->m_status = lp_status::TIME_EXHAUSTED;
|
||||
break;
|
||||
case FLOATING_POINT_ERROR:
|
||||
this->m_status = FLOATING_POINT_ERROR;
|
||||
case lp_status::FLOATING_POINT_ERROR:
|
||||
this->m_status = lp_status::FLOATING_POINT_ERROR;
|
||||
break;
|
||||
default:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename X> void lp_dual_simplex<T, X>::fix_logical_for_stage2(unsigned j) {
|
||||
lean_assert(j >= this->number_of_core_structurals());
|
||||
lp_assert(j >= this->number_of_core_structurals());
|
||||
switch (m_column_types_of_logicals[j - this->number_of_core_structurals()]) {
|
||||
case column_type::low_bound:
|
||||
m_low_bounds[j] = numeric_traits<T>::zero();
|
||||
|
@ -44,7 +44,7 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::fix_logical_for_st
|
|||
m_can_enter_basis[j] = false;
|
||||
break;
|
||||
default:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::fix_structural_for
|
|||
break;
|
||||
case column_type::fixed:
|
||||
case column_type::upper_bound:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
case column_type::boxed:
|
||||
this->m_upper_bounds[j] = ci->get_adjusted_upper_bound() / this->m_column_scale[j];
|
||||
m_low_bounds[j] = numeric_traits<T>::zero();
|
||||
|
@ -70,7 +70,7 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::fix_structural_for
|
|||
m_column_types_of_core_solver[j] = column_type::free_column;
|
||||
break;
|
||||
default:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
}
|
||||
// T cost_was = this->m_costs[j];
|
||||
this->set_scaled_cost(j);
|
||||
|
@ -99,23 +99,23 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::solve_for_stage2()
|
|||
m_core_solver->solve_yB(m_core_solver->m_y);
|
||||
m_core_solver->fill_reduced_costs_from_m_y_by_rows();
|
||||
m_core_solver->start_with_initial_basis_and_make_it_dual_feasible();
|
||||
m_core_solver->set_status(FEASIBLE);
|
||||
m_core_solver->set_status(lp_status::FEASIBLE);
|
||||
m_core_solver->solve();
|
||||
switch (m_core_solver->get_status()) {
|
||||
case OPTIMAL:
|
||||
this->m_status = OPTIMAL;
|
||||
case lp_status::OPTIMAL:
|
||||
this->m_status = lp_status::OPTIMAL;
|
||||
break;
|
||||
case DUAL_UNBOUNDED:
|
||||
this->m_status = INFEASIBLE;
|
||||
case lp_status::DUAL_UNBOUNDED:
|
||||
this->m_status = lp_status::INFEASIBLE;
|
||||
break;
|
||||
case TIME_EXHAUSTED:
|
||||
this->m_status = TIME_EXHAUSTED;
|
||||
case lp_status::TIME_EXHAUSTED:
|
||||
this->m_status = lp_status::TIME_EXHAUSTED;
|
||||
break;
|
||||
case FLOATING_POINT_ERROR:
|
||||
this->m_status = FLOATING_POINT_ERROR;
|
||||
case lp_status::FLOATING_POINT_ERROR:
|
||||
this->m_status = lp_status::FLOATING_POINT_ERROR;
|
||||
break;
|
||||
default:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
}
|
||||
this->m_second_stage_iterations = m_core_solver->total_iterations();
|
||||
this->m_total_iterations = (this->m_first_stage_iterations + this->m_second_stage_iterations);
|
||||
|
@ -129,7 +129,7 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::fill_x_with_zeros(
|
|||
}
|
||||
|
||||
template <typename T, typename X> void lp_dual_simplex<T, X>::stage1() {
|
||||
lean_assert(m_core_solver == nullptr);
|
||||
lp_assert(m_core_solver == nullptr);
|
||||
this->m_x.resize(this->m_A->column_count(), numeric_traits<T>::zero());
|
||||
if (this->m_settings.get_message_ostream() != nullptr)
|
||||
this->print_statistics_on_A(*this->m_settings.get_message_ostream());
|
||||
|
@ -151,7 +151,7 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::stage1() {
|
|||
m_core_solver->start_with_initial_basis_and_make_it_dual_feasible();
|
||||
if (this->m_settings.abs_val_is_smaller_than_artificial_tolerance(m_core_solver->get_cost())) {
|
||||
// skipping stage 1
|
||||
m_core_solver->set_status(OPTIMAL);
|
||||
m_core_solver->set_status(lp_status::OPTIMAL);
|
||||
m_core_solver->set_total_iterations(0);
|
||||
} else {
|
||||
m_core_solver->solve();
|
||||
|
@ -177,7 +177,7 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::fill_first_stage_s
|
|||
}
|
||||
|
||||
template <typename T, typename X> column_type lp_dual_simplex<T, X>::get_column_type(unsigned j) {
|
||||
lean_assert(j < this->m_A->column_count());
|
||||
lp_assert(j < this->m_A->column_count());
|
||||
if (j >= this->number_of_core_structurals()) {
|
||||
return m_column_types_of_logicals[j - this->number_of_core_structurals()];
|
||||
}
|
||||
|
@ -186,12 +186,12 @@ template <typename T, typename X> column_type lp_dual_simplex<T, X>::get_column_
|
|||
|
||||
template <typename T, typename X> void lp_dual_simplex<T, X>::fill_costs_bounds_types_and_can_enter_basis_for_the_first_stage_solver_structural_column(unsigned j) {
|
||||
// see 4.7 in the dissertation of Achim Koberstein
|
||||
lean_assert(this->m_core_solver_columns_to_external_columns.find(j) !=
|
||||
lp_assert(this->m_core_solver_columns_to_external_columns.find(j) !=
|
||||
this->m_core_solver_columns_to_external_columns.end());
|
||||
|
||||
T free_bound = T(1e4); // see 4.8
|
||||
unsigned jj = this->m_core_solver_columns_to_external_columns[j];
|
||||
lean_assert(this->m_map_from_var_index_to_column_info.find(jj) != this->m_map_from_var_index_to_column_info.end());
|
||||
lp_assert(this->m_map_from_var_index_to_column_info.find(jj) != this->m_map_from_var_index_to_column_info.end());
|
||||
column_info<T> * ci = this->m_map_from_var_index_to_column_info[jj];
|
||||
switch (ci->get_column_type()) {
|
||||
case column_type::upper_bound: {
|
||||
|
@ -221,14 +221,14 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::fill_costs_bounds_
|
|||
this->m_upper_bounds[j] = this->m_low_bounds[j] = numeric_traits<T>::zero(); // is it needed?
|
||||
break;
|
||||
default:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
}
|
||||
m_column_types_of_core_solver[j] = column_type::boxed;
|
||||
}
|
||||
|
||||
template <typename T, typename X> void lp_dual_simplex<T, X>::fill_costs_bounds_types_and_can_enter_basis_for_the_first_stage_solver_logical_column(unsigned j) {
|
||||
this->m_costs[j] = 0;
|
||||
lean_assert(get_column_type(j) != column_type::upper_bound);
|
||||
lp_assert(get_column_type(j) != column_type::upper_bound);
|
||||
if ((m_can_enter_basis[j] = (get_column_type(j) == column_type::low_bound))) {
|
||||
m_column_types_of_core_solver[j] = column_type::boxed;
|
||||
this->m_low_bounds[j] = numeric_traits<T>::zero();
|
||||
|
@ -254,7 +254,7 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::fill_costs_and_bou
|
|||
template <typename T, typename X> void lp_dual_simplex<T, X>::fill_first_stage_solver_fields_for_row_slack_and_artificial(unsigned row,
|
||||
unsigned & slack_var,
|
||||
unsigned & artificial) {
|
||||
lean_assert(row < this->row_count());
|
||||
lp_assert(row < this->row_count());
|
||||
auto & constraint = this->m_constraints[this->m_core_solver_rows_to_external_rows[row]];
|
||||
// we need to bring the program to the form Ax = b
|
||||
T rs = this->m_b[row];
|
||||
|
@ -336,7 +336,7 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::find_maximal_solut
|
|||
this->flip_costs(); // do it for now, todo ( remove the flipping)
|
||||
|
||||
this->cleanup();
|
||||
if (this->m_status == INFEASIBLE) {
|
||||
if (this->m_status == lp_status::INFEASIBLE) {
|
||||
return;
|
||||
}
|
||||
this->fill_matrix_A_and_init_right_side();
|
||||
|
@ -346,7 +346,7 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::find_maximal_solut
|
|||
fill_first_stage_solver_fields();
|
||||
copy_m_b_aside_and_set_it_to_zeros();
|
||||
stage1();
|
||||
if (this->m_status == FEASIBLE) {
|
||||
if (this->m_status == lp_status::FEASIBLE) {
|
||||
stage2();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
Author: Lev Nachmanson
|
||||
*/
|
||||
#include "util/lp/lp_dual_simplex.hpp"
|
||||
template lean::mpq lean::lp_dual_simplex<lean::mpq, lean::mpq>::get_current_cost() const;
|
||||
template void lean::lp_dual_simplex<lean::mpq, lean::mpq>::find_maximal_solution();
|
||||
template double lean::lp_dual_simplex<double, double>::get_current_cost() const;
|
||||
template void lean::lp_dual_simplex<double, double>::find_maximal_solution();
|
||||
template lp::mpq lp::lp_dual_simplex<lp::mpq, lp::mpq>::get_current_cost() const;
|
||||
template void lp::lp_dual_simplex<lp::mpq, lp::mpq>::find_maximal_solution();
|
||||
template double lp::lp_dual_simplex<double, double>::get_current_cost() const;
|
||||
template void lp::lp_dual_simplex<double, double>::find_maximal_solution();
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "util/lp/binary_heap_priority_queue.h"
|
||||
#include "util/lp/int_set.h"
|
||||
#include "util/lp/iterator_on_row.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
|
||||
// This core solver solves (Ax=b, low_bound_values \leq x \leq upper_bound_values, maximize costs*x )
|
||||
// The right side b is given implicitly by x and the basis
|
||||
|
@ -70,7 +70,7 @@ public:
|
|||
// unsigned len = 100000000;
|
||||
// for (unsigned j : this->m_inf_set.m_index) {
|
||||
// int i = this->m_basis_heading[j];
|
||||
// lean_assert(i >= 0);
|
||||
// lp_assert(i >= 0);
|
||||
// unsigned row_len = this->m_A.m_rows[i].size();
|
||||
// if (row_len < len) {
|
||||
// choices.clear();
|
||||
|
@ -98,8 +98,8 @@ public:
|
|||
bool column_is_benefitial_for_entering_basis_on_sign_row_strategy(unsigned j, int sign) const {
|
||||
// sign = 1 means the x of the basis column of the row has to grow to become feasible, when the coeff before j is neg, or x - has to diminish when the coeff is pos
|
||||
// we have xbj = -aj * xj
|
||||
lean_assert(this->m_basis_heading[j] < 0);
|
||||
lean_assert(this->column_is_feasible(j));
|
||||
lp_assert(this->m_basis_heading[j] < 0);
|
||||
lp_assert(this->column_is_feasible(j));
|
||||
switch (this->m_column_types[j]) {
|
||||
case column_type::free_column: return true;
|
||||
case column_type::fixed: return false;
|
||||
|
@ -117,13 +117,13 @@ public:
|
|||
return !this->x_is_at_upper_bound(j);
|
||||
}
|
||||
|
||||
lean_assert(false); // cannot be here
|
||||
lp_assert(false); // cannot be here
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool needs_to_grow(unsigned bj) const {
|
||||
lean_assert(!this->column_is_feasible(bj));
|
||||
lp_assert(!this->column_is_feasible(bj));
|
||||
switch(this->m_column_types[bj]) {
|
||||
case column_type::free_column:
|
||||
return false;
|
||||
|
@ -134,12 +134,12 @@ public:
|
|||
default:
|
||||
return false;
|
||||
}
|
||||
lean_assert(false); // unreachable
|
||||
lp_assert(false); // unreachable
|
||||
return false;
|
||||
}
|
||||
|
||||
int inf_sign_of_column(unsigned bj) const {
|
||||
lean_assert(!this->column_is_feasible(bj));
|
||||
lp_assert(!this->column_is_feasible(bj));
|
||||
switch(this->m_column_types[bj]) {
|
||||
case column_type::free_column:
|
||||
return 0;
|
||||
|
@ -151,7 +151,7 @@ public:
|
|||
default:
|
||||
return -1;
|
||||
}
|
||||
lean_assert(false); // unreachable
|
||||
lp_assert(false); // unreachable
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ public:
|
|||
|
||||
bool monoid_can_decrease(const row_cell<T> & rc) const {
|
||||
unsigned j = rc.m_j;
|
||||
lean_assert(this->column_is_feasible(j));
|
||||
lp_assert(this->column_is_feasible(j));
|
||||
switch (this->m_column_types[j]) {
|
||||
case column_type::free_column:
|
||||
return true;
|
||||
|
@ -186,13 +186,13 @@ public:
|
|||
default:
|
||||
return false;
|
||||
}
|
||||
lean_assert(false); // unreachable
|
||||
lp_assert(false); // unreachable
|
||||
return false;
|
||||
}
|
||||
|
||||
bool monoid_can_increase(const row_cell<T> & rc) const {
|
||||
unsigned j = rc.m_j;
|
||||
lean_assert(this->column_is_feasible(j));
|
||||
lp_assert(this->column_is_feasible(j));
|
||||
switch (this->m_column_types[j]) {
|
||||
case column_type::free_column:
|
||||
return true;
|
||||
|
@ -219,7 +219,7 @@ public:
|
|||
default:
|
||||
return false;
|
||||
}
|
||||
lean_assert(false); // unreachable
|
||||
lp_assert(false); // unreachable
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -329,24 +329,24 @@ public:
|
|||
}
|
||||
|
||||
void limit_theta_on_basis_column_for_inf_case_m_neg_upper_bound(unsigned j, const T & m, X & theta, bool & unlimited) {
|
||||
lean_assert(m < 0 && this->m_column_types[j] == column_type::upper_bound);
|
||||
lp_assert(m < 0 && this->m_column_types[j] == column_type::upper_bound);
|
||||
limit_inf_on_upper_bound_m_neg(m, this->m_x[j], this->m_upper_bounds[j], theta, unlimited);
|
||||
}
|
||||
|
||||
|
||||
void limit_theta_on_basis_column_for_inf_case_m_neg_low_bound(unsigned j, const T & m, X & theta, bool & unlimited) {
|
||||
lean_assert(m < 0 && this->m_column_types[j] == column_type::low_bound);
|
||||
lp_assert(m < 0 && this->m_column_types[j] == column_type::low_bound);
|
||||
limit_inf_on_bound_m_neg(m, this->m_x[j], this->m_low_bounds[j], theta, unlimited);
|
||||
}
|
||||
|
||||
|
||||
void limit_theta_on_basis_column_for_inf_case_m_pos_low_bound(unsigned j, const T & m, X & theta, bool & unlimited) {
|
||||
lean_assert(m > 0 && this->m_column_types[j] == column_type::low_bound);
|
||||
lp_assert(m > 0 && this->m_column_types[j] == column_type::low_bound);
|
||||
limit_inf_on_low_bound_m_pos(m, this->m_x[j], this->m_low_bounds[j], theta, unlimited);
|
||||
}
|
||||
|
||||
void limit_theta_on_basis_column_for_inf_case_m_pos_upper_bound(unsigned j, const T & m, X & theta, bool & unlimited) {
|
||||
lean_assert(m > 0 && this->m_column_types[j] == column_type::upper_bound);
|
||||
lp_assert(m > 0 && this->m_column_types[j] == column_type::upper_bound);
|
||||
limit_inf_on_bound_m_pos(m, this->m_x[j], this->m_upper_bounds[j], theta, unlimited);
|
||||
};
|
||||
|
||||
|
@ -388,7 +388,7 @@ public:
|
|||
bool need_to_switch_costs() const {
|
||||
if (this->m_settings.simplex_strategy() == simplex_strategy_enum::tableau_rows)
|
||||
return false;
|
||||
// lean_assert(calc_current_x_is_feasible() == current_x_is_feasible());
|
||||
// lp_assert(calc_current_x_is_feasible() == current_x_is_feasible());
|
||||
return this->current_x_is_feasible() == this->m_using_infeas_costs;
|
||||
}
|
||||
|
||||
|
@ -443,7 +443,7 @@ public:
|
|||
if (j == -1)
|
||||
return -1;
|
||||
|
||||
lean_assert(!this->column_is_feasible(j));
|
||||
lp_assert(!this->column_is_feasible(j));
|
||||
switch (this->m_column_types[j]) {
|
||||
case column_type::fixed:
|
||||
case column_type::upper_bound:
|
||||
|
@ -459,7 +459,8 @@ public:
|
|||
new_val_for_leaving = this->m_low_bounds[j];
|
||||
break;
|
||||
default:
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
new_val_for_leaving = numeric_traits<T>::zero(); // does not matter
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
@ -468,7 +469,7 @@ public:
|
|||
X new_val_for_leaving;
|
||||
int leaving = find_leaving_tableau_rows(new_val_for_leaving);
|
||||
if (leaving == -1) {
|
||||
this->set_status(OPTIMAL);
|
||||
this->set_status(lp_status::OPTIMAL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -484,14 +485,14 @@ public:
|
|||
T a_ent;
|
||||
int entering = find_beneficial_column_in_row_tableau_rows(this->m_basis_heading[leaving], a_ent);
|
||||
if (entering == -1) {
|
||||
this->set_status(INFEASIBLE);
|
||||
this->set_status(lp_status::INFEASIBLE);
|
||||
return;
|
||||
}
|
||||
X theta = (this->m_x[leaving] - new_val_for_leaving) / a_ent;
|
||||
advance_on_entering_and_leaving_tableau_rows(entering, leaving, theta );
|
||||
lean_assert(this->m_x[leaving] == new_val_for_leaving);
|
||||
lp_assert(this->m_x[leaving] == new_val_for_leaving);
|
||||
if (this->current_x_is_feasible())
|
||||
this->set_status(OPTIMAL);
|
||||
this->set_status(lp_status::OPTIMAL);
|
||||
}
|
||||
|
||||
void fill_breakpoints_array(unsigned entering);
|
||||
|
@ -506,13 +507,13 @@ public:
|
|||
void update_basis_and_x_with_comparison(unsigned entering, unsigned leaving, X delta);
|
||||
|
||||
void decide_on_status_when_cannot_find_entering() {
|
||||
lean_assert(!need_to_switch_costs());
|
||||
this->set_status(this->current_x_is_feasible()? OPTIMAL: INFEASIBLE);
|
||||
lp_assert(!need_to_switch_costs());
|
||||
this->set_status(this->current_x_is_feasible()? lp_status::OPTIMAL: lp_status::INFEASIBLE);
|
||||
}
|
||||
|
||||
// void limit_theta_on_basis_column_for_feas_case_m_neg(unsigned j, const T & m, X & theta) {
|
||||
// lean_assert(m < 0);
|
||||
// lean_assert(this->m_column_type[j] == low_bound || this->m_column_type[j] == boxed);
|
||||
// lp_assert(m < 0);
|
||||
// lp_assert(this->m_column_type[j] == low_bound || this->m_column_type[j] == boxed);
|
||||
// const X & eps = harris_eps_for_bound(this->m_low_bounds[j]);
|
||||
// if (this->above_bound(this->m_x[j], this->m_low_bounds[j])) {
|
||||
// theta = std::min((this->m_low_bounds[j] -this->m_x[j] - eps) / m, theta);
|
||||
|
@ -521,7 +522,7 @@ public:
|
|||
// }
|
||||
|
||||
void limit_theta_on_basis_column_for_feas_case_m_neg_no_check(unsigned j, const T & m, X & theta, bool & unlimited) {
|
||||
lean_assert(m < 0);
|
||||
lp_assert(m < 0);
|
||||
const X& eps = harris_eps_for_bound(this->m_low_bounds[j]);
|
||||
limit_theta((this->m_low_bounds[j] - this->m_x[j] - eps) / m, theta, unlimited);
|
||||
if (theta < zero_of_type<X>()) theta = zero_of_type<X>();
|
||||
|
@ -529,7 +530,7 @@ public:
|
|||
|
||||
bool limit_inf_on_bound_m_neg(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) {
|
||||
// x gets smaller
|
||||
lean_assert(m < 0);
|
||||
lp_assert(m < 0);
|
||||
if (numeric_traits<T>::precise()) {
|
||||
if (this->below_bound(x, bound)) return false;
|
||||
if (this->above_bound(x, bound)) {
|
||||
|
@ -553,7 +554,7 @@ public:
|
|||
|
||||
bool limit_inf_on_bound_m_pos(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) {
|
||||
// x gets larger
|
||||
lean_assert(m > 0);
|
||||
lp_assert(m > 0);
|
||||
if (numeric_traits<T>::precise()) {
|
||||
if (this->above_bound(x, bound)) return false;
|
||||
if (this->below_bound(x, bound)) {
|
||||
|
@ -578,14 +579,14 @@ public:
|
|||
void limit_inf_on_low_bound_m_pos(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) {
|
||||
if (numeric_traits<T>::precise()) {
|
||||
// x gets larger
|
||||
lean_assert(m > 0);
|
||||
lp_assert(m > 0);
|
||||
if (this->below_bound(x, bound)) {
|
||||
limit_theta((bound - x) / m, theta, unlimited);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// x gets larger
|
||||
lean_assert(m > 0);
|
||||
lp_assert(m > 0);
|
||||
const X& eps = harris_eps_for_bound(bound);
|
||||
if (this->below_bound(x, bound)) {
|
||||
limit_theta((bound - x + eps) / m, theta, unlimited);
|
||||
|
@ -595,7 +596,7 @@ public:
|
|||
|
||||
void limit_inf_on_upper_bound_m_neg(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) {
|
||||
// x gets smaller
|
||||
lean_assert(m < 0);
|
||||
lp_assert(m < 0);
|
||||
const X& eps = harris_eps_for_bound(bound);
|
||||
if (this->above_bound(x, bound)) {
|
||||
limit_theta((bound - x - eps) / m, theta, unlimited);
|
||||
|
@ -603,7 +604,7 @@ public:
|
|||
}
|
||||
|
||||
void limit_theta_on_basis_column_for_inf_case_m_pos_boxed(unsigned j, const T & m, X & theta, bool & unlimited) {
|
||||
// lean_assert(m > 0 && this->m_column_type[j] == column_type::boxed);
|
||||
// lp_assert(m > 0 && this->m_column_type[j] == column_type::boxed);
|
||||
const X & x = this->m_x[j];
|
||||
const X & lbound = this->m_low_bounds[j];
|
||||
|
||||
|
@ -623,7 +624,7 @@ public:
|
|||
}
|
||||
|
||||
void limit_theta_on_basis_column_for_inf_case_m_neg_boxed(unsigned j, const T & m, X & theta, bool & unlimited) {
|
||||
// lean_assert(m < 0 && this->m_column_type[j] == column_type::boxed);
|
||||
// lp_assert(m < 0 && this->m_column_type[j] == column_type::boxed);
|
||||
const X & x = this->m_x[j];
|
||||
const X & ubound = this->m_upper_bounds[j];
|
||||
if (this->above_bound(x, ubound)) {
|
||||
|
@ -641,7 +642,7 @@ public:
|
|||
}
|
||||
}
|
||||
void limit_theta_on_basis_column_for_feas_case_m_pos(unsigned j, const T & m, X & theta, bool & unlimited) {
|
||||
lean_assert(m > 0);
|
||||
lp_assert(m > 0);
|
||||
const T& eps = harris_eps_for_bound(this->m_upper_bounds[j]);
|
||||
if (this->below_bound(this->m_x[j], this->m_upper_bounds[j])) {
|
||||
limit_theta((this->m_upper_bounds[j] - this->m_x[j] + eps) / m, theta, unlimited);
|
||||
|
@ -653,7 +654,7 @@ public:
|
|||
}
|
||||
|
||||
void limit_theta_on_basis_column_for_feas_case_m_pos_no_check(unsigned j, const T & m, X & theta, bool & unlimited ) {
|
||||
lean_assert(m > 0);
|
||||
lp_assert(m > 0);
|
||||
const X& eps = harris_eps_for_bound(this->m_upper_bounds[j]);
|
||||
limit_theta( (this->m_upper_bounds[j] - this->m_x[j] + eps) / m, theta, unlimited);
|
||||
if (theta < zero_of_type<X>()) {
|
||||
|
@ -719,7 +720,7 @@ public:
|
|||
|
||||
break;
|
||||
default:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
}
|
||||
if (!unlimited && theta < zero_of_type<X>()) {
|
||||
theta = zero_of_type<X>();
|
||||
|
@ -778,7 +779,7 @@ public:
|
|||
if (this->m_basis_heading[j] < 0)
|
||||
continue;
|
||||
if (!this->column_is_feasible(j))
|
||||
this->m_inf_set.insert(j);
|
||||
this->insert_column_into_inf_set(j);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -802,7 +803,7 @@ public:
|
|||
case column_type::free_column:
|
||||
return 0;
|
||||
default:
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -837,7 +838,7 @@ public:
|
|||
return -1;
|
||||
break;
|
||||
default:
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
}
|
||||
return 0;
|
||||
|
||||
|
@ -863,7 +864,7 @@ public:
|
|||
|
||||
// the delta is between the old and the new cost (old - new)
|
||||
void update_reduced_cost_for_basic_column_cost_change(const T & delta, unsigned j) {
|
||||
lean_assert(this->m_basis_heading[j] >= 0);
|
||||
lp_assert(this->m_basis_heading[j] >= 0);
|
||||
unsigned i = static_cast<unsigned>(this->m_basis_heading[j]);
|
||||
for (const row_cell<T> & rc : this->m_A.m_rows[i]) {
|
||||
unsigned k = rc.m_j;
|
||||
|
@ -914,7 +915,7 @@ public:
|
|||
} else {
|
||||
m_converted_harris_eps = zero_of_type<T>();
|
||||
}
|
||||
this->set_status(UNKNOWN);
|
||||
this->set_status(lp_status::UNKNOWN);
|
||||
}
|
||||
|
||||
// constructor
|
||||
|
@ -942,7 +943,7 @@ public:
|
|||
upper_bound_values),
|
||||
m_beta(A.row_count()),
|
||||
m_converted_harris_eps(convert_struct<T, double>::convert(this->m_settings.harris_feasibility_tolerance)) {
|
||||
lean_assert(initial_x_is_correct());
|
||||
lp_assert(initial_x_is_correct());
|
||||
m_low_bounds_dummy.resize(A.column_count(), zero_of_type<T>());
|
||||
m_enter_price_eps = numeric_traits<T>::precise() ? numeric_traits<T>::zero() : T(1e-5);
|
||||
#ifdef LEAN_DEBUG
|
||||
|
|
|
@ -9,13 +9,13 @@
|
|||
#include <set>
|
||||
#include <string>
|
||||
#include "util/lp/lp_primal_core_solver.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
// This core solver solves (Ax=b, low_bound_values \leq x \leq upper_bound_values, maximize costs*x )
|
||||
// The right side b is given implicitly by x and the basis
|
||||
|
||||
template <typename T, typename X>
|
||||
void lp_primal_core_solver<T, X>::sort_non_basis_rational() {
|
||||
lean_assert(numeric_traits<T>::precise());
|
||||
lp_assert(numeric_traits<T>::precise());
|
||||
if (this->m_settings.use_tableau()) {
|
||||
std::sort(this->m_nbasis.begin(), this->m_nbasis.end(), [this](unsigned a, unsigned b) {
|
||||
unsigned ca = this->m_A.number_of_non_zeroes_in_column(a);
|
||||
|
@ -70,11 +70,11 @@ bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_on_breakpoin
|
|||
const T & d = this->m_d[j];
|
||||
switch (this->m_column_types[j]) {
|
||||
case column_type::low_bound:
|
||||
lean_assert(this->x_is_at_low_bound(j));
|
||||
lp_assert(this->x_is_at_low_bound(j));
|
||||
ret = d < -m_epsilon_of_reduced_cost;
|
||||
break;
|
||||
case column_type::upper_bound:
|
||||
lean_assert(this->x_is_at_upper_bound(j));
|
||||
lp_assert(this->x_is_at_upper_bound(j));
|
||||
ret = d > m_epsilon_of_reduced_cost;
|
||||
break;
|
||||
case column_type::fixed:
|
||||
|
@ -83,7 +83,7 @@ bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_on_breakpoin
|
|||
case column_type::boxed:
|
||||
{
|
||||
bool low_bound = this->x_is_at_low_bound(j);
|
||||
lean_assert(low_bound || this->x_is_at_upper_bound(j));
|
||||
lp_assert(low_bound || this->x_is_at_upper_bound(j));
|
||||
ret = (low_bound && d < -m_epsilon_of_reduced_cost) || ((!low_bound) && d > m_epsilon_of_reduced_cost);
|
||||
}
|
||||
break;
|
||||
|
@ -91,7 +91,7 @@ bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_on_breakpoin
|
|||
ret = d > m_epsilon_of_reduced_cost || d < - m_epsilon_of_reduced_cost;
|
||||
break;
|
||||
default:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
|
@ -127,14 +127,14 @@ bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_basis(unsign
|
|||
}
|
||||
break;
|
||||
default:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template <typename T, typename X>
|
||||
bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_basis_precise(unsigned j) const {
|
||||
lean_assert (numeric_traits<T>::precise());
|
||||
lp_assert (numeric_traits<T>::precise());
|
||||
if (this->m_using_infeas_costs && this->m_settings.use_breakpoints_in_feasibility_search)
|
||||
return column_is_benefitial_for_entering_on_breakpoints(j);
|
||||
const T& dj = this->m_d[j];
|
||||
|
@ -167,7 +167,7 @@ bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_basis_precis
|
|||
}
|
||||
break;
|
||||
default:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
|
@ -175,7 +175,7 @@ bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_basis_precis
|
|||
|
||||
template <typename T, typename X>
|
||||
int lp_primal_core_solver<T, X>::choose_entering_column_presize(unsigned number_of_benefitial_columns_to_go_over) { // at this moment m_y = cB * B(-1)
|
||||
lean_assert(numeric_traits<T>::precise());
|
||||
lp_assert(numeric_traits<T>::precise());
|
||||
if (number_of_benefitial_columns_to_go_over == 0)
|
||||
return -1;
|
||||
if (this->m_basis_sort_counter == 0) {
|
||||
|
@ -259,7 +259,7 @@ int lp_primal_core_solver<T, X>::choose_entering_column(unsigned number_of_benef
|
|||
template <typename T, typename X> int lp_primal_core_solver<T, X>::advance_on_sorted_breakpoints(unsigned entering, X &t) {
|
||||
T slope_at_entering = this->m_d[entering];
|
||||
breakpoint<X> * last_bp = nullptr;
|
||||
lean_assert(m_breakpoint_indices_queue.is_empty()==false);
|
||||
lp_assert(m_breakpoint_indices_queue.is_empty()==false);
|
||||
while (m_breakpoint_indices_queue.is_empty() == false) {
|
||||
unsigned bi = m_breakpoint_indices_queue.dequeue();
|
||||
breakpoint<X> *b = &m_breakpoints[bi];
|
||||
|
@ -274,7 +274,7 @@ template <typename T, typename X> int lp_primal_core_solver<T, X>::advance_on_so
|
|||
}
|
||||
}
|
||||
}
|
||||
lean_assert (last_bp != nullptr);
|
||||
lp_assert (last_bp != nullptr);
|
||||
t = last_bp->m_delta;
|
||||
return last_bp->m_j;
|
||||
}
|
||||
|
@ -282,13 +282,13 @@ template <typename T, typename X> int lp_primal_core_solver<T, X>::advance_on_so
|
|||
|
||||
template <typename T, typename X> int
|
||||
lp_primal_core_solver<T, X>::find_leaving_and_t_with_breakpoints(unsigned entering, X & t){
|
||||
lean_assert(this->precise() == false);
|
||||
lp_assert(this->precise() == false);
|
||||
fill_breakpoints_array(entering);
|
||||
return advance_on_sorted_breakpoints(entering, t);
|
||||
}
|
||||
|
||||
template <typename T, typename X> bool lp_primal_core_solver<T, X>::get_harris_theta(X & theta) {
|
||||
lean_assert(this->m_ed.is_OK());
|
||||
lp_assert(this->m_ed.is_OK());
|
||||
bool unlimited = true;
|
||||
for (unsigned i : this->m_ed.m_index) {
|
||||
if (this->m_settings.abs_val_is_smaller_than_pivot_tolerance(this->m_ed[i])) continue;
|
||||
|
@ -345,13 +345,13 @@ template <typename T, typename X> bool lp_primal_core_solver<T, X>::try_jump_to_
|
|||
if (m_sign_of_entering_delta > 0) {
|
||||
t = this->m_upper_bounds[entering] - this->m_x[entering];
|
||||
if (unlimited || t <= theta){
|
||||
lean_assert(t >= zero_of_type<X>());
|
||||
lp_assert(t >= zero_of_type<X>());
|
||||
return true;
|
||||
}
|
||||
} else { // m_sign_of_entering_delta == -1
|
||||
t = this->m_x[entering] - this->m_low_bounds[entering];
|
||||
if (unlimited || t <= theta) {
|
||||
lean_assert(t >= zero_of_type<X>());
|
||||
lp_assert(t >= zero_of_type<X>());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -360,7 +360,7 @@ template <typename T, typename X> bool lp_primal_core_solver<T, X>::try_jump_to_
|
|||
if (m_sign_of_entering_delta > 0) {
|
||||
t = this->m_upper_bounds[entering] - this->m_x[entering];
|
||||
if (unlimited || t <= theta){
|
||||
lean_assert(t >= zero_of_type<X>());
|
||||
lp_assert(t >= zero_of_type<X>());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -369,7 +369,7 @@ template <typename T, typename X> bool lp_primal_core_solver<T, X>::try_jump_to_
|
|||
if (m_sign_of_entering_delta < 0) {
|
||||
t = this->m_x[entering] - this->m_low_bounds[entering];
|
||||
if (unlimited || t <= theta) {
|
||||
lean_assert(t >= zero_of_type<X>());
|
||||
lp_assert(t >= zero_of_type<X>());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -405,7 +405,7 @@ template <typename T, typename X> int lp_primal_core_solver<T, X>::find_leaving_
|
|||
do {
|
||||
unsigned i = this->m_ed.m_index[k];
|
||||
const T & ed = this->m_ed[i];
|
||||
lean_assert(!numeric_traits<T>::is_zero(ed));
|
||||
lp_assert(!numeric_traits<T>::is_zero(ed));
|
||||
unsigned j = this->m_basis[i];
|
||||
limit_theta_on_basis_column(j, - ed * m_sign_of_entering_delta, t, unlimited);
|
||||
if (!unlimited) {
|
||||
|
@ -424,7 +424,7 @@ template <typename T, typename X> int lp_primal_core_solver<T, X>::find_leaving_
|
|||
while (k != initial_k) {
|
||||
unsigned i = this->m_ed.m_index[k];
|
||||
const T & ed = this->m_ed[i];
|
||||
lean_assert(!numeric_traits<T>::is_zero(ed));
|
||||
lp_assert(!numeric_traits<T>::is_zero(ed));
|
||||
unsigned j = this->m_basis[i];
|
||||
unlimited = true;
|
||||
limit_theta_on_basis_column(j, -ed * m_sign_of_entering_delta, ratio, unlimited);
|
||||
|
@ -464,7 +464,7 @@ template <typename T, typename X> int lp_primal_core_solver<T, X>::find_leavi
|
|||
return find_leaving_and_t_with_breakpoints(entering, t);
|
||||
X theta;
|
||||
bool unlimited = get_harris_theta(theta);
|
||||
lean_assert(unlimited || theta >= zero_of_type<X>());
|
||||
lp_assert(unlimited || theta >= zero_of_type<X>());
|
||||
if (try_jump_to_another_bound_on_entering(entering, theta, t, unlimited)) return entering;
|
||||
if (unlimited)
|
||||
return -1;
|
||||
|
@ -533,7 +533,7 @@ template <typename T, typename X> X lp_primal_core_solver<T, X>::get_max_boun
|
|||
template <typename T, typename X> void lp_primal_core_solver<T, X>::check_Ax_equal_b() {
|
||||
dense_matrix<T, X> d(this->m_A);
|
||||
T * ls = d.apply_from_left_with_different_dims(this->m_x);
|
||||
lean_assert(vectors_are_equal<T>(ls, this->m_b, this->m_m()));
|
||||
lp_assert(vectors_are_equal<T>(ls, this->m_b, this->m_m()));
|
||||
delete [] ls;
|
||||
}
|
||||
template <typename T, typename X> void lp_primal_core_solver<T, X>::check_the_bounds() {
|
||||
|
@ -543,8 +543,8 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::check_the
|
|||
}
|
||||
|
||||
template <typename T, typename X> void lp_primal_core_solver<T, X>::check_bound(unsigned i) {
|
||||
lean_assert (!(this->column_has_low_bound(i) && (numeric_traits<T>::zero() > this->m_x[i])));
|
||||
lean_assert (!(this->column_has_upper_bound(i) && (this->m_upper_bounds[i] < this->m_x[i])));
|
||||
lp_assert (!(this->column_has_low_bound(i) && (numeric_traits<T>::zero() > this->m_x[i])));
|
||||
lp_assert (!(this->column_has_upper_bound(i) && (this->m_upper_bounds[i] < this->m_x[i])));
|
||||
}
|
||||
|
||||
template <typename T, typename X> void lp_primal_core_solver<T, X>::check_correctness() {
|
||||
|
@ -560,8 +560,8 @@ void lp_primal_core_solver<T, X>::update_reduced_costs_from_pivot_row(unsigned e
|
|||
// the basis heading has changed already
|
||||
#ifdef LEAN_DEBUG
|
||||
auto & basis_heading = this->m_basis_heading;
|
||||
lean_assert(basis_heading[entering] >= 0 && static_cast<unsigned>(basis_heading[entering]) < this->m_m());
|
||||
lean_assert(basis_heading[leaving] < 0);
|
||||
lp_assert(basis_heading[entering] >= 0 && static_cast<unsigned>(basis_heading[entering]) < this->m_m());
|
||||
lp_assert(basis_heading[leaving] < 0);
|
||||
#endif
|
||||
T pivot = this->m_pivot_row[entering];
|
||||
T dq = this->m_d[entering]/pivot;
|
||||
|
@ -584,7 +584,7 @@ void lp_primal_core_solver<T, X>::update_reduced_costs_from_pivot_row(unsigned e
|
|||
template <typename T, typename X> int lp_primal_core_solver<T, X>::refresh_reduced_cost_at_entering_and_check_that_it_is_off(unsigned entering) {
|
||||
if (numeric_traits<T>::precise()) return 0;
|
||||
T reduced_at_entering_was = this->m_d[entering]; // can benefit from going over non-zeros of m_ed
|
||||
lean_assert(abs(reduced_at_entering_was) > m_epsilon_of_reduced_cost);
|
||||
lp_assert(abs(reduced_at_entering_was) > m_epsilon_of_reduced_cost);
|
||||
T refreshed_cost = this->m_costs[entering];
|
||||
unsigned i = this->m_m();
|
||||
while (i--) refreshed_cost -= this->m_costs[this->m_basis[i]] * this->m_ed[i];
|
||||
|
@ -619,7 +619,7 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::backup_an
|
|||
m_costs_backup = this->m_costs;
|
||||
} else {
|
||||
T cost_max = std::max(max_abs_in_vector(this->m_costs), T(1));
|
||||
lean_assert(m_costs_backup.size() == 0);
|
||||
lp_assert(m_costs_backup.size() == 0);
|
||||
for (unsigned j = 0; j < this->m_costs.size(); j++)
|
||||
m_costs_backup.push_back(this->m_costs[j] /= cost_max);
|
||||
}
|
||||
|
@ -649,16 +649,16 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::init_run(
|
|||
|
||||
|
||||
template <typename T, typename X> void lp_primal_core_solver<T, X>::calc_working_vector_beta_for_column_norms(){
|
||||
lean_assert(numeric_traits<T>::precise() == false);
|
||||
lean_assert(this->m_ed.is_OK());
|
||||
lean_assert(m_beta.is_OK());
|
||||
lp_assert(numeric_traits<T>::precise() == false);
|
||||
lp_assert(this->m_ed.is_OK());
|
||||
lp_assert(m_beta.is_OK());
|
||||
m_beta = this->m_ed;
|
||||
this->m_factorization->solve_yB_with_error_check_indexed(m_beta, this->m_basis_heading, this->m_basis, this->m_settings);
|
||||
}
|
||||
|
||||
template <typename T, typename X>
|
||||
void lp_primal_core_solver<T, X>::advance_on_entering_equal_leaving(int entering, X & t) {
|
||||
lean_assert(!this->A_mult_x_is_off() );
|
||||
lp_assert(!this->A_mult_x_is_off() );
|
||||
this->update_x(entering, t * m_sign_of_entering_delta);
|
||||
if (this->A_mult_x_is_off_on_index(this->m_ed.m_index) && !this->find_x_by_solving()) {
|
||||
this->init_lu();
|
||||
|
@ -670,7 +670,7 @@ void lp_primal_core_solver<T, X>::advance_on_entering_equal_leaving(int entering
|
|||
}
|
||||
}
|
||||
if (this->m_using_infeas_costs) {
|
||||
lean_assert(is_zero(this->m_costs[entering]));
|
||||
lp_assert(is_zero(this->m_costs[entering]));
|
||||
init_infeasibility_costs_for_changed_basis_only();
|
||||
}
|
||||
if (this->m_look_for_feasible_solution_only && this->current_x_is_feasible())
|
||||
|
@ -683,10 +683,10 @@ void lp_primal_core_solver<T, X>::advance_on_entering_equal_leaving(int entering
|
|||
}
|
||||
|
||||
template <typename T, typename X>void lp_primal_core_solver<T, X>::advance_on_entering_and_leaving(int entering, int leaving, X & t) {
|
||||
lean_assert(entering >= 0 && m_non_basis_list.back() == static_cast<unsigned>(entering));
|
||||
lean_assert(this->m_using_infeas_costs || t >= zero_of_type<X>());
|
||||
lean_assert(leaving >= 0 && entering >= 0);
|
||||
lean_assert(entering != leaving || !is_zero(t)); // otherwise nothing changes
|
||||
lp_assert(entering >= 0 && m_non_basis_list.back() == static_cast<unsigned>(entering));
|
||||
lp_assert(this->m_using_infeas_costs || t >= zero_of_type<X>());
|
||||
lp_assert(leaving >= 0 && entering >= 0);
|
||||
lp_assert(entering != leaving || !is_zero(t)); // otherwise nothing changes
|
||||
if (entering == leaving) {
|
||||
advance_on_entering_equal_leaving(entering, t);
|
||||
return;
|
||||
|
@ -698,14 +698,14 @@ template <typename T, typename X>void lp_primal_core_solver<T, X>::advance_on_en
|
|||
int pivot_compare_result = this->pivots_in_column_and_row_are_different(entering, leaving);
|
||||
if (!pivot_compare_result){;}
|
||||
else if (pivot_compare_result == 2) { // the sign is changed, cannot continue
|
||||
this->set_status(UNSTABLE);
|
||||
this->set_status(lp_status::UNSTABLE);
|
||||
this->iters_with_no_cost_growing()++;
|
||||
return;
|
||||
} else {
|
||||
lean_assert(pivot_compare_result == 1);
|
||||
lp_assert(pivot_compare_result == 1);
|
||||
this->init_lu();
|
||||
if (this->m_factorization == nullptr || this->m_factorization->get_status() != LU_status::OK) {
|
||||
this->set_status(UNSTABLE);
|
||||
this->set_status(lp_status::UNSTABLE);
|
||||
this->iters_with_no_cost_growing()++;
|
||||
return;
|
||||
}
|
||||
|
@ -717,10 +717,10 @@ template <typename T, typename X>void lp_primal_core_solver<T, X>::advance_on_en
|
|||
t = -t;
|
||||
}
|
||||
if (!this->update_basis_and_x(entering, leaving, t)) {
|
||||
if (this->get_status() == FLOATING_POINT_ERROR)
|
||||
if (this->get_status() == lp_status::FLOATING_POINT_ERROR)
|
||||
return;
|
||||
if (this->m_look_for_feasible_solution_only) {
|
||||
this->set_status(FLOATING_POINT_ERROR);
|
||||
this->set_status(lp_status::FLOATING_POINT_ERROR);
|
||||
return;
|
||||
}
|
||||
init_reduced_costs();
|
||||
|
@ -733,7 +733,7 @@ template <typename T, typename X>void lp_primal_core_solver<T, X>::advance_on_en
|
|||
}
|
||||
|
||||
if (this->current_x_is_feasible()) {
|
||||
this->set_status(FEASIBLE);
|
||||
this->set_status(lp_status::FEASIBLE);
|
||||
if (this->m_look_for_feasible_solution_only)
|
||||
return;
|
||||
}
|
||||
|
@ -746,7 +746,7 @@ template <typename T, typename X>void lp_primal_core_solver<T, X>::advance_on_en
|
|||
} else {
|
||||
update_reduced_costs_from_pivot_row(entering, leaving);
|
||||
}
|
||||
lean_assert(!need_to_switch_costs());
|
||||
lp_assert(!need_to_switch_costs());
|
||||
std::list<unsigned>::iterator it = m_non_basis_list.end();
|
||||
it--;
|
||||
* it = static_cast<unsigned>(leaving);
|
||||
|
@ -754,13 +754,13 @@ template <typename T, typename X>void lp_primal_core_solver<T, X>::advance_on_en
|
|||
|
||||
|
||||
template <typename T, typename X> void lp_primal_core_solver<T, X>::advance_on_entering_precise(int entering) {
|
||||
lean_assert(numeric_traits<T>::precise());
|
||||
lean_assert(entering > -1);
|
||||
lp_assert(numeric_traits<T>::precise());
|
||||
lp_assert(entering > -1);
|
||||
this->solve_Bd(entering);
|
||||
X t;
|
||||
int leaving = find_leaving_and_t_precise(entering, t);
|
||||
if (leaving == -1) {
|
||||
this->set_status(UNBOUNDED);
|
||||
this->set_status(lp_status::UNBOUNDED);
|
||||
return;
|
||||
}
|
||||
advance_on_entering_and_leaving(entering, leaving, t);
|
||||
|
@ -771,12 +771,12 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::advance_on_e
|
|||
advance_on_entering_precise(entering);
|
||||
return;
|
||||
}
|
||||
lean_assert(entering > -1);
|
||||
lp_assert(entering > -1);
|
||||
this->solve_Bd(entering);
|
||||
int refresh_result = refresh_reduced_cost_at_entering_and_check_that_it_is_off(entering);
|
||||
if (refresh_result) {
|
||||
if (this->m_look_for_feasible_solution_only) {
|
||||
this->set_status(FLOATING_POINT_ERROR);
|
||||
this->set_status(lp_status::FLOATING_POINT_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -791,7 +791,7 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::advance_on_e
|
|||
int leaving = find_leaving_and_t(entering, t);
|
||||
if (leaving == -1){
|
||||
if (!this->current_x_is_feasible()) {
|
||||
lean_assert(!numeric_traits<T>::precise()); // we cannot have unbounded with inf costs
|
||||
lp_assert(!numeric_traits<T>::precise()); // we cannot have unbounded with inf costs
|
||||
|
||||
// if (m_look_for_feasible_solution_only) {
|
||||
// this->m_status = INFEASIBLE;
|
||||
|
@ -799,19 +799,19 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::advance_on_e
|
|||
// }
|
||||
|
||||
|
||||
if (this->get_status() == UNSTABLE) {
|
||||
this->set_status(FLOATING_POINT_ERROR);
|
||||
if (this->get_status() == lp_status::UNSTABLE) {
|
||||
this->set_status(lp_status::FLOATING_POINT_ERROR);
|
||||
return;
|
||||
}
|
||||
init_infeasibility_costs();
|
||||
this->set_status(UNSTABLE);
|
||||
this->set_status(lp_status::UNSTABLE);
|
||||
|
||||
return;
|
||||
}
|
||||
if (this->get_status() == TENTATIVE_UNBOUNDED) {
|
||||
this->set_status(UNBOUNDED);
|
||||
if (this->get_status() == lp_status::TENTATIVE_UNBOUNDED) {
|
||||
this->set_status(lp_status::UNBOUNDED);
|
||||
} else {
|
||||
this->set_status(TENTATIVE_UNBOUNDED);
|
||||
this->set_status(lp_status::TENTATIVE_UNBOUNDED);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -825,7 +825,7 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::push_forw
|
|||
|
||||
template <typename T, typename X> unsigned lp_primal_core_solver<T, X>::get_number_of_non_basic_column_to_try_for_enter() {
|
||||
unsigned ret = static_cast<unsigned>(this->m_nbasis.size());
|
||||
if (this->get_status() == TENTATIVE_UNBOUNDED)
|
||||
if (this->get_status() == lp_status::TENTATIVE_UNBOUNDED)
|
||||
return ret; // we really need to find entering with a large reduced cost
|
||||
if (ret > 300) {
|
||||
ret = (unsigned)(ret * this->m_settings.percent_of_entering_to_check / 100);
|
||||
|
@ -852,12 +852,12 @@ template <typename T, typename X> unsigned lp_primal_core_solver<T, X>::solve()
|
|||
|
||||
init_run();
|
||||
if (this->current_x_is_feasible() && this->m_look_for_feasible_solution_only) {
|
||||
this->set_status(FEASIBLE);
|
||||
this->set_status(lp_status::FEASIBLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((!numeric_traits<T>::precise()) && this->A_mult_x_is_off()) {
|
||||
this->set_status(FLOATING_POINT_ERROR);
|
||||
this->set_status(lp_status::FLOATING_POINT_ERROR);
|
||||
return 0;
|
||||
}
|
||||
do {
|
||||
|
@ -865,10 +865,10 @@ template <typename T, typename X> unsigned lp_primal_core_solver<T, X>::solve()
|
|||
return this->total_iterations();
|
||||
}
|
||||
one_iteration();
|
||||
lean_assert(!this->m_using_infeas_costs || this->costs_on_nbasis_are_zeros());
|
||||
lp_assert(!this->m_using_infeas_costs || this->costs_on_nbasis_are_zeros());
|
||||
switch (this->get_status()) {
|
||||
case OPTIMAL: // double check that we are at optimum
|
||||
case INFEASIBLE:
|
||||
case lp_status::OPTIMAL: // double check that we are at optimum
|
||||
case lp_status::INFEASIBLE:
|
||||
if (this->m_look_for_feasible_solution_only && this->current_x_is_feasible())
|
||||
break;
|
||||
if (!numeric_traits<T>::precise()) {
|
||||
|
@ -877,7 +877,7 @@ template <typename T, typename X> unsigned lp_primal_core_solver<T, X>::solve()
|
|||
this->init_lu();
|
||||
|
||||
if (this->m_factorization->get_status() != LU_status::OK) {
|
||||
this->set_status (FLOATING_POINT_ERROR);
|
||||
this->set_status (lp_status::FLOATING_POINT_ERROR);
|
||||
break;
|
||||
}
|
||||
init_reduced_costs();
|
||||
|
@ -885,7 +885,7 @@ template <typename T, typename X> unsigned lp_primal_core_solver<T, X>::solve()
|
|||
decide_on_status_when_cannot_find_entering();
|
||||
break;
|
||||
}
|
||||
this->set_status(UNKNOWN);
|
||||
this->set_status(lp_status::UNKNOWN);
|
||||
} else { // precise case
|
||||
if (this->m_look_for_feasible_solution_only) { // todo: keep the reduced costs correct all the time!
|
||||
init_reduced_costs();
|
||||
|
@ -893,31 +893,31 @@ template <typename T, typename X> unsigned lp_primal_core_solver<T, X>::solve()
|
|||
decide_on_status_when_cannot_find_entering();
|
||||
break;
|
||||
}
|
||||
this->set_status(UNKNOWN);
|
||||
this->set_status(lp_status::UNKNOWN);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TENTATIVE_UNBOUNDED:
|
||||
case lp_status::TENTATIVE_UNBOUNDED:
|
||||
this->init_lu();
|
||||
if (this->m_factorization->get_status() != LU_status::OK) {
|
||||
this->set_status(FLOATING_POINT_ERROR);
|
||||
this->set_status(lp_status::FLOATING_POINT_ERROR);
|
||||
break;
|
||||
}
|
||||
|
||||
init_reduced_costs();
|
||||
break;
|
||||
case UNBOUNDED:
|
||||
case lp_status::UNBOUNDED:
|
||||
if (this->current_x_is_infeasible()) {
|
||||
init_reduced_costs();
|
||||
this->set_status(UNKNOWN);
|
||||
this->set_status(lp_status::UNKNOWN);
|
||||
}
|
||||
break;
|
||||
|
||||
case UNSTABLE:
|
||||
lean_assert(! (numeric_traits<T>::precise()));
|
||||
case lp_status::UNSTABLE:
|
||||
lp_assert(! (numeric_traits<T>::precise()));
|
||||
this->init_lu();
|
||||
if (this->m_factorization->get_status() != LU_status::OK) {
|
||||
this->set_status(FLOATING_POINT_ERROR);
|
||||
this->set_status(lp_status::FLOATING_POINT_ERROR);
|
||||
break;
|
||||
}
|
||||
init_reduced_costs();
|
||||
|
@ -926,13 +926,13 @@ template <typename T, typename X> unsigned lp_primal_core_solver<T, X>::solve()
|
|||
default:
|
||||
break; // do nothing
|
||||
}
|
||||
} while (this->get_status() != FLOATING_POINT_ERROR
|
||||
} while (this->get_status() != lp_status::FLOATING_POINT_ERROR
|
||||
&&
|
||||
this->get_status() != UNBOUNDED
|
||||
this->get_status() != lp_status::UNBOUNDED
|
||||
&&
|
||||
this->get_status() != OPTIMAL
|
||||
this->get_status() != lp_status::OPTIMAL
|
||||
&&
|
||||
this->get_status() != INFEASIBLE
|
||||
this->get_status() != lp_status::INFEASIBLE
|
||||
&&
|
||||
this->iters_with_no_cost_growing() <= this->m_settings.max_number_of_iterations_with_no_improvements
|
||||
&&
|
||||
|
@ -940,7 +940,7 @@ template <typename T, typename X> unsigned lp_primal_core_solver<T, X>::solve()
|
|||
&&
|
||||
!(this->current_x_is_feasible() && this->m_look_for_feasible_solution_only));
|
||||
|
||||
lean_assert(this->get_status() == FLOATING_POINT_ERROR
|
||||
lp_assert(this->get_status() == lp_status::FLOATING_POINT_ERROR
|
||||
||
|
||||
this->current_x_is_feasible() == false
|
||||
||
|
||||
|
@ -957,7 +957,7 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::delete_fa
|
|||
|
||||
// according to Swietanowski, " A new steepest edge approximation for the simplex method for linear programming"
|
||||
template <typename T, typename X> void lp_primal_core_solver<T, X>::init_column_norms() {
|
||||
lean_assert(numeric_traits<T>::precise() == false);
|
||||
lp_assert(numeric_traits<T>::precise() == false);
|
||||
for (unsigned j = 0; j < this->m_n(); j++) {
|
||||
this->m_column_norms[j] = T(static_cast<int>(this->m_A.m_columns[j].size() + 1))
|
||||
|
||||
|
@ -967,7 +967,7 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::init_column_
|
|||
|
||||
// debug only
|
||||
template <typename T, typename X> T lp_primal_core_solver<T, X>::calculate_column_norm_exactly(unsigned j) {
|
||||
lean_assert(numeric_traits<T>::precise() == false);
|
||||
lp_assert(numeric_traits<T>::precise() == false);
|
||||
indexed_vector<T> w(this->m_m());
|
||||
this->m_A.copy_column_to_vector(j, w);
|
||||
vector<T> d(this->m_m());
|
||||
|
@ -979,8 +979,8 @@ template <typename T, typename X> T lp_primal_core_solver<T, X>::calculate_colum
|
|||
}
|
||||
|
||||
template <typename T, typename X> void lp_primal_core_solver<T, X>::update_or_init_column_norms(unsigned entering, unsigned leaving) {
|
||||
lean_assert(numeric_traits<T>::precise() == false);
|
||||
lean_assert(m_column_norm_update_counter <= this->m_settings.column_norms_update_frequency);
|
||||
lp_assert(numeric_traits<T>::precise() == false);
|
||||
lp_assert(m_column_norm_update_counter <= this->m_settings.column_norms_update_frequency);
|
||||
if (m_column_norm_update_counter == this->m_settings.column_norms_update_frequency) {
|
||||
m_column_norm_update_counter = 0;
|
||||
init_column_norms();
|
||||
|
@ -992,7 +992,7 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::update_or
|
|||
|
||||
// following Swietanowski - A new steepest ...
|
||||
template <typename T, typename X> void lp_primal_core_solver<T, X>::update_column_norms(unsigned entering, unsigned leaving) {
|
||||
lean_assert(numeric_traits<T>::precise() == false);
|
||||
lp_assert(numeric_traits<T>::precise() == false);
|
||||
T pivot = this->m_pivot_row[entering];
|
||||
T g_ent = calculate_norm_of_entering_exactly() / pivot / pivot;
|
||||
if (!numeric_traits<T>::precise()) {
|
||||
|
@ -1027,8 +1027,8 @@ template <typename T, typename X> T lp_primal_core_solver<T, X>::calculate_no
|
|||
// calling it stage1 is too cryptic
|
||||
template <typename T, typename X> void lp_primal_core_solver<T, X>::find_feasible_solution() {
|
||||
this->m_look_for_feasible_solution_only = true;
|
||||
lean_assert(this->non_basic_columns_are_set_correctly());
|
||||
this->set_status(UNKNOWN);
|
||||
lp_assert(this->non_basic_columns_are_set_correctly());
|
||||
this->set_status(lp_status::UNKNOWN);
|
||||
solve();
|
||||
}
|
||||
|
||||
|
@ -1072,15 +1072,15 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::fill_breakpo
|
|||
|
||||
|
||||
template <typename T, typename X> bool lp_primal_core_solver<T, X>::done() {
|
||||
if (this->get_status() == OPTIMAL || this->get_status() == FLOATING_POINT_ERROR) return true;
|
||||
if (this->get_status() == INFEASIBLE) {
|
||||
if (this->get_status() == lp_status::OPTIMAL || this->get_status() == lp_status::FLOATING_POINT_ERROR) return true;
|
||||
if (this->get_status() == lp_status::INFEASIBLE) {
|
||||
return true;
|
||||
}
|
||||
if (this->m_iters_with_no_cost_growing >= this->m_settings.max_number_of_iterations_with_no_improvements) {
|
||||
this->get_status() = ITERATIONS_EXHAUSTED; return true;
|
||||
this->get_status() = lp_status::ITERATIONS_EXHAUSTED; return true;
|
||||
}
|
||||
if (this->total_iterations() >= this->m_settings.max_total_number_of_iterations) {
|
||||
this->get_status() = ITERATIONS_EXHAUSTED; return true;
|
||||
this->get_status() = lp_status::ITERATIONS_EXHAUSTED; return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1095,8 +1095,8 @@ void lp_primal_core_solver<T, X>::init_infeasibility_costs_for_changed_basis_onl
|
|||
|
||||
template <typename T, typename X>
|
||||
void lp_primal_core_solver<T, X>::init_infeasibility_costs() {
|
||||
lean_assert(this->m_x.size() >= this->m_n());
|
||||
lean_assert(this->m_column_types.size() >= this->m_n());
|
||||
lp_assert(this->m_x.size() >= this->m_n());
|
||||
lp_assert(this->m_column_types.size() >= this->m_n());
|
||||
for (unsigned j = this->m_n(); j--;)
|
||||
init_infeasibility_cost_for_column(j);
|
||||
this->m_using_infeas_costs = true;
|
||||
|
@ -1138,7 +1138,8 @@ lp_primal_core_solver<T, X>::get_infeasibility_cost_for_column(unsigned j) const
|
|||
ret = numeric_traits<T>::zero();
|
||||
break;
|
||||
default:
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
ret = numeric_traits<T>::zero(); // does not matter
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1191,14 +1192,14 @@ lp_primal_core_solver<T, X>::init_infeasibility_cost_for_column(unsigned j) {
|
|||
this->m_costs[j] = numeric_traits<T>::zero();
|
||||
break;
|
||||
default:
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if (numeric_traits<T>::is_zero(this->m_costs[j])) {
|
||||
this->m_inf_set.erase(j);
|
||||
this->remove_column_from_inf_set(j);
|
||||
} else {
|
||||
this->m_inf_set.insert(j);
|
||||
this->insert_column_into_inf_set(j);
|
||||
}
|
||||
if (!this->m_settings.use_breakpoints_in_feasibility_search) {
|
||||
this->m_costs[j] = - this->m_costs[j];
|
||||
|
@ -1222,7 +1223,7 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::print_column
|
|||
case column_type::free_column:
|
||||
out << "( _" << this->m_x[j] << "_)" << std::endl;
|
||||
default:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1261,7 +1262,7 @@ template <typename T, typename X> std::string lp_primal_core_solver<T, X>::break
|
|||
case upper_break: return "upper_break";
|
||||
case fixed_break: return "fixed_break";
|
||||
default:
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
break;
|
||||
}
|
||||
return "type is not found";
|
||||
|
@ -1274,7 +1275,7 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::print_breakp
|
|||
|
||||
template <typename T, typename X>
|
||||
void lp_primal_core_solver<T, X>::init_reduced_costs() {
|
||||
lean_assert(!this->use_tableau());
|
||||
lp_assert(!this->use_tableau());
|
||||
if (this->current_x_is_infeasible() && !this->m_using_infeas_costs) {
|
||||
init_infeasibility_costs();
|
||||
} else if (this->current_x_is_feasible() && this->m_using_infeas_costs) {
|
||||
|
@ -1289,12 +1290,12 @@ void lp_primal_core_solver<T, X>::init_reduced_costs() {
|
|||
|
||||
template <typename T, typename X> void lp_primal_core_solver<T, X>::change_slope_on_breakpoint(unsigned entering, breakpoint<X> * b, T & slope_at_entering) {
|
||||
if (b->m_j == entering) {
|
||||
lean_assert(b->m_type != fixed_break && (!is_zero(b->m_delta)));
|
||||
lp_assert(b->m_type != fixed_break && (!is_zero(b->m_delta)));
|
||||
slope_at_entering += m_sign_of_entering_delta;
|
||||
return;
|
||||
}
|
||||
|
||||
lean_assert(this->m_basis_heading[b->m_j] >= 0);
|
||||
lp_assert(this->m_basis_heading[b->m_j] >= 0);
|
||||
unsigned i_row = this->m_basis_heading[b->m_j];
|
||||
const T & d = - this->m_ed[i_row];
|
||||
if (numeric_traits<T>::is_zero(d)) return;
|
||||
|
@ -1313,13 +1314,13 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::change_sl
|
|||
slope_at_entering += delta;
|
||||
break;
|
||||
default:
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T, typename X> void lp_primal_core_solver<T, X>::try_add_breakpoint_in_row(unsigned i) {
|
||||
lean_assert(i < this->m_m());
|
||||
lp_assert(i < this->m_m());
|
||||
const T & d = this->m_ed[i]; // the coefficient before m_entering in the i-th row
|
||||
if (d == 0) return; // the change of x[m_entering] will not change the corresponding basis x
|
||||
unsigned j = this->m_basis[i];
|
||||
|
@ -1341,7 +1342,7 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::try_add_b
|
|||
case column_type::free_column:
|
||||
break;
|
||||
default:
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1365,7 +1366,7 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::print_bound_
|
|||
out << "inf, inf" << std::endl;
|
||||
break;
|
||||
default:
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,18 +10,18 @@
|
|||
#include "util/lp/lar_solver.h"
|
||||
#include "util/lp/lp_primal_core_solver.hpp"
|
||||
#include "util/lp/lp_primal_core_solver_tableau.hpp"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
|
||||
template void lp_primal_core_solver<double, double>::find_feasible_solution();
|
||||
template void lean::lp_primal_core_solver<lean::mpq, lean::numeric_pair<lean::mpq> >::find_feasible_solution();
|
||||
template void lp::lp_primal_core_solver<lp::mpq, lp::numeric_pair<lp::mpq> >::find_feasible_solution();
|
||||
|
||||
template unsigned lp_primal_core_solver<double, double>::solve();
|
||||
template unsigned lp_primal_core_solver<double, double>::solve_with_tableau();
|
||||
template unsigned lp_primal_core_solver<mpq, mpq>::solve();
|
||||
template unsigned lp_primal_core_solver<mpq, numeric_pair<mpq> >::solve();
|
||||
template void lean::lp_primal_core_solver<double, double>::clear_breakpoints();
|
||||
template bool lean::lp_primal_core_solver<lean::mpq, lean::mpq>::update_basis_and_x_tableau(int, int, lean::mpq const&);
|
||||
template bool lean::lp_primal_core_solver<double, double>::update_basis_and_x_tableau(int, int, double const&);
|
||||
template bool lean::lp_primal_core_solver<lean::mpq, lean::numeric_pair<lean::mpq> >::update_basis_and_x_tableau(int, int, lean::numeric_pair<lean::mpq> const&);
|
||||
template void lp::lp_primal_core_solver<double, double>::clear_breakpoints();
|
||||
template bool lp::lp_primal_core_solver<lp::mpq, lp::mpq>::update_basis_and_x_tableau(int, int, lp::mpq const&);
|
||||
template bool lp::lp_primal_core_solver<double, double>::update_basis_and_x_tableau(int, int, double const&);
|
||||
template bool lp::lp_primal_core_solver<lp::mpq, lp::numeric_pair<lp::mpq> >::update_basis_and_x_tableau(int, int, lp::numeric_pair<lp::mpq> const&);
|
||||
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
// this is a part of lp_primal_core_solver that deals with the tableau
|
||||
#include "util/lp/lp_primal_core_solver.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T, typename X> void lp_primal_core_solver<T, X>::one_iteration_tableau() {
|
||||
int entering = choose_entering_column_tableau();
|
||||
if (entering == -1) {
|
||||
|
@ -13,14 +13,14 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::one_iteratio
|
|||
else {
|
||||
advance_on_entering_tableau(entering);
|
||||
}
|
||||
lean_assert(this->inf_set_is_correct());
|
||||
lp_assert(this->inf_set_is_correct());
|
||||
}
|
||||
|
||||
template <typename T, typename X> void lp_primal_core_solver<T, X>::advance_on_entering_tableau(int entering) {
|
||||
X t;
|
||||
int leaving = find_leaving_and_t_tableau(entering, t);
|
||||
if (leaving == -1) {
|
||||
this->set_status(UNBOUNDED);
|
||||
this->set_status(lp_status::UNBOUNDED);
|
||||
return;
|
||||
}
|
||||
advance_on_entering_and_leaving_tableau(entering, leaving, t);
|
||||
|
@ -37,7 +37,7 @@ template <typename T, typename X> int lp_primal_core_solver<T, X>::choose_enteri
|
|||
//this moment m_y = cB * B(-1)
|
||||
unsigned number_of_benefitial_columns_to_go_over = get_number_of_non_basic_column_to_try_for_enter();
|
||||
|
||||
lean_assert(numeric_traits<T>::precise());
|
||||
lp_assert(numeric_traits<T>::precise());
|
||||
if (number_of_benefitial_columns_to_go_over == 0)
|
||||
return -1;
|
||||
if (this->m_basis_sort_counter == 0) {
|
||||
|
@ -85,12 +85,12 @@ template <typename T, typename X>
|
|||
unsigned lp_primal_core_solver<T, X>::solve_with_tableau() {
|
||||
init_run_tableau();
|
||||
if (this->current_x_is_feasible() && this->m_look_for_feasible_solution_only) {
|
||||
this->set_status(FEASIBLE);
|
||||
this->set_status(lp_status::FEASIBLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((!numeric_traits<T>::precise()) && this->A_mult_x_is_off()) {
|
||||
this->set_status(FLOATING_POINT_ERROR);
|
||||
this->set_status(lp_status::FLOATING_POINT_ERROR);
|
||||
return 0;
|
||||
}
|
||||
do {
|
||||
|
@ -102,8 +102,8 @@ unsigned lp_primal_core_solver<T, X>::solve_with_tableau() {
|
|||
else
|
||||
one_iteration_tableau();
|
||||
switch (this->get_status()) {
|
||||
case OPTIMAL: // double check that we are at optimum
|
||||
case INFEASIBLE:
|
||||
case lp_status::OPTIMAL: // double check that we are at optimum
|
||||
case lp_status::INFEASIBLE:
|
||||
if (this->m_look_for_feasible_solution_only && this->current_x_is_feasible())
|
||||
break;
|
||||
if (!numeric_traits<T>::precise()) {
|
||||
|
@ -112,7 +112,7 @@ unsigned lp_primal_core_solver<T, X>::solve_with_tableau() {
|
|||
this->init_lu();
|
||||
|
||||
if (this->m_factorization->get_status() != LU_status::OK) {
|
||||
this->set_status(FLOATING_POINT_ERROR);
|
||||
this->set_status(lp_status::FLOATING_POINT_ERROR);
|
||||
break;
|
||||
}
|
||||
init_reduced_costs();
|
||||
|
@ -120,7 +120,7 @@ unsigned lp_primal_core_solver<T, X>::solve_with_tableau() {
|
|||
decide_on_status_when_cannot_find_entering();
|
||||
break;
|
||||
}
|
||||
this->set_status(UNKNOWN);
|
||||
this->set_status(lp_status::UNKNOWN);
|
||||
} else { // precise case
|
||||
if ((!this->infeasibility_costs_are_correct())) {
|
||||
init_reduced_costs_tableau(); // forcing recalc
|
||||
|
@ -128,31 +128,31 @@ unsigned lp_primal_core_solver<T, X>::solve_with_tableau() {
|
|||
decide_on_status_when_cannot_find_entering();
|
||||
break;
|
||||
}
|
||||
this->set_status(UNKNOWN);
|
||||
this->set_status(lp_status::UNKNOWN);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TENTATIVE_UNBOUNDED:
|
||||
case lp_status::TENTATIVE_UNBOUNDED:
|
||||
this->init_lu();
|
||||
if (this->m_factorization->get_status() != LU_status::OK) {
|
||||
this->set_status(FLOATING_POINT_ERROR);
|
||||
this->set_status(lp_status::FLOATING_POINT_ERROR);
|
||||
break;
|
||||
}
|
||||
|
||||
init_reduced_costs();
|
||||
break;
|
||||
case UNBOUNDED:
|
||||
case lp_status::UNBOUNDED:
|
||||
if (this->current_x_is_infeasible()) {
|
||||
init_reduced_costs();
|
||||
this->set_status(UNKNOWN);
|
||||
this->set_status(lp_status::UNKNOWN);
|
||||
}
|
||||
break;
|
||||
|
||||
case UNSTABLE:
|
||||
lean_assert(! (numeric_traits<T>::precise()));
|
||||
case lp_status::UNSTABLE:
|
||||
lp_assert(! (numeric_traits<T>::precise()));
|
||||
this->init_lu();
|
||||
if (this->m_factorization->get_status() != LU_status::OK) {
|
||||
this->set_status(FLOATING_POINT_ERROR);
|
||||
this->set_status(lp_status::FLOATING_POINT_ERROR);
|
||||
break;
|
||||
}
|
||||
init_reduced_costs();
|
||||
|
@ -161,13 +161,13 @@ unsigned lp_primal_core_solver<T, X>::solve_with_tableau() {
|
|||
default:
|
||||
break; // do nothing
|
||||
}
|
||||
} while (this->get_status() != FLOATING_POINT_ERROR
|
||||
} while (this->get_status() != lp_status::FLOATING_POINT_ERROR
|
||||
&&
|
||||
this->get_status() != UNBOUNDED
|
||||
this->get_status() != lp_status::UNBOUNDED
|
||||
&&
|
||||
this->get_status() != OPTIMAL
|
||||
this->get_status() != lp_status::OPTIMAL
|
||||
&&
|
||||
this->get_status() != INFEASIBLE
|
||||
this->get_status() != lp_status::INFEASIBLE
|
||||
&&
|
||||
this->iters_with_no_cost_growing() <= this->m_settings.max_number_of_iterations_with_no_improvements
|
||||
&&
|
||||
|
@ -175,7 +175,7 @@ unsigned lp_primal_core_solver<T, X>::solve_with_tableau() {
|
|||
&&
|
||||
!(this->current_x_is_feasible() && this->m_look_for_feasible_solution_only));
|
||||
|
||||
lean_assert(this->get_status() == FLOATING_POINT_ERROR
|
||||
lp_assert(this->get_status() == lp_status::FLOATING_POINT_ERROR
|
||||
||
|
||||
this->current_x_is_feasible() == false
|
||||
||
|
||||
|
@ -184,13 +184,13 @@ unsigned lp_primal_core_solver<T, X>::solve_with_tableau() {
|
|||
|
||||
}
|
||||
template <typename T, typename X>void lp_primal_core_solver<T, X>::advance_on_entering_and_leaving_tableau(int entering, int leaving, X & t) {
|
||||
lean_assert(this->A_mult_x_is_off() == false);
|
||||
lean_assert(leaving >= 0 && entering >= 0);
|
||||
lean_assert((this->m_settings.simplex_strategy() ==
|
||||
lp_assert(this->A_mult_x_is_off() == false);
|
||||
lp_assert(leaving >= 0 && entering >= 0);
|
||||
lp_assert((this->m_settings.simplex_strategy() ==
|
||||
simplex_strategy_enum::tableau_rows) ||
|
||||
m_non_basis_list.back() == static_cast<unsigned>(entering));
|
||||
lean_assert(this->m_using_infeas_costs || !is_neg(t));
|
||||
lean_assert(entering != leaving || !is_zero(t)); // otherwise nothing changes
|
||||
lp_assert(this->m_using_infeas_costs || !is_neg(t));
|
||||
lp_assert(entering != leaving || !is_zero(t)); // otherwise nothing changes
|
||||
if (entering == leaving) {
|
||||
advance_on_entering_equal_leaving_tableau(entering, t);
|
||||
return;
|
||||
|
@ -201,7 +201,7 @@ template <typename T, typename X>void lp_primal_core_solver<T, X>::advance_on_en
|
|||
t = -t;
|
||||
}
|
||||
this->update_basis_and_x_tableau(entering, leaving, t);
|
||||
lean_assert(this->A_mult_x_is_off() == false);
|
||||
lp_assert(this->A_mult_x_is_off() == false);
|
||||
this->iters_with_no_cost_growing() = 0;
|
||||
} else {
|
||||
this->pivot_column_tableau(entering, this->m_basis_heading[leaving]);
|
||||
|
@ -216,7 +216,7 @@ template <typename T, typename X>void lp_primal_core_solver<T, X>::advance_on_en
|
|||
this->init_reduced_costs_tableau();
|
||||
}
|
||||
|
||||
lean_assert(!need_to_switch_costs());
|
||||
lp_assert(!need_to_switch_costs());
|
||||
std::list<unsigned>::iterator it = m_non_basis_list.end();
|
||||
it--;
|
||||
* it = static_cast<unsigned>(leaving);
|
||||
|
@ -225,7 +225,7 @@ template <typename T, typename X>void lp_primal_core_solver<T, X>::advance_on_en
|
|||
|
||||
template <typename T, typename X>
|
||||
void lp_primal_core_solver<T, X>::advance_on_entering_equal_leaving_tableau(int entering, X & t) {
|
||||
lean_assert(!this->A_mult_x_is_off() );
|
||||
lp_assert(!this->A_mult_x_is_off() );
|
||||
this->update_x_tableau(entering, t * m_sign_of_entering_delta);
|
||||
if (this->m_look_for_feasible_solution_only && this->current_x_is_feasible())
|
||||
return;
|
||||
|
@ -246,7 +246,7 @@ template <typename T, typename X> int lp_primal_core_solver<T, X>::find_leaving_
|
|||
const column_cell & c = col[k];
|
||||
unsigned i = c.m_i;
|
||||
const T & ed = this->m_A.get_val(c);
|
||||
lean_assert(!numeric_traits<T>::is_zero(ed));
|
||||
lp_assert(!numeric_traits<T>::is_zero(ed));
|
||||
unsigned j = this->m_basis[i];
|
||||
limit_theta_on_basis_column(j, - ed * m_sign_of_entering_delta, t, unlimited);
|
||||
if (!unlimited) {
|
||||
|
@ -265,7 +265,7 @@ template <typename T, typename X> int lp_primal_core_solver<T, X>::find_leaving_
|
|||
const column_cell & c = col[k];
|
||||
unsigned i = c.m_i;
|
||||
const T & ed = this->m_A.get_val(c);
|
||||
lean_assert(!numeric_traits<T>::is_zero(ed));
|
||||
lp_assert(!numeric_traits<T>::is_zero(ed));
|
||||
unsigned j = this->m_basis[i];
|
||||
unlimited = true;
|
||||
limit_theta_on_basis_column(j, -ed * m_sign_of_entering_delta, ratio, unlimited);
|
||||
|
@ -298,12 +298,12 @@ template <typename T, typename X> int lp_primal_core_solver<T, X>::find_leaving_
|
|||
}
|
||||
template <typename T, typename X> void lp_primal_core_solver<T, X>::init_run_tableau() {
|
||||
// print_matrix(&(this->m_A), std::cout);
|
||||
lean_assert(this->A_mult_x_is_off() == false);
|
||||
lean_assert(basis_columns_are_set_correctly());
|
||||
lp_assert(this->A_mult_x_is_off() == false);
|
||||
lp_assert(basis_columns_are_set_correctly());
|
||||
this->m_basis_sort_counter = 0; // to initiate the sort of the basis
|
||||
this->set_total_iterations(0);
|
||||
this->iters_with_no_cost_growing() = 0;
|
||||
lean_assert(this->inf_set_is_correct());
|
||||
lp_assert(this->inf_set_is_correct());
|
||||
if (this->current_x_is_feasible() && this->m_look_for_feasible_solution_only)
|
||||
return;
|
||||
if (this->m_settings.backup_costs)
|
||||
|
@ -317,13 +317,13 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::init_run_tab
|
|||
}
|
||||
if (this->m_settings.simplex_strategy() == simplex_strategy_enum::tableau_rows)
|
||||
init_tableau_rows();
|
||||
lean_assert(this->reduced_costs_are_correct_tableau());
|
||||
lean_assert(!this->need_to_pivot_to_basis_tableau());
|
||||
lp_assert(this->reduced_costs_are_correct_tableau());
|
||||
lp_assert(!this->need_to_pivot_to_basis_tableau());
|
||||
}
|
||||
|
||||
template <typename T, typename X> bool lp_primal_core_solver<T, X>::
|
||||
update_basis_and_x_tableau(int entering, int leaving, X const & tt) {
|
||||
lean_assert(this->use_tableau());
|
||||
lp_assert(this->use_tableau());
|
||||
update_x_tableau(entering, tt);
|
||||
this->pivot_column_tableau(entering, this->m_basis_heading[leaving]);
|
||||
this->change_basis(entering, leaving);
|
||||
|
@ -340,8 +340,8 @@ update_x_tableau(unsigned entering, const X& delta) {
|
|||
}
|
||||
} else { // m_using_infeas_costs == true
|
||||
this->m_x[entering] += delta;
|
||||
lean_assert(this->column_is_feasible(entering));
|
||||
lean_assert(this->m_costs[entering] == zero_of_type<T>());
|
||||
lp_assert(this->column_is_feasible(entering));
|
||||
lp_assert(this->m_costs[entering] == zero_of_type<T>());
|
||||
// m_d[entering] can change because of the cost change for basic columns.
|
||||
for (const auto & c : this->m_A.m_columns[entering]) {
|
||||
unsigned i = c.m_i;
|
||||
|
@ -349,18 +349,18 @@ update_x_tableau(unsigned entering, const X& delta) {
|
|||
this->m_x[j] -= delta * this->m_A.get_val(c);
|
||||
update_inf_cost_for_column_tableau(j);
|
||||
if (is_zero(this->m_costs[j]))
|
||||
this->m_inf_set.erase(j);
|
||||
this->remove_column_from_inf_set(j);
|
||||
else
|
||||
this->m_inf_set.insert(j);
|
||||
this->insert_column_into_inf_set(j);
|
||||
}
|
||||
}
|
||||
lean_assert(this->A_mult_x_is_off() == false);
|
||||
lp_assert(this->A_mult_x_is_off() == false);
|
||||
}
|
||||
|
||||
template <typename T, typename X> void lp_primal_core_solver<T, X>::
|
||||
update_inf_cost_for_column_tableau(unsigned j) {
|
||||
lean_assert(this->m_settings.simplex_strategy() != simplex_strategy_enum::tableau_rows);
|
||||
lean_assert(this->m_using_infeas_costs);
|
||||
lp_assert(this->m_settings.simplex_strategy() != simplex_strategy_enum::tableau_rows);
|
||||
lp_assert(this->m_using_infeas_costs);
|
||||
T new_cost = get_infeasibility_cost_for_column(j);
|
||||
T delta = this->m_costs[j] - new_cost;
|
||||
if (is_zero(delta))
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include "util/lp/lp_primal_core_solver.h"
|
||||
#include "util/lp/lp_solver.h"
|
||||
#include "util/lp/iterator_on_row.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T, typename X>
|
||||
class lp_primal_simplex: public lp_solver<T, X> {
|
||||
lp_primal_core_solver<T, X> * m_core_solver;
|
||||
|
@ -55,10 +55,6 @@ public:
|
|||
|
||||
void set_core_solver_bounds();
|
||||
|
||||
void update_time_limit_from_starting_time(int start_time) {
|
||||
this->m_settings.time_limit -= (get_millisecond_span(start_time) / 1000.);
|
||||
}
|
||||
|
||||
void find_maximal_solution();
|
||||
|
||||
void fill_A_x_and_basis_for_stage_one_total_inf();
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "util/vector.h"
|
||||
#include "util/lp/lp_primal_simplex.h"
|
||||
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T, typename X> void lp_primal_simplex<T, X>::fill_costs_and_x_for_first_stage_solver(unsigned original_number_of_columns) {
|
||||
unsigned slack_var = original_number_of_columns;
|
||||
unsigned artificial = original_number_of_columns + this->m_slacks;
|
||||
|
@ -61,7 +61,7 @@ template <typename T, typename X> void lp_primal_simplex<T, X>::fill_costs_and_x
|
|||
int row,
|
||||
unsigned & slack_var,
|
||||
unsigned & artificial) {
|
||||
lean_assert(row >= 0 && row < this->row_count());
|
||||
lp_assert(row >= 0 && row < this->row_count());
|
||||
auto & constraint = this->m_constraints[this->m_core_solver_rows_to_external_rows[row]];
|
||||
// we need to bring the program to the form Ax = b
|
||||
T rs = this->m_b[row];
|
||||
|
@ -86,7 +86,7 @@ template <typename T, typename X> void lp_primal_simplex<T, X>::fill_costs_and_x
|
|||
(*this->m_A)(row, slack_var) = - numeric_traits<T>::one();
|
||||
|
||||
if (rs > 0) {
|
||||
lean_assert(numeric_traits<T>::is_zero(this->m_x[slack_var]));
|
||||
lp_assert(numeric_traits<T>::is_zero(this->m_x[slack_var]));
|
||||
// adding one artificial
|
||||
this->m_column_types[artificial] = column_type::low_bound;
|
||||
(*this->m_A)(row, artificial) = numeric_traits<T>::one();
|
||||
|
@ -108,7 +108,7 @@ template <typename T, typename X> void lp_primal_simplex<T, X>::fill_costs_and_x
|
|||
|
||||
if (rs < 0) {
|
||||
// adding one artificial
|
||||
lean_assert(numeric_traits<T>::is_zero(this->m_x[slack_var]));
|
||||
lp_assert(numeric_traits<T>::is_zero(this->m_x[slack_var]));
|
||||
this->m_column_types[artificial] = column_type::low_bound;
|
||||
(*this->m_A)(row, artificial) = - numeric_traits<T>::one();
|
||||
this->m_costs[artificial] = artificial_cost;
|
||||
|
@ -152,7 +152,6 @@ template <typename T, typename X> void lp_primal_simplex<T, X>::set_core_solver_
|
|||
|
||||
|
||||
template <typename T, typename X> void lp_primal_simplex<T, X>::find_maximal_solution() {
|
||||
int preprocessing_start_time = get_millisecond_count();
|
||||
if (this->problem_is_empty()) {
|
||||
this->m_status = lp_status::EMPTY;
|
||||
return;
|
||||
|
@ -169,7 +168,6 @@ template <typename T, typename X> void lp_primal_simplex<T, X>::find_maximal_sol
|
|||
fill_acceptable_values_for_x();
|
||||
this->count_slacks_and_artificials();
|
||||
set_core_solver_bounds();
|
||||
update_time_limit_from_starting_time(preprocessing_start_time);
|
||||
solve_with_total_inf();
|
||||
}
|
||||
|
||||
|
@ -179,12 +177,12 @@ template <typename T, typename X> void lp_primal_simplex<T, X>::fill_A_x_and_bas
|
|||
}
|
||||
|
||||
template <typename T, typename X> void lp_primal_simplex<T, X>::fill_A_x_and_basis_for_stage_one_total_inf_for_row(unsigned row) {
|
||||
lean_assert(row < this->row_count());
|
||||
lp_assert(row < this->row_count());
|
||||
auto ext_row_it = this->m_core_solver_rows_to_external_rows.find(row);
|
||||
lean_assert(ext_row_it != this->m_core_solver_rows_to_external_rows.end());
|
||||
lp_assert(ext_row_it != this->m_core_solver_rows_to_external_rows.end());
|
||||
unsigned ext_row = ext_row_it->second;
|
||||
auto constr_it = this->m_constraints.find(ext_row);
|
||||
lean_assert(constr_it != this->m_constraints.end());
|
||||
lp_assert(constr_it != this->m_constraints.end());
|
||||
auto & constraint = constr_it->second;
|
||||
unsigned j = this->m_A->column_count(); // j is a slack variable
|
||||
this->m_A->add_column();
|
||||
|
@ -211,14 +209,14 @@ template <typename T, typename X> void lp_primal_simplex<T, X>::fill_A_x_and_bas
|
|||
this->m_upper_bounds[j] = m_low_bounds[j] = zero_of_type<X>();
|
||||
break;
|
||||
default:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename X> void lp_primal_simplex<T, X>::solve_with_total_inf() {
|
||||
int total_vars = this->m_A->column_count() + this->row_count();
|
||||
if (total_vars == 0) {
|
||||
this->m_status = OPTIMAL;
|
||||
this->m_status = lp_status::OPTIMAL;
|
||||
return;
|
||||
}
|
||||
m_low_bounds.clear();
|
||||
|
@ -283,10 +281,10 @@ template <typename T, typename X> T lp_primal_simplex<T, X>::get_row_value(unsig
|
|||
T ret = numeric_traits<T>::zero();
|
||||
for (auto & pair : it->second) {
|
||||
auto cit = this->m_map_from_var_index_to_column_info.find(pair.first);
|
||||
lean_assert(cit != this->m_map_from_var_index_to_column_info.end());
|
||||
lp_assert(cit != this->m_map_from_var_index_to_column_info.end());
|
||||
column_info<T> * ci = cit->second;
|
||||
auto sol_it = solution.find(ci->get_name());
|
||||
lean_assert(sol_it != solution.end());
|
||||
lp_assert(sol_it != solution.end());
|
||||
T column_val = sol_it->second;
|
||||
if (out != nullptr) {
|
||||
(*out) << pair.second << "(" << ci->get_name() << "=" << column_val << ") ";
|
||||
|
@ -331,7 +329,7 @@ template <typename T, typename X> bool lp_primal_simplex<T, X>::row_constraint_h
|
|||
}
|
||||
return true;;
|
||||
}
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
return false; // it is unreachable
|
||||
}
|
||||
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
#include "util/vector.h"
|
||||
#include <functional>
|
||||
#include "util/lp/lp_primal_simplex.hpp"
|
||||
template bool lean::lp_primal_simplex<double, double>::bounds_hold(std::unordered_map<std::string, double, std::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, double> > > const&);
|
||||
template bool lean::lp_primal_simplex<double, double>::row_constraints_hold(std::unordered_map<std::string, double, std::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, double> > > const&);
|
||||
template double lean::lp_primal_simplex<double, double>::get_current_cost() const;
|
||||
template double lean::lp_primal_simplex<double, double>::get_column_value(unsigned int) const;
|
||||
template lean::lp_primal_simplex<double, double>::~lp_primal_simplex();
|
||||
template lean::lp_primal_simplex<lean::mpq, lean::mpq>::~lp_primal_simplex();
|
||||
template lean::mpq lean::lp_primal_simplex<lean::mpq, lean::mpq>::get_current_cost() const;
|
||||
template lean::mpq lean::lp_primal_simplex<lean::mpq, lean::mpq>::get_column_value(unsigned int) const;
|
||||
template void lean::lp_primal_simplex<double, double>::find_maximal_solution();
|
||||
template void lean::lp_primal_simplex<lean::mpq, lean::mpq>::find_maximal_solution();
|
||||
template bool lp::lp_primal_simplex<double, double>::bounds_hold(std::unordered_map<std::string, double, std::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, double> > > const&);
|
||||
template bool lp::lp_primal_simplex<double, double>::row_constraints_hold(std::unordered_map<std::string, double, std::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, double> > > const&);
|
||||
template double lp::lp_primal_simplex<double, double>::get_current_cost() const;
|
||||
template double lp::lp_primal_simplex<double, double>::get_column_value(unsigned int) const;
|
||||
template lp::lp_primal_simplex<double, double>::~lp_primal_simplex();
|
||||
template lp::lp_primal_simplex<lp::mpq, lp::mpq>::~lp_primal_simplex();
|
||||
template lp::mpq lp::lp_primal_simplex<lp::mpq, lp::mpq>::get_current_cost() const;
|
||||
template lp::mpq lp::lp_primal_simplex<lp::mpq, lp::mpq>::get_column_value(unsigned int) const;
|
||||
template void lp::lp_primal_simplex<double, double>::find_maximal_solution();
|
||||
template void lp::lp_primal_simplex<lp::mpq, lp::mpq>::find_maximal_solution();
|
||||
|
|
|
@ -8,32 +8,25 @@
|
|||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <sys/timeb.h>
|
||||
#include <iomanip>
|
||||
#include "util/lp/lp_utils.h"
|
||||
#include "util/stopwatch.h"
|
||||
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
typedef unsigned var_index;
|
||||
typedef unsigned constraint_index;
|
||||
typedef unsigned row_index;
|
||||
|
||||
enum class final_check_status {
|
||||
DONE,
|
||||
CONTINUE,
|
||||
UNSAT,
|
||||
GIVEUP
|
||||
};
|
||||
|
||||
typedef vector<std::pair<mpq, constraint_index>> explanation_t;
|
||||
|
||||
|
||||
enum class column_type {
|
||||
free_column = 0,
|
||||
low_bound = 1,
|
||||
upper_bound = 2,
|
||||
boxed = 3,
|
||||
fixed = 4
|
||||
};
|
||||
low_bound = 1,
|
||||
upper_bound = 2,
|
||||
boxed = 3,
|
||||
fixed = 4
|
||||
};
|
||||
|
||||
enum class simplex_strategy_enum {
|
||||
undecided = 3,
|
||||
|
@ -44,7 +37,7 @@ enum class simplex_strategy_enum {
|
|||
|
||||
std::string column_type_to_string(column_type t);
|
||||
|
||||
enum lp_status {
|
||||
enum class lp_status {
|
||||
UNKNOWN,
|
||||
INFEASIBLE,
|
||||
TENTATIVE_UNBOUNDED,
|
||||
|
@ -80,21 +73,20 @@ enum non_basic_column_value_position { at_low_bound, at_upper_bound, at_fixed, f
|
|||
|
||||
template <typename X> bool is_epsilon_small(const X & v, const double& eps); // forward definition
|
||||
|
||||
int get_millisecond_count();
|
||||
int get_millisecond_span(int start_time);
|
||||
|
||||
|
||||
class lp_resource_limit {
|
||||
public:
|
||||
virtual bool get_cancel_flag() = 0;
|
||||
};
|
||||
|
||||
struct stats {
|
||||
unsigned m_make_feasible;
|
||||
unsigned m_total_iterations;
|
||||
unsigned m_iters_with_no_cost_growing;
|
||||
unsigned m_num_factorizations;
|
||||
unsigned m_num_of_implied_bounds;
|
||||
unsigned m_need_to_solve_inf;
|
||||
unsigned m_max_cols;
|
||||
unsigned m_max_rows;
|
||||
stats() { reset(); }
|
||||
void reset() { memset(this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
@ -103,12 +95,13 @@ struct lp_settings {
|
|||
private:
|
||||
class default_lp_resource_limit : public lp_resource_limit {
|
||||
lp_settings& m_settings;
|
||||
int m_start_time;
|
||||
stopwatch m_sw;
|
||||
public:
|
||||
default_lp_resource_limit(lp_settings& s): m_settings(s), m_start_time(get_millisecond_count()) {}
|
||||
default_lp_resource_limit(lp_settings& s): m_settings(s) {
|
||||
m_sw.start();
|
||||
}
|
||||
virtual bool get_cancel_flag() {
|
||||
int span_in_mills = get_millisecond_span(m_start_time);
|
||||
return (span_in_mills / 1000.0 > m_settings.time_limit);
|
||||
return (m_sw.get_current_seconds() > m_settings.time_limit);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -212,7 +205,8 @@ public:
|
|||
use_breakpoints_in_feasibility_search(false),
|
||||
max_row_length_for_bound_propagation(300),
|
||||
backup_costs(true),
|
||||
column_number_threshold_for_using_lu_in_lar_solver(4000)
|
||||
column_number_threshold_for_using_lu_in_lar_solver(4000),
|
||||
m_int_branch_cut_threshold(100)
|
||||
{}
|
||||
|
||||
void set_resource_limit(lp_resource_limit& lim) { m_resource_limit = &lim; }
|
||||
|
@ -292,13 +286,13 @@ public:
|
|||
return m_simplex_strategy;
|
||||
}
|
||||
|
||||
bool use_lu() const {
|
||||
return m_simplex_strategy == simplex_strategy_enum::lu;
|
||||
}
|
||||
bool use_lu() const {
|
||||
return m_simplex_strategy == simplex_strategy_enum::lu;
|
||||
}
|
||||
|
||||
bool use_tableau() const {
|
||||
return m_simplex_strategy == simplex_strategy_enum::tableau_rows ||
|
||||
m_simplex_strategy == simplex_strategy_enum::tableau_costs;
|
||||
return m_simplex_strategy == simplex_strategy_enum::tableau_rows ||
|
||||
m_simplex_strategy == simplex_strategy_enum::tableau_costs;
|
||||
}
|
||||
|
||||
bool use_tableau_rows() const {
|
||||
|
@ -319,6 +313,7 @@ public:
|
|||
unsigned max_row_length_for_bound_propagation;
|
||||
bool backup_costs;
|
||||
unsigned column_number_threshold_for_using_lu_in_lar_solver;
|
||||
unsigned m_int_branch_cut_threshold;
|
||||
}; // end of lp_settings class
|
||||
|
||||
|
||||
|
@ -380,7 +375,7 @@ inline void print_blanks(int n, std::ostream & out) {
|
|||
// after a push of the last element we ensure that the vector increases
|
||||
// we also suppose that before the last push the vector was increasing
|
||||
inline void ensure_increasing(vector<unsigned> & v) {
|
||||
lean_assert(v.size() > 0);
|
||||
lp_assert(v.size() > 0);
|
||||
unsigned j = v.size() - 1;
|
||||
for (; j > 0; j-- )
|
||||
if (v[j] <= v[j - 1]) {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <string>
|
||||
#include "util/vector.h"
|
||||
#include "util/lp/lp_settings.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
std::string column_type_to_string(column_type t) {
|
||||
switch (t) {
|
||||
case column_type::fixed: return "fixed";
|
||||
|
@ -14,27 +14,27 @@ std::string column_type_to_string(column_type t) {
|
|||
case column_type::low_bound: return "low_bound";
|
||||
case column_type::upper_bound: return "upper_bound";
|
||||
case column_type::free_column: return "free_column";
|
||||
default: lean_unreachable();
|
||||
default: lp_unreachable();
|
||||
}
|
||||
return "unknown"; // it is unreachable
|
||||
}
|
||||
|
||||
const char* lp_status_to_string(lp_status status) {
|
||||
switch (status) {
|
||||
case UNKNOWN: return "UNKNOWN";
|
||||
case INFEASIBLE: return "INFEASIBLE";
|
||||
case UNBOUNDED: return "UNBOUNDED";
|
||||
case TENTATIVE_DUAL_UNBOUNDED: return "TENTATIVE_DUAL_UNBOUNDED";
|
||||
case DUAL_UNBOUNDED: return "DUAL_UNBOUNDED";
|
||||
case OPTIMAL: return "OPTIMAL";
|
||||
case FEASIBLE: return "FEASIBLE";
|
||||
case FLOATING_POINT_ERROR: return "FLOATING_POINT_ERROR";
|
||||
case TIME_EXHAUSTED: return "TIME_EXHAUSTED";
|
||||
case ITERATIONS_EXHAUSTED: return "ITERATIONS_EXHAUSTED";
|
||||
case EMPTY: return "EMPTY";
|
||||
case UNSTABLE: return "UNSTABLE";
|
||||
case lp_status::UNKNOWN: return "UNKNOWN";
|
||||
case lp_status::INFEASIBLE: return "INFEASIBLE";
|
||||
case lp_status::UNBOUNDED: return "UNBOUNDED";
|
||||
case lp_status::TENTATIVE_DUAL_UNBOUNDED: return "TENTATIVE_DUAL_UNBOUNDED";
|
||||
case lp_status::DUAL_UNBOUNDED: return "DUAL_UNBOUNDED";
|
||||
case lp_status::OPTIMAL: return "OPTIMAL";
|
||||
case lp_status::FEASIBLE: return "FEASIBLE";
|
||||
case lp_status::FLOATING_POINT_ERROR: return "FLOATING_POINT_ERROR";
|
||||
case lp_status::TIME_EXHAUSTED: return "TIME_EXHAUSTED";
|
||||
case lp_status::ITERATIONS_EXHAUSTED: return "ITERATIONS_EXHAUSTED";
|
||||
case lp_status::EMPTY: return "EMPTY";
|
||||
case lp_status::UNSTABLE: return "UNSTABLE";
|
||||
default:
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
}
|
||||
return "UNKNOWN"; // it is unreachable
|
||||
}
|
||||
|
@ -49,22 +49,9 @@ lp_status lp_status_from_string(std::string status) {
|
|||
if (status == "TIME_EXHAUSTED") return lp_status::TIME_EXHAUSTED;
|
||||
if (status == "ITERATIONS_EXHAUSTED") return lp_status::ITERATIONS_EXHAUSTED;
|
||||
if (status == "EMPTY") return lp_status::EMPTY;
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
return lp_status::UNKNOWN; // it is unreachable
|
||||
}
|
||||
int get_millisecond_count() {
|
||||
timeb tb;
|
||||
ftime(&tb);
|
||||
return tb.millitm + (tb.time & 0xfffff) * 1000;
|
||||
}
|
||||
|
||||
int get_millisecond_span(int start_time) {
|
||||
int span = get_millisecond_count() - start_time;
|
||||
if (span < 0)
|
||||
span += 0x100000 * 1000;
|
||||
return span;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
Copyright (c) 2017 Microsoft Corporation
|
||||
Author: Lev Nachmanson
|
||||
*/
|
||||
#include "util/vector.h"
|
||||
#include <memory>
|
||||
#include "util/vector.h"
|
||||
#include "util/lp/lp_settings.hpp"
|
||||
template bool lean::vectors_are_equal<double>(vector<double> const&, vector<double> const&);
|
||||
template bool lean::vectors_are_equal<lean::mpq>(vector<lean::mpq > const&, vector<lean::mpq> const&);
|
||||
template bool lp::vectors_are_equal<double>(vector<double> const&, vector<double> const&);
|
||||
template bool lp::vectors_are_equal<lp::mpq>(vector<lp::mpq > const&, vector<lp::mpq> const&);
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include "util/lp/scaler.h"
|
||||
#include "util/lp/linear_combination_iterator.h"
|
||||
#include "util/lp/bound_analyzer_on_row.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
enum lp_relation {
|
||||
Less_or_equal,
|
||||
Equal,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <algorithm>
|
||||
#include "util/vector.h"
|
||||
#include "util/lp/lp_solver.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T, typename X> column_info<T> * lp_solver<T, X>::get_or_create_column_info(unsigned column) {
|
||||
auto it = m_map_from_var_index_to_column_info.find(column);
|
||||
return (it == m_map_from_var_index_to_column_info.end())? (m_map_from_var_index_to_column_info[column] = new column_info<T>(static_cast<unsigned>(-1))) : it->second;
|
||||
|
@ -32,7 +32,7 @@ template <typename T, typename X> T lp_solver<T, X>::get_column_cost_value(unsig
|
|||
return ci->get_cost() * get_column_value(j);
|
||||
}
|
||||
template <typename T, typename X> void lp_solver<T, X>::add_constraint(lp_relation relation, T right_side, unsigned row_index) {
|
||||
lean_assert(m_constraints.find(row_index) == m_constraints.end());
|
||||
lp_assert(m_constraints.find(row_index) == m_constraints.end());
|
||||
lp_constraint<T, X> cs(right_side, relation);
|
||||
m_constraints[row_index] = cs;
|
||||
}
|
||||
|
@ -158,10 +158,10 @@ template <typename T, typename X> void lp_solver<T, X>::pin_vars_on_row_with_sig
|
|||
column_info<T> * ci = m_map_from_var_index_to_column_info[j];
|
||||
T a = t.second;
|
||||
if (a * sign > numeric_traits<T>::zero()) {
|
||||
lean_assert(ci->upper_bound_is_set());
|
||||
lp_assert(ci->upper_bound_is_set());
|
||||
ci->set_fixed_value(ci->get_upper_bound());
|
||||
} else {
|
||||
lean_assert(ci->low_bound_is_set());
|
||||
lp_assert(ci->low_bound_is_set());
|
||||
ci->set_fixed_value(ci->get_low_bound());
|
||||
}
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ template <typename T, typename X> bool lp_solver<T, X>::row_e_is_obsolete(std
|
|||
T rs = m_constraints[row_index].m_rs;
|
||||
if (row_is_zero(row)) {
|
||||
if (!is_zero(rs))
|
||||
m_status = INFEASIBLE;
|
||||
m_status = lp_status::INFEASIBLE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -233,7 +233,7 @@ template <typename T, typename X> bool lp_solver<T, X>::row_e_is_obsolete(std
|
|||
T diff = low_bound - rs;
|
||||
if (!val_is_smaller_than_eps(diff, m_settings.refactor_tolerance)){
|
||||
// low_bound > rs + m_settings.refactor_epsilon
|
||||
m_status = INFEASIBLE;
|
||||
m_status = lp_status::INFEASIBLE;
|
||||
return true;
|
||||
}
|
||||
if (val_is_smaller_than_eps(-diff, m_settings.refactor_tolerance)){
|
||||
|
@ -248,7 +248,7 @@ template <typename T, typename X> bool lp_solver<T, X>::row_e_is_obsolete(std
|
|||
T diff = rs - upper_bound;
|
||||
if (!val_is_smaller_than_eps(diff, m_settings.refactor_tolerance)) {
|
||||
// upper_bound < rs - m_settings.refactor_tolerance
|
||||
m_status = INFEASIBLE;
|
||||
m_status = lp_status::INFEASIBLE;
|
||||
return true;
|
||||
}
|
||||
if (val_is_smaller_than_eps(-diff, m_settings.refactor_tolerance)){
|
||||
|
@ -264,7 +264,7 @@ template <typename T, typename X> bool lp_solver<T, X>::row_ge_is_obsolete(std:
|
|||
T rs = m_constraints[row_index].m_rs;
|
||||
if (row_is_zero(row)) {
|
||||
if (rs > zero_of_type<X>())
|
||||
m_status = INFEASIBLE;
|
||||
m_status = lp_status::INFEASIBLE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -273,7 +273,7 @@ template <typename T, typename X> bool lp_solver<T, X>::row_ge_is_obsolete(std:
|
|||
T diff = rs - upper_bound;
|
||||
if (!val_is_smaller_than_eps(diff, m_settings.refactor_tolerance)) {
|
||||
// upper_bound < rs - m_settings.refactor_tolerance
|
||||
m_status = INFEASIBLE;
|
||||
m_status = lp_status::INFEASIBLE;
|
||||
return true;
|
||||
}
|
||||
if (val_is_smaller_than_eps(-diff, m_settings.refactor_tolerance)){
|
||||
|
@ -290,7 +290,7 @@ template <typename T, typename X> bool lp_solver<T, X>::row_le_is_obsolete(std::
|
|||
T rs = m_constraints[row_index].m_rs;
|
||||
if (row_is_zero(row)) {
|
||||
if (rs < zero_of_type<X>())
|
||||
m_status = INFEASIBLE;
|
||||
m_status = lp_status::INFEASIBLE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -328,7 +328,7 @@ template <typename T, typename X> bool lp_solver<T, X>::row_is_obsolete(std::
|
|||
case lp_relation::Less_or_equal:
|
||||
return row_le_is_obsolete(row, row_index);
|
||||
}
|
||||
lean_unreachable();
|
||||
lp_unreachable();
|
||||
return false; // it is unreachable
|
||||
}
|
||||
|
||||
|
@ -343,7 +343,7 @@ template <typename T, typename X> void lp_solver<T, X>::remove_fixed_or_zero_col
|
|||
vector<unsigned> removed;
|
||||
for (auto & col : row) {
|
||||
unsigned j = col.first;
|
||||
lean_assert(m_map_from_var_index_to_column_info.find(j) != m_map_from_var_index_to_column_info.end());
|
||||
lp_assert(m_map_from_var_index_to_column_info.find(j) != m_map_from_var_index_to_column_info.end());
|
||||
column_info<T> * ci = m_map_from_var_index_to_column_info[j];
|
||||
if (ci->is_fixed()) {
|
||||
removed.push_back(j);
|
||||
|
@ -412,7 +412,7 @@ template <typename T, typename X> void lp_solver<T, X>::map_external_columns_to_
|
|||
}
|
||||
unsigned j = col.first;
|
||||
auto column_info_it = m_map_from_var_index_to_column_info.find(j);
|
||||
lean_assert(column_info_it != m_map_from_var_index_to_column_info.end());
|
||||
lp_assert(column_info_it != m_map_from_var_index_to_column_info.end());
|
||||
|
||||
auto j_column = column_info_it->second->get_column_index();
|
||||
if (!is_valid(j_column)) { // j is a newcomer
|
||||
|
@ -435,14 +435,14 @@ template <typename T, typename X> void lp_solver<T, X>::fill_A_from_A_values() {
|
|||
m_A = new static_matrix<T, X>(static_cast<unsigned>(m_A_values.size()), number_of_core_structurals());
|
||||
for (auto & t : m_A_values) {
|
||||
auto row_it = m_external_rows_to_core_solver_rows.find(t.first);
|
||||
lean_assert(row_it != m_external_rows_to_core_solver_rows.end());
|
||||
lp_assert(row_it != m_external_rows_to_core_solver_rows.end());
|
||||
unsigned row = row_it->second;
|
||||
for (auto k : t.second) {
|
||||
auto column_info_it = m_map_from_var_index_to_column_info.find(k.first);
|
||||
lean_assert(column_info_it != m_map_from_var_index_to_column_info.end());
|
||||
lp_assert(column_info_it != m_map_from_var_index_to_column_info.end());
|
||||
column_info<T> *ci = column_info_it->second;
|
||||
unsigned col = ci->get_column_index();
|
||||
lean_assert(is_valid(col));
|
||||
lp_assert(is_valid(col));
|
||||
bool col_is_flipped = m_map_from_var_index_to_column_info[k.first]->is_flipped();
|
||||
if (!col_is_flipped) {
|
||||
(*m_A)(row, col) = k.second;
|
||||
|
@ -456,7 +456,7 @@ template <typename T, typename X> void lp_solver<T, X>::fill_A_from_A_values() {
|
|||
template <typename T, typename X> void lp_solver<T, X>::fill_matrix_A_and_init_right_side() {
|
||||
map_external_rows_to_core_solver_rows();
|
||||
map_external_columns_to_core_solver_columns();
|
||||
lean_assert(m_A == nullptr);
|
||||
lp_assert(m_A == nullptr);
|
||||
fill_A_from_A_values();
|
||||
m_b.resize(m_A->row_count());
|
||||
}
|
||||
|
@ -468,7 +468,7 @@ template <typename T, typename X> void lp_solver<T, X>::count_slacks_and_artific
|
|||
}
|
||||
|
||||
template <typename T, typename X> void lp_solver<T, X>::count_slacks_and_artificials_for_row(unsigned i) {
|
||||
lean_assert(this->m_constraints.find(this->m_core_solver_rows_to_external_rows[i]) != this->m_constraints.end());
|
||||
lp_assert(this->m_constraints.find(this->m_core_solver_rows_to_external_rows[i]) != this->m_constraints.end());
|
||||
auto & constraint = this->m_constraints[this->m_core_solver_rows_to_external_rows[i]];
|
||||
switch (constraint.m_relation) {
|
||||
case Equal:
|
||||
|
@ -504,7 +504,7 @@ template <typename T, typename X> T lp_solver<T, X>::low_bound_shift_for_row(
|
|||
|
||||
template <typename T, typename X> void lp_solver<T, X>::fill_m_b() {
|
||||
for (int i = this->row_count() - 1; i >= 0; i--) {
|
||||
lean_assert(this->m_constraints.find(this->m_core_solver_rows_to_external_rows[i]) != this->m_constraints.end());
|
||||
lp_assert(this->m_constraints.find(this->m_core_solver_rows_to_external_rows[i]) != this->m_constraints.end());
|
||||
unsigned external_i = this->m_core_solver_rows_to_external_rows[i];
|
||||
auto & constraint = this->m_constraints[external_i];
|
||||
this->m_b[i] = constraint.m_rs - low_bound_shift_for_row(external_i);
|
||||
|
@ -542,13 +542,13 @@ template <typename T, typename X> T lp_solver<T, X>::get_column_value_with_core_
|
|||
|
||||
template <typename T, typename X> void lp_solver<T, X>::set_scaled_cost(unsigned j) {
|
||||
// grab original costs but modify it with the column scales
|
||||
lean_assert(j < this->m_column_scale.size());
|
||||
lp_assert(j < this->m_column_scale.size());
|
||||
column_info<T> * ci = this->m_map_from_var_index_to_column_info[this->m_core_solver_columns_to_external_columns[j]];
|
||||
T cost = ci->get_cost();
|
||||
if (ci->is_flipped()){
|
||||
cost *= -1;
|
||||
}
|
||||
lean_assert(ci->is_fixed() == false);
|
||||
lp_assert(ci->is_fixed() == false);
|
||||
this->m_costs[j] = cost * this->m_column_scale[j];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,37 +4,37 @@
|
|||
*/
|
||||
#include <string>
|
||||
#include "util/lp/lp_solver.hpp"
|
||||
template void lean::lp_solver<double, double>::add_constraint(lean::lp_relation, double, unsigned int);
|
||||
template void lean::lp_solver<double, double>::cleanup();
|
||||
template void lean::lp_solver<double, double>::count_slacks_and_artificials();
|
||||
template void lean::lp_solver<double, double>::fill_m_b();
|
||||
template void lean::lp_solver<double, double>::fill_matrix_A_and_init_right_side();
|
||||
template void lean::lp_solver<double, double>::flip_costs();
|
||||
template double lean::lp_solver<double, double>::get_column_cost_value(unsigned int, lean::column_info<double>*) const;
|
||||
template int lean::lp_solver<double, double>::get_column_index_by_name(std::string) const;
|
||||
template double lean::lp_solver<double, double>::get_column_value_with_core_solver(unsigned int, lean::lp_core_solver_base<double, double>*) const;
|
||||
template lean::column_info<double>* lean::lp_solver<double, double>::get_or_create_column_info(unsigned int);
|
||||
template void lean::lp_solver<double, double>::give_symbolic_name_to_column(std::string, unsigned int);
|
||||
template void lean::lp_solver<double, double>::print_statistics_on_A(std::ostream & out);
|
||||
template bool lean::lp_solver<double, double>::problem_is_empty();
|
||||
template void lean::lp_solver<double, double>::scale();
|
||||
template void lean::lp_solver<double, double>::set_scaled_cost(unsigned int);
|
||||
template lean::lp_solver<double, double>::~lp_solver();
|
||||
template void lean::lp_solver<lean::mpq, lean::mpq>::add_constraint(lean::lp_relation, lean::mpq, unsigned int);
|
||||
template void lean::lp_solver<lean::mpq, lean::mpq>::cleanup();
|
||||
template void lean::lp_solver<lean::mpq, lean::mpq>::count_slacks_and_artificials();
|
||||
template void lean::lp_solver<lean::mpq, lean::mpq>::fill_m_b();
|
||||
template void lean::lp_solver<lean::mpq, lean::mpq>::fill_matrix_A_and_init_right_side();
|
||||
template void lean::lp_solver<lean::mpq, lean::mpq>::flip_costs();
|
||||
template lean::mpq lean::lp_solver<lean::mpq, lean::mpq>::get_column_cost_value(unsigned int, lean::column_info<lean::mpq>*) const;
|
||||
template int lean::lp_solver<lean::mpq, lean::mpq>::get_column_index_by_name(std::string) const;
|
||||
template lean::mpq lean::lp_solver<lean::mpq, lean::mpq>::get_column_value_by_name(std::string) const;
|
||||
template lean::mpq lean::lp_solver<lean::mpq, lean::mpq>::get_column_value_with_core_solver(unsigned int, lean::lp_core_solver_base<lean::mpq, lean::mpq>*) const;
|
||||
template lean::column_info<lean::mpq>* lean::lp_solver<lean::mpq, lean::mpq>::get_or_create_column_info(unsigned int);
|
||||
template void lean::lp_solver<lean::mpq, lean::mpq>::give_symbolic_name_to_column(std::string, unsigned int);
|
||||
template void lean::lp_solver<lean::mpq, lean::mpq>::print_statistics_on_A(std::ostream & out);
|
||||
template bool lean::lp_solver<lean::mpq, lean::mpq>::problem_is_empty();
|
||||
template void lean::lp_solver<lean::mpq, lean::mpq>::scale();
|
||||
template void lean::lp_solver<lean::mpq, lean::mpq>::set_scaled_cost(unsigned int);
|
||||
template lean::lp_solver<lean::mpq, lean::mpq>::~lp_solver();
|
||||
template double lean::lp_solver<double, double>::get_column_value_by_name(std::string) const;
|
||||
template void lp::lp_solver<double, double>::add_constraint(lp::lp_relation, double, unsigned int);
|
||||
template void lp::lp_solver<double, double>::cleanup();
|
||||
template void lp::lp_solver<double, double>::count_slacks_and_artificials();
|
||||
template void lp::lp_solver<double, double>::fill_m_b();
|
||||
template void lp::lp_solver<double, double>::fill_matrix_A_and_init_right_side();
|
||||
template void lp::lp_solver<double, double>::flip_costs();
|
||||
template double lp::lp_solver<double, double>::get_column_cost_value(unsigned int, lp::column_info<double>*) const;
|
||||
template int lp::lp_solver<double, double>::get_column_index_by_name(std::string) const;
|
||||
template double lp::lp_solver<double, double>::get_column_value_with_core_solver(unsigned int, lp::lp_core_solver_base<double, double>*) const;
|
||||
template lp::column_info<double>* lp::lp_solver<double, double>::get_or_create_column_info(unsigned int);
|
||||
template void lp::lp_solver<double, double>::give_symbolic_name_to_column(std::string, unsigned int);
|
||||
template void lp::lp_solver<double, double>::print_statistics_on_A(std::ostream & out);
|
||||
template bool lp::lp_solver<double, double>::problem_is_empty();
|
||||
template void lp::lp_solver<double, double>::scale();
|
||||
template void lp::lp_solver<double, double>::set_scaled_cost(unsigned int);
|
||||
template lp::lp_solver<double, double>::~lp_solver();
|
||||
template void lp::lp_solver<lp::mpq, lp::mpq>::add_constraint(lp::lp_relation, lp::mpq, unsigned int);
|
||||
template void lp::lp_solver<lp::mpq, lp::mpq>::cleanup();
|
||||
template void lp::lp_solver<lp::mpq, lp::mpq>::count_slacks_and_artificials();
|
||||
template void lp::lp_solver<lp::mpq, lp::mpq>::fill_m_b();
|
||||
template void lp::lp_solver<lp::mpq, lp::mpq>::fill_matrix_A_and_init_right_side();
|
||||
template void lp::lp_solver<lp::mpq, lp::mpq>::flip_costs();
|
||||
template lp::mpq lp::lp_solver<lp::mpq, lp::mpq>::get_column_cost_value(unsigned int, lp::column_info<lp::mpq>*) const;
|
||||
template int lp::lp_solver<lp::mpq, lp::mpq>::get_column_index_by_name(std::string) const;
|
||||
template lp::mpq lp::lp_solver<lp::mpq, lp::mpq>::get_column_value_by_name(std::string) const;
|
||||
template lp::mpq lp::lp_solver<lp::mpq, lp::mpq>::get_column_value_with_core_solver(unsigned int, lp::lp_core_solver_base<lp::mpq, lp::mpq>*) const;
|
||||
template lp::column_info<lp::mpq>* lp::lp_solver<lp::mpq, lp::mpq>::get_or_create_column_info(unsigned int);
|
||||
template void lp::lp_solver<lp::mpq, lp::mpq>::give_symbolic_name_to_column(std::string, unsigned int);
|
||||
template void lp::lp_solver<lp::mpq, lp::mpq>::print_statistics_on_A(std::ostream & out);
|
||||
template bool lp::lp_solver<lp::mpq, lp::mpq>::problem_is_empty();
|
||||
template void lp::lp_solver<lp::mpq, lp::mpq>::scale();
|
||||
template void lp::lp_solver<lp::mpq, lp::mpq>::set_scaled_cost(unsigned int);
|
||||
template lp::lp_solver<lp::mpq, lp::mpq>::~lp_solver();
|
||||
template double lp::lp_solver<double, double>::get_column_value_by_name(std::string) const;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
#include "util/lp/lp_utils.h"
|
||||
#ifdef lp_for_z3
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
double numeric_traits<double>::g_zero = 0.0;
|
||||
double numeric_traits<double>::g_one = 1.0;
|
||||
}
|
||||
|
|
|
@ -27,14 +27,14 @@ bool contains(const std::unordered_map<A, B> & map, const A& key) {
|
|||
#define LEAN_DEBUG 1
|
||||
#endif
|
||||
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
inline void throw_exception(const std::string & str) {
|
||||
throw default_exception(str);
|
||||
}
|
||||
typedef z3_exception exception;
|
||||
|
||||
#define lean_assert(_x_) { SASSERT(_x_); }
|
||||
inline void lean_unreachable() { lean_assert(false); }
|
||||
#define lp_assert(_x_) { SASSERT(_x_); }
|
||||
inline void lp_unreachable() { lp_assert(false); }
|
||||
template <typename X> inline X zero_of_type() { return numeric_traits<X>::zero(); }
|
||||
template <typename X> inline X one_of_type() { return numeric_traits<X>::one(); }
|
||||
template <typename X> inline bool is_zero(const X & v) { return numeric_traits<X>::is_zero(v); }
|
||||
|
@ -68,8 +68,8 @@ template<typename S, typename T> struct hash<pair<S, T>> {
|
|||
};
|
||||
|
||||
template<>
|
||||
struct hash<lean::numeric_pair<lean::mpq>> {
|
||||
inline size_t operator()(const lean::numeric_pair<lean::mpq> & v) const {
|
||||
struct hash<lp::numeric_pair<lp::mpq>> {
|
||||
inline size_t operator()(const lp::numeric_pair<lp::mpq> & v) const {
|
||||
size_t seed = 0;
|
||||
hash_combine(seed, v.x);
|
||||
hash_combine(seed, v.y);
|
||||
|
@ -91,26 +91,26 @@ struct hash<lean::numeric_pair<lean::mpq>> {
|
|||
#endif
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<lean::mpq> {
|
||||
inline size_t operator()(const lean::mpq & v) const {
|
||||
struct hash<lp::mpq> {
|
||||
inline size_t operator()(const lp::mpq & v) const {
|
||||
return v.hash();
|
||||
}
|
||||
};
|
||||
}
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename X> inline bool precise() { return numeric_traits<X>::precise();}
|
||||
template <typename X> inline X one_of_type() { return numeric_traits<X>::one(); }
|
||||
template <typename X> inline bool is_zero(const X & v) { return numeric_traits<X>::is_zero(v); }
|
||||
template <typename X> inline double get_double(const X & v) { return numeric_traits<X>::get_double(v); }
|
||||
template <typename T> inline T zero_of_type() {return numeric_traits<T>::zero();}
|
||||
inline void throw_exception(std::string str) { throw exception(str); }
|
||||
template <typename T> inline T from_string(std::string const & ) { lean_unreachable();}
|
||||
template <typename T> inline T from_string(std::string const & ) { lp_unreachable();}
|
||||
template <> double inline from_string<double>(std::string const & str) { return atof(str.c_str());}
|
||||
template <> mpq inline from_string<mpq>(std::string const & str) {
|
||||
return mpq(atof(str.c_str()));
|
||||
}
|
||||
|
||||
} // closing lean
|
||||
} // closing lp
|
||||
template <class T>
|
||||
inline void hash_combine(std::size_t & seed, const T & v) {
|
||||
seed ^= std::hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
|
@ -126,8 +126,8 @@ template<typename S, typename T> struct hash<pair<S, T>> {
|
|||
}
|
||||
};
|
||||
template<>
|
||||
struct hash<lean::numeric_pair<lean::mpq>> {
|
||||
inline size_t operator()(const lean::numeric_pair<lean::mpq> & v) const {
|
||||
struct hash<lp::numeric_pair<lp::mpq>> {
|
||||
inline size_t operator()(const lp::numeric_pair<lp::mpq> & v) const {
|
||||
size_t seed = 0;
|
||||
hash_combine(seed, v.x);
|
||||
hash_combine(seed, v.y);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "util/lp/row_eta_matrix.h"
|
||||
#include "util/lp/square_dense_submatrix.h"
|
||||
#include "util/lp/dense_matrix.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
#ifdef LEAN_DEBUG
|
||||
template <typename T, typename X> // print the nr x nc submatrix at the top left corner
|
||||
void print_submatrix(sparse_matrix<T, X> & m, unsigned mr, unsigned nc);
|
||||
|
@ -32,7 +32,7 @@ void print_matrix(sparse_matrix<T, X>& m, std::ostream & out);
|
|||
|
||||
template <typename T, typename X>
|
||||
X dot_product(const vector<T> & a, const vector<X> & b) {
|
||||
lean_assert(a.size() == b.size());
|
||||
lp_assert(a.size() == b.size());
|
||||
auto r = zero_of_type<X>();
|
||||
for (unsigned i = 0; i < a.size(); i++) {
|
||||
r += a[i] * b[i];
|
||||
|
@ -99,7 +99,7 @@ public:
|
|||
m_i = p.apply_reverse(m_i);
|
||||
|
||||
#ifdef LEAN_DEBUG
|
||||
// lean_assert(*this == deb);
|
||||
// lp_assert(*this == deb);
|
||||
#endif
|
||||
}
|
||||
}; // end of one_elem_on_diag
|
||||
|
@ -291,7 +291,7 @@ public:
|
|||
bool need_to_refactor() { return m_refactor_counter >= 200; }
|
||||
|
||||
void adjust_dimension_with_matrix_A() {
|
||||
lean_assert(m_A.row_count() >= m_dim);
|
||||
lp_assert(m_A.row_count() >= m_dim);
|
||||
m_dim = m_A.row_count();
|
||||
m_U.resize(m_dim);
|
||||
m_Q.resize(m_dim);
|
||||
|
@ -305,7 +305,7 @@ public:
|
|||
unsigned m = m_A.row_count();
|
||||
unsigned m_prev = m_U.dimension();
|
||||
|
||||
lean_assert(m_A.column_count() == heading.size());
|
||||
lp_assert(m_A.column_count() == heading.size());
|
||||
|
||||
for (unsigned i = m_prev; i < m; i++) {
|
||||
for (const row_cell<T> & c : m_A.m_rows[i]) {
|
||||
|
@ -321,14 +321,14 @@ public:
|
|||
|
||||
void add_last_rows_to_B(const vector<int> & heading, const std::unordered_set<unsigned> & columns_to_replace) {
|
||||
unsigned m = m_A.row_count();
|
||||
lean_assert(m_A.column_count() == heading.size());
|
||||
lp_assert(m_A.column_count() == heading.size());
|
||||
adjust_dimension_with_matrix_A();
|
||||
m_w_for_extension.resize(m);
|
||||
// At this moment the LU is correct
|
||||
// for B extended by only by ones at the diagonal in the lower right corner
|
||||
|
||||
for (unsigned j :columns_to_replace) {
|
||||
lean_assert(heading[j] >= 0);
|
||||
lp_assert(heading[j] >= 0);
|
||||
replace_column_with_only_change_at_last_rows(j, heading[j]);
|
||||
if (get_status() == LU_status::Degenerated)
|
||||
break;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include <utility>
|
||||
#include "util/debug.h"
|
||||
#include "util/lp/lu.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
#ifdef LEAN_DEBUG
|
||||
template <typename T, typename X> // print the nr x nc submatrix at the top left corner
|
||||
void print_submatrix(sparse_matrix<T, X> & m, unsigned mr, unsigned nc, std::ostream & out) {
|
||||
|
@ -122,29 +122,29 @@ lu<T, X>::lu(static_matrix<T, X> const & A,
|
|||
m_failure(false),
|
||||
m_row_eta_work_vector(A.row_count()),
|
||||
m_refactor_counter(0) {
|
||||
lean_assert(!(numeric_traits<T>::precise() && settings.use_tableau()));
|
||||
lp_assert(!(numeric_traits<T>::precise() && settings.use_tableau()));
|
||||
#ifdef LEAN_DEBUG
|
||||
debug_test_of_basis(A, basis);
|
||||
#endif
|
||||
++m_settings.st().m_num_factorizations;
|
||||
create_initial_factorization();
|
||||
#ifdef LEAN_DEBUG
|
||||
// lean_assert(check_correctness());
|
||||
// lp_assert(check_correctness());
|
||||
#endif
|
||||
}
|
||||
template <typename T, typename X>
|
||||
void lu<T, X>::debug_test_of_basis(static_matrix<T, X> const & A, vector<unsigned> & basis) {
|
||||
std::set<unsigned> set;
|
||||
for (unsigned i = 0; i < A.row_count(); i++) {
|
||||
lean_assert(basis[i]< A.column_count());
|
||||
lp_assert(basis[i]< A.column_count());
|
||||
set.insert(basis[i]);
|
||||
}
|
||||
lean_assert(set.size() == A.row_count());
|
||||
lp_assert(set.size() == A.row_count());
|
||||
}
|
||||
|
||||
template <typename T, typename X>
|
||||
void lu<T, X>::solve_By(indexed_vector<X> & y) {
|
||||
lean_assert(false); // not implemented
|
||||
lp_assert(false); // not implemented
|
||||
// init_vector_y(y);
|
||||
// solve_By_when_y_is_ready(y);
|
||||
}
|
||||
|
@ -277,20 +277,20 @@ void lu<T, X>::solve_yB(vector<T>& y) {
|
|||
|
||||
template <typename T, typename X>
|
||||
void lu<T, X>::solve_yB_indexed(indexed_vector<T>& y) {
|
||||
lean_assert(y.is_OK());
|
||||
lp_assert(y.is_OK());
|
||||
// first solve yU = cb*R(-1)
|
||||
m_R.apply_reverse_from_right_to_T(y); // got y = cb*R(-1)
|
||||
lean_assert(y.is_OK());
|
||||
lp_assert(y.is_OK());
|
||||
m_U.solve_y_U_indexed(y, m_settings); // got y*U=cb*R(-1)
|
||||
lean_assert(y.is_OK());
|
||||
lp_assert(y.is_OK());
|
||||
m_Q.apply_reverse_from_right_to_T(y);
|
||||
lean_assert(y.is_OK());
|
||||
lp_assert(y.is_OK());
|
||||
for (auto e = m_tail.rbegin(); e != m_tail.rend(); ++e) {
|
||||
#ifdef LEAN_DEBUG
|
||||
(*e)->set_number_of_columns(m_dim);
|
||||
#endif
|
||||
(*e)->apply_from_right(y);
|
||||
lean_assert(y.is_OK());
|
||||
lp_assert(y.is_OK());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,8 +304,8 @@ void lu<T, X>::add_delta_to_solution(const vector<T>& yc, vector<T>& y){
|
|||
template <typename T, typename X>
|
||||
void lu<T, X>::add_delta_to_solution_indexed(indexed_vector<T>& y) {
|
||||
// the delta sits in m_y_copy, put result into y
|
||||
lean_assert(y.is_OK());
|
||||
lean_assert(m_y_copy.is_OK());
|
||||
lp_assert(y.is_OK());
|
||||
lp_assert(m_y_copy.is_OK());
|
||||
m_ii.clear();
|
||||
m_ii.resize(y.data_size());
|
||||
for (unsigned i : y.m_index)
|
||||
|
@ -315,7 +315,7 @@ void lu<T, X>::add_delta_to_solution_indexed(indexed_vector<T>& y) {
|
|||
if (m_ii[i] == 0)
|
||||
m_ii.set_value(1, i);
|
||||
}
|
||||
lean_assert(m_ii.is_OK());
|
||||
lp_assert(m_ii.is_OK());
|
||||
y.m_index.clear();
|
||||
|
||||
for (unsigned i : m_ii.m_index) {
|
||||
|
@ -326,7 +326,7 @@ void lu<T, X>::add_delta_to_solution_indexed(indexed_vector<T>& y) {
|
|||
v = zero_of_type<T>();
|
||||
}
|
||||
|
||||
lean_assert(y.is_OK());
|
||||
lp_assert(y.is_OK());
|
||||
}
|
||||
|
||||
template <typename T, typename X>
|
||||
|
@ -343,7 +343,7 @@ void lu<T, X>::find_error_of_yB_indexed(const indexed_vector<T>& y, const vector
|
|||
// it is a non efficient version
|
||||
indexed_vector<T> yc = m_y_copy;
|
||||
yc.m_index.clear();
|
||||
lean_assert(!numeric_traits<T>::precise());
|
||||
lp_assert(!numeric_traits<T>::precise());
|
||||
{
|
||||
|
||||
vector<unsigned> d_basis(y.m_data.size());
|
||||
|
@ -364,10 +364,10 @@ void lu<T, X>::find_error_of_yB_indexed(const indexed_vector<T>& y, const vector
|
|||
}
|
||||
}
|
||||
#endif
|
||||
lean_assert(m_ii.is_OK());
|
||||
lp_assert(m_ii.is_OK());
|
||||
m_ii.clear();
|
||||
m_ii.resize(y.data_size());
|
||||
lean_assert(m_y_copy.is_OK());
|
||||
lp_assert(m_y_copy.is_OK());
|
||||
// put the error into m_y_copy
|
||||
for (auto k : y.m_index) {
|
||||
auto & row = m_A.m_rows[k];
|
||||
|
@ -399,7 +399,7 @@ void lu<T, X>::find_error_of_yB_indexed(const indexed_vector<T>& y, const vector
|
|||
m_y_copy.set_value(v, k);
|
||||
}
|
||||
}
|
||||
lean_assert(m_y_copy.is_OK());
|
||||
lp_assert(m_y_copy.is_OK());
|
||||
|
||||
}
|
||||
|
||||
|
@ -419,12 +419,12 @@ void lu<T, X>::solve_yB_with_error_check_indexed(indexed_vector<T> & y, const ve
|
|||
}
|
||||
return;
|
||||
}
|
||||
lean_assert(m_y_copy.is_OK());
|
||||
lean_assert(y.is_OK());
|
||||
lp_assert(m_y_copy.is_OK());
|
||||
lp_assert(y.is_OK());
|
||||
if (y.m_index.size() * ratio_of_index_size_to_all_size<T>() < m_A.column_count()) {
|
||||
m_y_copy = y;
|
||||
solve_yB_indexed(y);
|
||||
lean_assert(y.is_OK());
|
||||
lp_assert(y.is_OK());
|
||||
if (y.m_index.size() * ratio_of_index_size_to_all_size<T>() >= m_A.column_count()) {
|
||||
find_error_of_yB(m_y_copy.m_data, y.m_data, basis);
|
||||
solve_yB(m_y_copy.m_data);
|
||||
|
@ -436,7 +436,7 @@ void lu<T, X>::solve_yB_with_error_check_indexed(indexed_vector<T> & y, const ve
|
|||
solve_yB_indexed(m_y_copy);
|
||||
add_delta_to_solution_indexed(y);
|
||||
}
|
||||
lean_assert(m_y_copy.is_OK());
|
||||
lp_assert(m_y_copy.is_OK());
|
||||
} else {
|
||||
solve_yB_with_error_check(y.m_data, basis);
|
||||
y.restore_index_and_clean_from_data();
|
||||
|
@ -489,7 +489,7 @@ template <typename T, typename X>
|
|||
void lu<T, X>::perform_transformations_on_w(indexed_vector<T>& w) {
|
||||
apply_lp_list_to_w(w);
|
||||
m_Q.apply_reverse_from_left(w);
|
||||
// TBD does not compile: lean_assert(numeric_traits<T>::precise() || check_vector_for_small_values(w, m_settings));
|
||||
// TBD does not compile: lp_assert(numeric_traits<T>::precise() || check_vector_for_small_values(w, m_settings));
|
||||
}
|
||||
|
||||
// see Chvatal 24.3
|
||||
|
@ -503,7 +503,7 @@ template <typename T, typename X>
|
|||
void lu<T, X>::apply_lp_list_to_w(indexed_vector<T> & w) {
|
||||
for (unsigned i = 0; i < m_tail.size(); i++) {
|
||||
m_tail[i]->apply_from_left_to_T(w, m_settings);
|
||||
// TBD does not compile: lean_assert(check_vector_for_small_values(w, m_settings));
|
||||
// TBD does not compile: lp_assert(check_vector_for_small_values(w, m_settings));
|
||||
}
|
||||
}
|
||||
template <typename T, typename X>
|
||||
|
@ -595,7 +595,7 @@ void lu<T, X>::check_apply_lp_lists_to_w(T * w) {
|
|||
permutation_matrix<T, X> qr = m_Q.get_reverse();
|
||||
apply_to_vector(qr, w);
|
||||
for (int i = m_dim - 1; i >= 0; i--) {
|
||||
lean_assert(abs(w[i] - w[i]) < 0.0000001);
|
||||
lp_assert(abs(w[i] - w[i]) < 0.0000001);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -640,7 +640,7 @@ bool lu<T, X>::is_correct(const vector<unsigned>& basis) {
|
|||
#ifdef LEAN_DEBUG
|
||||
template <typename T, typename X>
|
||||
dense_matrix<T, X> lu<T, X>::tail_product() {
|
||||
lean_assert(tail_size() > 0);
|
||||
lp_assert(tail_size() > 0);
|
||||
dense_matrix<T, X> left_side = permutation_matrix<T, X>(m_dim);
|
||||
for (unsigned i = 0; i < tail_size(); i++) {
|
||||
matrix<T, X>* lp = get_lp_matrix(i);
|
||||
|
@ -690,8 +690,8 @@ template <typename T, typename X>
|
|||
bool lu<T, X>::all_columns_and_rows_are_active() {
|
||||
unsigned i = m_dim;
|
||||
while (i--) {
|
||||
lean_assert(m_U.col_is_active(i));
|
||||
lean_assert(m_U.row_is_active(i));
|
||||
lp_assert(m_U.col_is_active(i));
|
||||
lp_assert(m_U.row_is_active(i));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -733,9 +733,9 @@ void lu<T, X>::create_initial_factorization(){
|
|||
}
|
||||
}
|
||||
if (j == m_dim) {
|
||||
// TBD does not compile: lean_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings));
|
||||
// lean_assert(is_correct());
|
||||
// lean_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings));
|
||||
// TBD does not compile: lp_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings));
|
||||
// lp_assert(is_correct());
|
||||
// lp_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings));
|
||||
return;
|
||||
}
|
||||
j++;
|
||||
|
@ -748,12 +748,12 @@ void lu<T, X>::create_initial_factorization(){
|
|||
}
|
||||
}
|
||||
m_dense_LU->update_parent_matrix(m_settings);
|
||||
lean_assert(m_dense_LU->is_L_matrix());
|
||||
lp_assert(m_dense_LU->is_L_matrix());
|
||||
m_dense_LU->conjugate_by_permutation(m_Q);
|
||||
push_matrix_to_tail(m_dense_LU);
|
||||
m_refactor_counter = 0;
|
||||
// lean_assert(is_correct());
|
||||
// lean_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings));
|
||||
// lp_assert(is_correct());
|
||||
// lp_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings));
|
||||
}
|
||||
|
||||
template <typename T, typename X>
|
||||
|
@ -780,7 +780,7 @@ void lu<T, X>::scan_last_row_to_work_vector(unsigned lowest_row_of_the_bump) {
|
|||
vector<indexed_value<T>> & last_row_vec = m_U.get_row_values(m_U.adjust_row(lowest_row_of_the_bump));
|
||||
for (auto & iv : last_row_vec) {
|
||||
if (is_zero(iv.m_value)) continue;
|
||||
lean_assert(!m_settings.abs_val_is_smaller_than_drop_tolerance(iv.m_value));
|
||||
lp_assert(!m_settings.abs_val_is_smaller_than_drop_tolerance(iv.m_value));
|
||||
unsigned adjusted_col = m_U.adjust_column_inverse(iv.m_index);
|
||||
if (adjusted_col < lowest_row_of_the_bump) {
|
||||
m_row_eta_work_vector.set_value(-iv.m_value, adjusted_col);
|
||||
|
@ -801,14 +801,14 @@ void lu<T, X>::pivot_and_solve_the_system(unsigned replaced_column, unsigned low
|
|||
vector<indexed_value<T>> & row = m_U.get_row_values(aj);
|
||||
for (auto & iv : row) {
|
||||
unsigned col = m_U.adjust_column_inverse(iv.m_index);
|
||||
lean_assert(col >= j || numeric_traits<T>::is_zero(iv.m_value));
|
||||
lp_assert(col >= j || numeric_traits<T>::is_zero(iv.m_value));
|
||||
if (col == j) continue;
|
||||
if (numeric_traits<T>::is_zero(iv.m_value)) {
|
||||
continue;
|
||||
}
|
||||
// the -v is for solving the system ( to zero the last row), and +v is for pivoting
|
||||
T delta = col < lowest_row_of_the_bump? -v * iv.m_value: v * iv.m_value;
|
||||
lean_assert(numeric_traits<T>::is_zero(delta) == false);
|
||||
lp_assert(numeric_traits<T>::is_zero(delta) == false);
|
||||
|
||||
|
||||
|
||||
|
@ -885,15 +885,15 @@ void lu<T, X>::replace_column(T pivot_elem_for_checking, indexed_vector<T> & w,
|
|||
push_matrix_to_tail(row_eta);
|
||||
}
|
||||
calculate_Lwave_Pwave_for_bump(replaced_column, lowest_row_of_the_bump);
|
||||
// lean_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings));
|
||||
// lean_assert(w.is_OK() && m_row_eta_work_vector.is_OK());
|
||||
// lp_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings));
|
||||
// lp_assert(w.is_OK() && m_row_eta_work_vector.is_OK());
|
||||
}
|
||||
template <typename T, typename X>
|
||||
void lu<T, X>::calculate_Lwave_Pwave_for_bump(unsigned replaced_column, unsigned lowest_row_of_the_bump){
|
||||
T diagonal_elem;
|
||||
if (replaced_column < lowest_row_of_the_bump) {
|
||||
diagonal_elem = m_row_eta_work_vector[lowest_row_of_the_bump];
|
||||
// lean_assert(m_row_eta_work_vector.is_OK());
|
||||
// lp_assert(m_row_eta_work_vector.is_OK());
|
||||
m_U.set_row_from_work_vector_and_clean_work_vector_not_adjusted(m_U.adjust_row(lowest_row_of_the_bump), m_row_eta_work_vector, m_settings);
|
||||
} else {
|
||||
diagonal_elem = m_U(lowest_row_of_the_bump, lowest_row_of_the_bump); // todo - get it more efficiently
|
||||
|
@ -904,7 +904,7 @@ void lu<T, X>::calculate_Lwave_Pwave_for_bump(unsigned replaced_column, unsigned
|
|||
}
|
||||
|
||||
calculate_Lwave_Pwave_for_last_row(lowest_row_of_the_bump, diagonal_elem);
|
||||
// lean_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings));
|
||||
// lp_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings));
|
||||
}
|
||||
|
||||
template <typename T, typename X>
|
||||
|
@ -930,8 +930,8 @@ void init_factorization(lu<T, X>* & factorization, static_matrix<T, X> & m_A, ve
|
|||
#ifdef LEAN_DEBUG
|
||||
template <typename T, typename X>
|
||||
dense_matrix<T, X> get_B(lu<T, X>& f, const vector<unsigned>& basis) {
|
||||
lean_assert(basis.size() == f.dimension());
|
||||
lean_assert(basis.size() == f.m_U.dimension());
|
||||
lp_assert(basis.size() == f.dimension());
|
||||
lp_assert(basis.size() == f.m_U.dimension());
|
||||
dense_matrix<T, X> B(f.dimension(), f.dimension());
|
||||
for (unsigned i = 0; i < f.dimension(); i++)
|
||||
for (unsigned j = 0; j < f.dimension(); j++)
|
||||
|
|
|
@ -8,56 +8,56 @@
|
|||
#include "util/vector.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/lp/lu.hpp"
|
||||
template double lean::dot_product<double, double>(vector<double> const&, vector<double> const&);
|
||||
template lean::lu<double, double>::lu(lean::static_matrix<double, double> const&, vector<unsigned int>&, lean::lp_settings&);
|
||||
template void lean::lu<double, double>::push_matrix_to_tail(lean::tail_matrix<double, double>*);
|
||||
template void lean::lu<double, double>::replace_column(double, lean::indexed_vector<double>&, unsigned);
|
||||
template void lean::lu<double, double>::solve_Bd(unsigned int, lean::indexed_vector<double>&, lean::indexed_vector<double>&);
|
||||
template lean::lu<double, double>::~lu();
|
||||
template void lean::lu<lean::mpq, lean::mpq>::push_matrix_to_tail(lean::tail_matrix<lean::mpq, lean::mpq>*);
|
||||
template void lean::lu<lean::mpq, lean::mpq>::solve_Bd(unsigned int, lean::indexed_vector<lean::mpq>&, lean::indexed_vector<lean::mpq>&);
|
||||
template lean::lu<lean::mpq, lean::mpq>::~lu();
|
||||
template void lean::lu<lean::mpq, lean::numeric_pair<lean::mpq> >::push_matrix_to_tail(lean::tail_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >*);
|
||||
template void lean::lu<lean::mpq, lean::numeric_pair<lean::mpq> >::solve_Bd(unsigned int, lean::indexed_vector<lean::mpq>&, lean::indexed_vector<lean::mpq>&);
|
||||
template lean::lu<lean::mpq, lean::numeric_pair<lean::mpq> >::~lu();
|
||||
template lean::mpq lean::dot_product<lean::mpq, lean::mpq>(vector<lean::mpq > const&, vector<lean::mpq > const&);
|
||||
template void lean::init_factorization<double, double>(lean::lu<double, double>*&, lean::static_matrix<double, double>&, vector<unsigned int>&, lean::lp_settings&);
|
||||
template void lean::init_factorization<lean::mpq, lean::mpq>(lean::lu<lean::mpq, lean::mpq>*&, lean::static_matrix<lean::mpq, lean::mpq>&, vector<unsigned int>&, lean::lp_settings&);
|
||||
template void lean::init_factorization<lean::mpq, lean::numeric_pair<lean::mpq> >(lean::lu<lean::mpq, lean::numeric_pair<lean::mpq> >*&, lean::static_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >&, vector<unsigned int>&, lean::lp_settings&);
|
||||
template double lp::dot_product<double, double>(vector<double> const&, vector<double> const&);
|
||||
template lp::lu<double, double>::lu(lp::static_matrix<double, double> const&, vector<unsigned int>&, lp::lp_settings&);
|
||||
template void lp::lu<double, double>::push_matrix_to_tail(lp::tail_matrix<double, double>*);
|
||||
template void lp::lu<double, double>::replace_column(double, lp::indexed_vector<double>&, unsigned);
|
||||
template void lp::lu<double, double>::solve_Bd(unsigned int, lp::indexed_vector<double>&, lp::indexed_vector<double>&);
|
||||
template lp::lu<double, double>::~lu();
|
||||
template void lp::lu<lp::mpq, lp::mpq>::push_matrix_to_tail(lp::tail_matrix<lp::mpq, lp::mpq>*);
|
||||
template void lp::lu<lp::mpq, lp::mpq>::solve_Bd(unsigned int, lp::indexed_vector<lp::mpq>&, lp::indexed_vector<lp::mpq>&);
|
||||
template lp::lu<lp::mpq, lp::mpq>::~lu();
|
||||
template void lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::push_matrix_to_tail(lp::tail_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >*);
|
||||
template void lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_Bd(unsigned int, lp::indexed_vector<lp::mpq>&, lp::indexed_vector<lp::mpq>&);
|
||||
template lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::~lu();
|
||||
template lp::mpq lp::dot_product<lp::mpq, lp::mpq>(vector<lp::mpq > const&, vector<lp::mpq > const&);
|
||||
template void lp::init_factorization<double, double>(lp::lu<double, double>*&, lp::static_matrix<double, double>&, vector<unsigned int>&, lp::lp_settings&);
|
||||
template void lp::init_factorization<lp::mpq, lp::mpq>(lp::lu<lp::mpq, lp::mpq>*&, lp::static_matrix<lp::mpq, lp::mpq>&, vector<unsigned int>&, lp::lp_settings&);
|
||||
template void lp::init_factorization<lp::mpq, lp::numeric_pair<lp::mpq> >(lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >*&, lp::static_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >&, vector<unsigned int>&, lp::lp_settings&);
|
||||
#ifdef LEAN_DEBUG
|
||||
template void lean::print_matrix<double, double>(lean::sparse_matrix<double, double>&, std::ostream & out);
|
||||
template void lean::print_matrix<lean::mpq, lean::mpq>(lean::static_matrix<lean::mpq, lean::mpq>&, std::ostream&);
|
||||
template void lean::print_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >(lean::static_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >&, std::ostream&);
|
||||
template void lean::print_matrix<double, double>(lean::static_matrix<double, double>&, std::ostream & out);
|
||||
template bool lean::lu<double, double>::is_correct(const vector<unsigned>& basis);
|
||||
template bool lean::lu<lean::mpq, lean::numeric_pair<lean::mpq> >::is_correct( vector<unsigned int> const &);
|
||||
template lean::dense_matrix<double, double> lean::get_B<double, double>(lean::lu<double, double>&, const vector<unsigned>& basis);
|
||||
template lean::dense_matrix<lean::mpq, lean::mpq> lean::get_B<lean::mpq, lean::mpq>(lean::lu<lean::mpq, lean::mpq>&, vector<unsigned int> const&);
|
||||
template void lp::print_matrix<double, double>(lp::sparse_matrix<double, double>&, std::ostream & out);
|
||||
template void lp::print_matrix<lp::mpq, lp::mpq>(lp::static_matrix<lp::mpq, lp::mpq>&, std::ostream&);
|
||||
template void lp::print_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >(lp::static_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >&, std::ostream&);
|
||||
template void lp::print_matrix<double, double>(lp::static_matrix<double, double>&, std::ostream & out);
|
||||
template bool lp::lu<double, double>::is_correct(const vector<unsigned>& basis);
|
||||
template bool lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::is_correct( vector<unsigned int> const &);
|
||||
template lp::dense_matrix<double, double> lp::get_B<double, double>(lp::lu<double, double>&, const vector<unsigned>& basis);
|
||||
template lp::dense_matrix<lp::mpq, lp::mpq> lp::get_B<lp::mpq, lp::mpq>(lp::lu<lp::mpq, lp::mpq>&, vector<unsigned int> const&);
|
||||
|
||||
#endif
|
||||
|
||||
template bool lean::lu<double, double>::pivot_the_row(int); // NOLINT
|
||||
template void lean::lu<double, double>::init_vector_w(unsigned int, lean::indexed_vector<double>&);
|
||||
template void lean::lu<double, double>::solve_By(vector<double>&);
|
||||
template void lean::lu<double, double>::solve_By_when_y_is_ready_for_X(vector<double>&);
|
||||
template void lean::lu<double, double>::solve_yB_with_error_check(vector<double>&, const vector<unsigned>& basis);
|
||||
template void lean::lu<double, double>::solve_yB_with_error_check_indexed(lean::indexed_vector<double>&, vector<int> const&, const vector<unsigned> & basis, const lp_settings&);
|
||||
template void lean::lu<lean::mpq, lean::mpq>::replace_column(lean::mpq, lean::indexed_vector<lean::mpq>&, unsigned);
|
||||
template void lean::lu<lean::mpq, lean::mpq>::solve_By(vector<lean::mpq >&);
|
||||
template void lean::lu<lean::mpq, lean::mpq>::solve_By_when_y_is_ready_for_X(vector<lean::mpq >&);
|
||||
template void lean::lu<lean::mpq, lean::mpq>::solve_yB_with_error_check(vector<lean::mpq >&, const vector<unsigned>& basis);
|
||||
template void lean::lu<lean::mpq, lean::mpq>::solve_yB_with_error_check_indexed(lean::indexed_vector<lean::mpq>&, vector< int > const&, const vector<unsigned> & basis, const lp_settings&);
|
||||
template void lean::lu<lean::mpq, lean::numeric_pair<lean::mpq> >::solve_yB_with_error_check_indexed(lean::indexed_vector<lean::mpq>&, vector< int > const&, const vector<unsigned> & basis, const lp_settings&);
|
||||
template void lean::lu<lean::mpq, lean::numeric_pair<lean::mpq> >::init_vector_w(unsigned int, lean::indexed_vector<lean::mpq>&);
|
||||
template void lean::lu<lean::mpq, lean::numeric_pair<lean::mpq> >::replace_column(lean::mpq, lean::indexed_vector<lean::mpq>&, unsigned);
|
||||
template void lean::lu<lean::mpq, lean::numeric_pair<lean::mpq> >::solve_Bd_faster(unsigned int, lean::indexed_vector<lean::mpq>&);
|
||||
template void lean::lu<lean::mpq, lean::numeric_pair<lean::mpq> >::solve_By(vector<lean::numeric_pair<lean::mpq> >&);
|
||||
template void lean::lu<lean::mpq, lean::numeric_pair<lean::mpq> >::solve_By_when_y_is_ready_for_X(vector<lean::numeric_pair<lean::mpq> >&);
|
||||
template void lean::lu<lean::mpq, lean::numeric_pair<lean::mpq> >::solve_yB_with_error_check(vector<lean::mpq >&, const vector<unsigned>& basis);
|
||||
template void lean::lu<lean::mpq, lean::mpq>::solve_By(lean::indexed_vector<lean::mpq>&);
|
||||
template void lean::lu<double, double>::solve_By(lean::indexed_vector<double>&);
|
||||
template void lean::lu<double, double>::solve_yB_indexed(lean::indexed_vector<double>&);
|
||||
template void lean::lu<lean::mpq, lean::mpq>::solve_yB_indexed(lean::indexed_vector<lean::mpq>&);
|
||||
template void lean::lu<lean::mpq, lean::numeric_pair<lean::mpq> >::solve_yB_indexed(lean::indexed_vector<lean::mpq>&);
|
||||
template void lean::lu<lean::mpq, lean::mpq>::solve_By_for_T_indexed_only(lean::indexed_vector<lean::mpq>&, lean::lp_settings const&);
|
||||
template void lean::lu<double, double>::solve_By_for_T_indexed_only(lean::indexed_vector<double>&, lean::lp_settings const&);
|
||||
template bool lp::lu<double, double>::pivot_the_row(int); // NOLINT
|
||||
template void lp::lu<double, double>::init_vector_w(unsigned int, lp::indexed_vector<double>&);
|
||||
template void lp::lu<double, double>::solve_By(vector<double>&);
|
||||
template void lp::lu<double, double>::solve_By_when_y_is_ready_for_X(vector<double>&);
|
||||
template void lp::lu<double, double>::solve_yB_with_error_check(vector<double>&, const vector<unsigned>& basis);
|
||||
template void lp::lu<double, double>::solve_yB_with_error_check_indexed(lp::indexed_vector<double>&, vector<int> const&, const vector<unsigned> & basis, const lp_settings&);
|
||||
template void lp::lu<lp::mpq, lp::mpq>::replace_column(lp::mpq, lp::indexed_vector<lp::mpq>&, unsigned);
|
||||
template void lp::lu<lp::mpq, lp::mpq>::solve_By(vector<lp::mpq >&);
|
||||
template void lp::lu<lp::mpq, lp::mpq>::solve_By_when_y_is_ready_for_X(vector<lp::mpq >&);
|
||||
template void lp::lu<lp::mpq, lp::mpq>::solve_yB_with_error_check(vector<lp::mpq >&, const vector<unsigned>& basis);
|
||||
template void lp::lu<lp::mpq, lp::mpq>::solve_yB_with_error_check_indexed(lp::indexed_vector<lp::mpq>&, vector< int > const&, const vector<unsigned> & basis, const lp_settings&);
|
||||
template void lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_yB_with_error_check_indexed(lp::indexed_vector<lp::mpq>&, vector< int > const&, const vector<unsigned> & basis, const lp_settings&);
|
||||
template void lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::init_vector_w(unsigned int, lp::indexed_vector<lp::mpq>&);
|
||||
template void lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::replace_column(lp::mpq, lp::indexed_vector<lp::mpq>&, unsigned);
|
||||
template void lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_Bd_faster(unsigned int, lp::indexed_vector<lp::mpq>&);
|
||||
template void lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_By(vector<lp::numeric_pair<lp::mpq> >&);
|
||||
template void lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_By_when_y_is_ready_for_X(vector<lp::numeric_pair<lp::mpq> >&);
|
||||
template void lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_yB_with_error_check(vector<lp::mpq >&, const vector<unsigned>& basis);
|
||||
template void lp::lu<lp::mpq, lp::mpq>::solve_By(lp::indexed_vector<lp::mpq>&);
|
||||
template void lp::lu<double, double>::solve_By(lp::indexed_vector<double>&);
|
||||
template void lp::lu<double, double>::solve_yB_indexed(lp::indexed_vector<double>&);
|
||||
template void lp::lu<lp::mpq, lp::mpq>::solve_yB_indexed(lp::indexed_vector<lp::mpq>&);
|
||||
template void lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_yB_indexed(lp::indexed_vector<lp::mpq>&);
|
||||
template void lp::lu<lp::mpq, lp::mpq>::solve_By_for_T_indexed_only(lp::indexed_vector<lp::mpq>&, lp::lp_settings const&);
|
||||
template void lp::lu<double, double>::solve_By_for_T_indexed_only(lp::indexed_vector<double>&, lp::lp_settings const&);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "util/vector.h"
|
||||
#include <string>
|
||||
#include "util/lp/lp_settings.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
// used for debugging purposes only
|
||||
template <typename T, typename X>
|
||||
class matrix {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <cmath>
|
||||
#include <string>
|
||||
#include "util/lp/matrix.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T, typename X>
|
||||
bool matrix<T, X>::is_equal(const matrix<T, X>& other) {
|
||||
if (other.row_count() != row_count() || other.column_count() != column_count())
|
||||
|
@ -58,8 +58,8 @@ unsigned get_width_of_column(unsigned j, vector<vector<std::string>> & A) {
|
|||
unsigned r = 0;
|
||||
for (unsigned i = 0; i < A.size(); i++) {
|
||||
vector<std::string> & t = A[i];
|
||||
std::string str= t[j];
|
||||
unsigned s = str.size();
|
||||
std::string str = t[j];
|
||||
unsigned s = static_cast<unsigned>(str.size());
|
||||
if (r < s) {
|
||||
r = s;
|
||||
}
|
||||
|
@ -69,8 +69,8 @@ unsigned get_width_of_column(unsigned j, vector<vector<std::string>> & A) {
|
|||
|
||||
void print_matrix_with_widths(vector<vector<std::string>> & A, vector<unsigned> & ws, std::ostream & out) {
|
||||
for (unsigned i = 0; i < A.size(); i++) {
|
||||
for (unsigned j = 0; j < A[i].size(); j++) {
|
||||
print_blanks(ws[j] - A[i][j].size(), out);
|
||||
for (unsigned j = 0; j < static_cast<unsigned>(A[i].size()); j++) {
|
||||
print_blanks(ws[j] - static_cast<unsigned>(A[i][j].size()), out);
|
||||
out << A[i][j] << " ";
|
||||
}
|
||||
out << std::endl;
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
#include "util/lp/matrix.hpp"
|
||||
#include "util/lp/static_matrix.h"
|
||||
#include <string>
|
||||
template void lean::print_matrix<double, double>(lean::matrix<double, double> const*, std::ostream & out);
|
||||
template bool lean::matrix<double, double>::is_equal(lean::matrix<double, double> const&);
|
||||
template void lean::print_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >(lean::matrix<lean::mpq, lean::numeric_pair<lean::mpq> > const *, std::basic_ostream<char, std::char_traits<char> > &);
|
||||
template void lean::print_matrix<lean::mpq, lean::mpq>(lean::matrix<lean::mpq, lean::mpq> const*, std::ostream&);
|
||||
template bool lean::matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::is_equal(lean::matrix<lean::mpq, lean::numeric_pair<lean::mpq> > const&);
|
||||
template bool lean::matrix<lean::mpq, lean::mpq>::is_equal(lean::matrix<lean::mpq, lean::mpq> const&);
|
||||
template void lp::print_matrix<double, double>(lp::matrix<double, double> const*, std::ostream & out);
|
||||
template bool lp::matrix<double, double>::is_equal(lp::matrix<double, double> const&);
|
||||
template void lp::print_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >(lp::matrix<lp::mpq, lp::numeric_pair<lp::mpq> > const *, std::basic_ostream<char, std::char_traits<char> > &);
|
||||
template void lp::print_matrix<lp::mpq, lp::mpq>(lp::matrix<lp::mpq, lp::mpq> const*, std::ostream&);
|
||||
template bool lp::matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::is_equal(lp::matrix<lp::mpq, lp::numeric_pair<lp::mpq> > const&);
|
||||
template bool lp::matrix<lp::mpq, lp::mpq>::is_equal(lp::matrix<lp::mpq, lp::mpq> const&);
|
||||
#endif
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "util/lp/lar_solver.h"
|
||||
#include "util/lp/lp_utils.h"
|
||||
#include "util/lp/lp_solver.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
inline bool my_white_space(const char & a) {
|
||||
return a == ' ' || a == '\t';
|
||||
}
|
||||
|
@ -160,9 +160,9 @@ class mps_reader {
|
|||
if (m_line[i] == ' ')
|
||||
break;
|
||||
}
|
||||
lean_assert(m_line.size() >= offset);
|
||||
lean_assert(m_line.size() >> i);
|
||||
lean_assert(i >= offset);
|
||||
lp_assert(m_line.size() >= offset);
|
||||
lp_assert(m_line.size() >> i);
|
||||
lp_assert(i >= offset);
|
||||
return m_line.substr(offset, i - offset);
|
||||
}
|
||||
|
||||
|
@ -497,7 +497,7 @@ class mps_reader {
|
|||
|
||||
void create_or_update_bound() {
|
||||
const unsigned name_offset = 14;
|
||||
lean_assert(m_line.size() >= 14);
|
||||
lp_assert(m_line.size() >= 14);
|
||||
vector<std::string> bound_string = split_and_trim(m_line.substr(name_offset, m_line.size()));
|
||||
|
||||
if (bound_string.size() == 0) {
|
||||
|
@ -603,7 +603,7 @@ class mps_reader {
|
|||
}
|
||||
|
||||
for (auto s : row_with_range->m_row_columns) {
|
||||
lean_assert(m_columns.find(s.first) != m_columns.end());
|
||||
lp_assert(m_columns.find(s.first) != m_columns.end());
|
||||
other_bound_range_row->m_row_columns[s.first] = s.second;
|
||||
}
|
||||
}
|
||||
|
@ -679,7 +679,7 @@ class mps_reader {
|
|||
if (row->m_name != m_cost_row_name) {
|
||||
solver->add_constraint(get_relation_from_row(row->m_type), row->m_right_side, row->m_index);
|
||||
for (auto s : row->m_row_columns) {
|
||||
lean_assert(m_columns.find(s.first) != m_columns.end());
|
||||
lp_assert(m_columns.find(s.first) != m_columns.end());
|
||||
solver->set_row_column_coefficient(row->m_index, m_columns[s.first]->m_index, s.second);
|
||||
}
|
||||
} else {
|
||||
|
@ -714,7 +714,7 @@ class mps_reader {
|
|||
void set_solver_cost(row * row, lp_solver<T, X> *solver) {
|
||||
for (auto s : row->m_row_columns) {
|
||||
std::string name = s.first;
|
||||
lean_assert(m_columns.find(name) != m_columns.end());
|
||||
lp_assert(m_columns.find(name) != m_columns.end());
|
||||
mps_reader::column * col = m_columns[name];
|
||||
solver->set_cost_for_column(col->m_index, s.second);
|
||||
}
|
||||
|
@ -723,7 +723,7 @@ class mps_reader {
|
|||
public:
|
||||
|
||||
void set_message_stream(std::ostream * o) {
|
||||
lean_assert(o != nullptr);
|
||||
lp_assert(o != nullptr);
|
||||
m_message_stream = o;
|
||||
}
|
||||
vector<std::string> column_names() {
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
/*
|
||||
Copyright (c) 2017 Microsoft Corporation
|
||||
Author: Lev Nachmanson
|
||||
Author: Nikolaj Bjorner
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "util/lp/lar_solver.h"
|
||||
#include "util/lp/nra_solver.h"
|
||||
#include "nlsat/nlsat_solver.h"
|
||||
|
@ -14,47 +13,45 @@
|
|||
|
||||
namespace nra {
|
||||
|
||||
struct mon_eq {
|
||||
mon_eq(lp::var_index v, unsigned sz, lp::var_index const* vs):
|
||||
m_v(v), m_vs(sz, vs) {}
|
||||
lp::var_index m_v;
|
||||
svector<lp::var_index> m_vs;
|
||||
};
|
||||
|
||||
struct solver::imp {
|
||||
lean::lar_solver& s;
|
||||
reslimit& m_limit; // TBD: extract from lar_solver
|
||||
params_ref m_params; // TBD: pass from outside
|
||||
lp::lar_solver& s;
|
||||
reslimit& m_limit;
|
||||
params_ref m_params;
|
||||
u_map<polynomial::var> m_lp2nl; // map from lar_solver variables to nlsat::solver variables
|
||||
nlsat::solver m_nlsat;
|
||||
scoped_ptr<nlsat::solver> m_nlsat;
|
||||
vector<mon_eq> m_monomials;
|
||||
unsigned_vector m_monomials_lim;
|
||||
mutable std::unordered_map<lp::var_index, rational> m_variable_values; // current model
|
||||
|
||||
struct mon_eq {
|
||||
mon_eq(lean::var_index v, unsigned sz, lean::var_index const* vs):
|
||||
m_v(v), m_vs(sz, vs) {}
|
||||
lean::var_index m_v;
|
||||
svector<lean::var_index> m_vs;
|
||||
};
|
||||
|
||||
vector<mon_eq> m_monomials;
|
||||
unsigned_vector m_lim;
|
||||
mutable std::unordered_map<lean::var_index, rational> m_variable_values; // current model
|
||||
|
||||
imp(lean::lar_solver& s, reslimit& lim, params_ref const& p):
|
||||
imp(lp::lar_solver& s, reslimit& lim, params_ref const& p):
|
||||
s(s),
|
||||
m_limit(lim),
|
||||
m_params(p),
|
||||
m_nlsat(m_limit, m_params) {
|
||||
m_params(p) {
|
||||
}
|
||||
|
||||
bool need_check() {
|
||||
return !m_monomials.empty() && !check_assignments();
|
||||
}
|
||||
|
||||
void add(lean::var_index v, unsigned sz, lean::var_index const* vs) {
|
||||
void add(lp::var_index v, unsigned sz, lp::var_index const* vs) {
|
||||
m_monomials.push_back(mon_eq(v, sz, vs));
|
||||
}
|
||||
|
||||
void push() {
|
||||
m_lim.push_back(m_monomials.size());
|
||||
m_monomials_lim.push_back(m_monomials.size());
|
||||
}
|
||||
|
||||
void pop(unsigned n) {
|
||||
if (n == 0) return;
|
||||
m_monomials.shrink(m_lim[m_lim.size() - n]);
|
||||
m_lim.shrink(m_lim.size() - n);
|
||||
m_monomials.shrink(m_monomials_lim[m_monomials_lim.size() - n]);
|
||||
m_monomials_lim.shrink(m_monomials_lim.size() - n);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -79,7 +76,6 @@ namespace nra {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief one-shot nlsat check.
|
||||
A one shot checker is the least functionality that can
|
||||
|
@ -89,10 +85,11 @@ namespace nra {
|
|||
with the remaining solver.
|
||||
|
||||
TBD: use partial model from lra_solver to prime the state of nlsat_solver.
|
||||
TBD: explore more incremental ways of applying nlsat (using assumptions)
|
||||
*/
|
||||
lbool check(lean::explanation_t& ex) {
|
||||
lbool check(lp::explanation_t& ex) {
|
||||
SASSERT(need_check());
|
||||
m_nlsat.reset();
|
||||
m_nlsat = alloc(nlsat::solver, m_limit, m_params);
|
||||
m_lp2nl.reset();
|
||||
vector<nlsat::assumption, false> core;
|
||||
|
||||
|
@ -107,14 +104,14 @@ namespace nra {
|
|||
}
|
||||
// TBD: add variable bounds?
|
||||
|
||||
lbool r = m_nlsat.check();
|
||||
TRACE("arith", m_nlsat.display(tout << r << "\n"););
|
||||
lbool r = m_nlsat->check();
|
||||
TRACE("arith", m_nlsat->display(tout << r << "\n"););
|
||||
switch (r) {
|
||||
case l_true:
|
||||
break;
|
||||
case l_false:
|
||||
ex.reset();
|
||||
m_nlsat.get_core(core);
|
||||
m_nlsat->get_core(core);
|
||||
for (auto c : core) {
|
||||
unsigned idx = static_cast<unsigned>(static_cast<imp*>(c) - this);
|
||||
ex.push_back(std::pair<rational, unsigned>(rational(1), idx));
|
||||
|
@ -129,7 +126,7 @@ namespace nra {
|
|||
}
|
||||
|
||||
void add_monomial_eq(mon_eq const& m) {
|
||||
polynomial::manager& pm = m_nlsat.pm();
|
||||
polynomial::manager& pm = m_nlsat->pm();
|
||||
svector<polynomial::var> vars;
|
||||
for (auto v : m.m_vs) {
|
||||
vars.push_back(lp2nl(v));
|
||||
|
@ -143,13 +140,13 @@ namespace nra {
|
|||
polynomial::polynomial_ref p(pm.mk_polynomial(2, coeffs.c_ptr(), mls), pm);
|
||||
polynomial::polynomial* ps[1] = { p };
|
||||
bool even[1] = { false };
|
||||
nlsat::literal lit = m_nlsat.mk_ineq_literal(nlsat::atom::kind::EQ, 1, ps, even);
|
||||
m_nlsat.mk_clause(1, &lit, 0);
|
||||
nlsat::literal lit = m_nlsat->mk_ineq_literal(nlsat::atom::kind::EQ, 1, ps, even);
|
||||
m_nlsat->mk_clause(1, &lit, 0);
|
||||
}
|
||||
|
||||
void add_constraint(unsigned idx) {
|
||||
auto& c = s.get_constraint(idx);
|
||||
auto& pm = m_nlsat.pm();
|
||||
auto& pm = m_nlsat->pm();
|
||||
auto k = c.m_kind;
|
||||
auto rhs = c.m_right_side;
|
||||
auto lhs = c.get_left_side_coefficients();
|
||||
|
@ -169,45 +166,48 @@ namespace nra {
|
|||
polynomial::polynomial* ps[1] = { p };
|
||||
bool is_even[1] = { false };
|
||||
nlsat::literal lit;
|
||||
switch (k) {
|
||||
case lean::lconstraint_kind::LE:
|
||||
lit = ~m_nlsat.mk_ineq_literal(nlsat::atom::kind::GT, 1, ps, is_even);
|
||||
break;
|
||||
case lean::lconstraint_kind::GE:
|
||||
lit = ~m_nlsat.mk_ineq_literal(nlsat::atom::kind::LT, 1, ps, is_even);
|
||||
break;
|
||||
case lean::lconstraint_kind::LT:
|
||||
lit = m_nlsat.mk_ineq_literal(nlsat::atom::kind::LT, 1, ps, is_even);
|
||||
break;
|
||||
case lean::lconstraint_kind::GT:
|
||||
lit = m_nlsat.mk_ineq_literal(nlsat::atom::kind::GT, 1, ps, is_even);
|
||||
break;
|
||||
case lean::lconstraint_kind::EQ:
|
||||
lit = m_nlsat.mk_ineq_literal(nlsat::atom::kind::EQ, 1, ps, is_even);
|
||||
break;
|
||||
}
|
||||
|
||||
nlsat::assumption a = this + idx;
|
||||
m_nlsat.mk_clause(1, &lit, a);
|
||||
switch (k) {
|
||||
case lp::lconstraint_kind::LE:
|
||||
lit = ~m_nlsat->mk_ineq_literal(nlsat::atom::kind::GT, 1, ps, is_even);
|
||||
break;
|
||||
case lp::lconstraint_kind::GE:
|
||||
lit = ~m_nlsat->mk_ineq_literal(nlsat::atom::kind::LT, 1, ps, is_even);
|
||||
break;
|
||||
case lp::lconstraint_kind::LT:
|
||||
lit = m_nlsat->mk_ineq_literal(nlsat::atom::kind::LT, 1, ps, is_even);
|
||||
break;
|
||||
case lp::lconstraint_kind::GT:
|
||||
lit = m_nlsat->mk_ineq_literal(nlsat::atom::kind::GT, 1, ps, is_even);
|
||||
break;
|
||||
case lp::lconstraint_kind::EQ:
|
||||
lit = m_nlsat->mk_ineq_literal(nlsat::atom::kind::EQ, 1, ps, is_even);
|
||||
break;
|
||||
}
|
||||
m_nlsat->mk_clause(1, &lit, a);
|
||||
}
|
||||
|
||||
bool is_int(lean::var_index v) {
|
||||
// TBD: is it s.column_is_integer(v), if then the function should take a var_index and not unsigned; s.is_int(v);
|
||||
return false;
|
||||
bool is_int(lp::var_index v) {
|
||||
return s.var_is_int(v);
|
||||
}
|
||||
|
||||
|
||||
polynomial::var lp2nl(lean::var_index v) {
|
||||
polynomial::var lp2nl(lp::var_index v) {
|
||||
polynomial::var r;
|
||||
if (!m_lp2nl.find(v, r)) {
|
||||
r = m_nlsat.mk_var(is_int(v));
|
||||
r = m_nlsat->mk_var(is_int(v));
|
||||
m_lp2nl.insert(v, r);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
nlsat::anum const& value(lean::var_index v) const {
|
||||
return m_nlsat.value(m_lp2nl.find(v));
|
||||
nlsat::anum const& value(lp::var_index v) const {
|
||||
return m_nlsat->value(m_lp2nl.find(v));
|
||||
}
|
||||
|
||||
nlsat::anum_manager& am() {
|
||||
return m_nlsat->am();
|
||||
}
|
||||
|
||||
std::ostream& display(std::ostream& out) const {
|
||||
|
@ -220,10 +220,9 @@ namespace nra {
|
|||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
solver::solver(lean::lar_solver& s, reslimit& lim, params_ref const& p) {
|
||||
solver::solver(lp::lar_solver& s, reslimit& lim, params_ref const& p) {
|
||||
m_imp = alloc(imp, s, lim, p);
|
||||
}
|
||||
|
||||
|
@ -231,11 +230,11 @@ namespace nra {
|
|||
dealloc(m_imp);
|
||||
}
|
||||
|
||||
void solver::add_monomial(lean::var_index v, unsigned sz, lean::var_index const* vs) {
|
||||
void solver::add_monomial(lp::var_index v, unsigned sz, lp::var_index const* vs) {
|
||||
m_imp->add(v, sz, vs);
|
||||
}
|
||||
|
||||
lbool solver::check(lean::explanation_t& ex) {
|
||||
lbool solver::check(lp::explanation_t& ex) {
|
||||
return m_imp->check(ex);
|
||||
}
|
||||
|
||||
|
@ -255,8 +254,13 @@ namespace nra {
|
|||
return m_imp->display(out);
|
||||
}
|
||||
|
||||
nlsat::anum const& solver::value(lean::var_index v) const {
|
||||
nlsat::anum const& solver::value(lp::var_index v) const {
|
||||
return m_imp->value(v);
|
||||
}
|
||||
|
||||
nlsat::anum_manager& solver::am() {
|
||||
return m_imp->am();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (c) 2017 Microsoft Corporation
|
||||
Author: Lev Nachmanson
|
||||
Author: Nikolaj Bjorner
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
@ -10,7 +10,7 @@
|
|||
#include "util/params.h"
|
||||
#include "nlsat/nlsat_solver.h"
|
||||
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
class lar_solver;
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ namespace nra {
|
|||
|
||||
public:
|
||||
|
||||
solver(lean::lar_solver& s, reslimit& lim, params_ref const& p = params_ref());
|
||||
solver(lp::lar_solver& s, reslimit& lim, params_ref const& p = params_ref());
|
||||
|
||||
~solver();
|
||||
|
||||
|
@ -33,13 +33,13 @@ namespace nra {
|
|||
\brief Add a definition v = vs[0]*vs[1]*...*vs[sz-1]
|
||||
The variable v is equal to the product of variables vs.
|
||||
*/
|
||||
void add_monomial(lean::var_index v, unsigned sz, lean::var_index const* vs);
|
||||
void add_monomial(lp::var_index v, unsigned sz, lp::var_index const* vs);
|
||||
|
||||
/*
|
||||
\brief Check feasiblity of linear constraints augmented by polynomial definitions
|
||||
that are added.
|
||||
*/
|
||||
lbool check(lean::explanation_t& ex);
|
||||
lbool check(lp::explanation_t& ex);
|
||||
|
||||
/*
|
||||
\brief determine whether nra check is needed.
|
||||
|
@ -49,7 +49,9 @@ namespace nra {
|
|||
/*
|
||||
\brief Access model.
|
||||
*/
|
||||
nlsat::anum const& value(lean::var_index v) const;
|
||||
nlsat::anum const& value(lp::var_index v) const;
|
||||
|
||||
nlsat::anum_manager& am();
|
||||
|
||||
/*
|
||||
\brief push and pop scope.
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
// include "util/numerics/mpq.h"
|
||||
// include "util/numerics/numeric_traits.h"
|
||||
#endif
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
#ifdef lp_for_z3 // rename rationals
|
||||
typedef rational mpq;
|
||||
#else
|
||||
typedef lean::mpq mpq;
|
||||
typedef lp::mpq mpq;
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -73,8 +73,8 @@ template <typename X, typename Y>
|
|||
struct convert_struct {
|
||||
static X convert(const Y & y){ return X(y);}
|
||||
static bool is_epsilon_small(const X & x, const double & y) { return std::abs(numeric_traits<X>::get_double(x)) < y; }
|
||||
static bool below_bound_numeric(const X &, const X &, const Y &) { /*lean_unreachable();*/ return false;}
|
||||
static bool above_bound_numeric(const X &, const X &, const Y &) { /*lean_unreachable();*/ return false; }
|
||||
static bool below_bound_numeric(const X &, const X &, const Y &) { /*lp_unreachable();*/ return false;}
|
||||
static bool above_bound_numeric(const X &, const X &, const Y &) { /*lp_unreachable();*/ return false; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -144,7 +144,7 @@ struct numeric_pair {
|
|||
}
|
||||
|
||||
numeric_pair operator/(const numeric_pair &) const {
|
||||
// lean_unreachable();
|
||||
// lp_unreachable();
|
||||
}
|
||||
|
||||
|
||||
|
@ -153,7 +153,7 @@ struct numeric_pair {
|
|||
}
|
||||
|
||||
numeric_pair operator*(const numeric_pair & /*a*/) const {
|
||||
// lean_unreachable();
|
||||
// lp_unreachable();
|
||||
}
|
||||
|
||||
numeric_pair& operator+=(const numeric_pair & a) {
|
||||
|
@ -188,7 +188,7 @@ struct numeric_pair {
|
|||
return numeric_pair(-x, -y);
|
||||
}
|
||||
|
||||
static bool precize() { return lean::numeric_traits<T>::precize();}
|
||||
static bool precize() { return lp::numeric_traits<T>::precize();}
|
||||
|
||||
bool is_zero() const { return x.is_zero() && y.is_zero(); }
|
||||
|
||||
|
@ -199,6 +199,11 @@ struct numeric_pair {
|
|||
std::string to_string() const {
|
||||
return std::string("(") + T_to_string(x) + ", " + T_to_string(y) + ")";
|
||||
}
|
||||
|
||||
bool is_int() const {
|
||||
return x.is_int() && y.is_zero();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -225,15 +230,15 @@ numeric_pair<T> operator/(const numeric_pair<T> & r, const X & a) {
|
|||
}
|
||||
|
||||
// template <numeric_pair, typename T> bool precise() { return numeric_traits<T>::precise();}
|
||||
template <typename T> double get_double(const lean::numeric_pair<T> & ) { /* lean_unreachable(); */ return 0;}
|
||||
template <typename T> double get_double(const lp::numeric_pair<T> & ) { /* lp_unreachable(); */ return 0;}
|
||||
template <typename T>
|
||||
class numeric_traits<lean::numeric_pair<T>> {
|
||||
class numeric_traits<lp::numeric_pair<T>> {
|
||||
public:
|
||||
static bool precise() { return numeric_traits<T>::precise();}
|
||||
static lean::numeric_pair<T> zero() { return lean::numeric_pair<T>(numeric_traits<T>::zero(), numeric_traits<T>::zero()); }
|
||||
static bool is_zero(const lean::numeric_pair<T> & v) { return numeric_traits<T>::is_zero(v.x) && numeric_traits<T>::is_zero(v.y); }
|
||||
static double get_double(const lean::numeric_pair<T> & v){ return numeric_traits<T>::get_double(v.x); } // just return the double of the first coordinate
|
||||
static double one() { /*lean_unreachable();*/ return 0;}
|
||||
static lp::numeric_pair<T> zero() { return lp::numeric_pair<T>(numeric_traits<T>::zero(), numeric_traits<T>::zero()); }
|
||||
static bool is_zero(const lp::numeric_pair<T> & v) { return numeric_traits<T>::is_zero(v.x) && numeric_traits<T>::is_zero(v.y); }
|
||||
static double get_double(const lp::numeric_pair<T> & v){ return numeric_traits<T>::get_double(v.x); } // just return the double of the first coordinate
|
||||
static double one() { /*lp_unreachable();*/ return 0;}
|
||||
static bool is_pos(const numeric_pair<T> &p) {
|
||||
return numeric_traits<T>::is_pos(p.x) ||
|
||||
(numeric_traits<T>::is_zero(p.x) && numeric_traits<T>::is_pos(p.y));
|
||||
|
@ -263,11 +268,11 @@ struct convert_struct<numeric_pair<T>, double> {
|
|||
return convert_struct<T, double>::is_epsilon_small(p.x, eps) && convert_struct<T, double>::is_epsilon_small(p.y, eps);
|
||||
}
|
||||
static bool below_bound_numeric(const numeric_pair<T> &, const numeric_pair<T> &, const double &) {
|
||||
// lean_unreachable();
|
||||
// lp_unreachable();
|
||||
return false;
|
||||
}
|
||||
static bool above_bound_numeric(const numeric_pair<T> &, const numeric_pair<T> &, const double &) {
|
||||
// lean_unreachable();
|
||||
// lp_unreachable();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
@ -324,4 +329,26 @@ struct convert_struct<double, double> {
|
|||
template <typename X> bool is_epsilon_small(const X & v, const double &eps) { return convert_struct<X, double>::is_epsilon_small(v, eps);}
|
||||
template <typename X> bool below_bound_numeric(const X & x, const X & bound, const double& eps) { return convert_struct<X, double>::below_bound_numeric(x, bound, eps);}
|
||||
template <typename X> bool above_bound_numeric(const X & x, const X & bound, const double& eps) { return convert_struct<X, double>::above_bound_numeric(x, bound, eps);}
|
||||
template <typename T> T floor(const numeric_pair<T> & r) {
|
||||
if (r.x.is_int()) {
|
||||
if (r.y.is_nonneg()) {
|
||||
return r.x;
|
||||
}
|
||||
return r.x - mpq::one();
|
||||
}
|
||||
|
||||
return floor(r.x);
|
||||
}
|
||||
|
||||
template <typename T> T ceil(const numeric_pair<T> & r) {
|
||||
if (r.x.is_int()) {
|
||||
if (r.y.is_nonpos()) {
|
||||
return r.x;
|
||||
}
|
||||
return r.x + mpq::one();
|
||||
}
|
||||
|
||||
return ceil(r.x);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include "util/lp/lp_settings.h"
|
||||
#include "util/lp/matrix.h"
|
||||
#include "util/lp/tail_matrix.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
#ifdef LEAN_DEBUG
|
||||
inline bool is_even(int k) { return (k/2)*2 == k; }
|
||||
#endif
|
||||
|
@ -86,7 +86,7 @@ class permutation_matrix : public tail_matrix<T, X> {
|
|||
void apply_reverse_from_right_to_X(vector<X> & w);
|
||||
|
||||
void set_val(unsigned i, unsigned pi) {
|
||||
lean_assert(i < size() && pi < size()); m_permutation[i] = pi; m_rev[pi] = i; }
|
||||
lp_assert(i < size() && pi < size()); m_permutation[i] = pi; m_rev[pi] = i; }
|
||||
|
||||
void transpose_from_left(unsigned i, unsigned j);
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
#include "util/vector.h"
|
||||
#include "util/lp/permutation_matrix.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T, typename X> permutation_matrix<T, X>::permutation_matrix(unsigned length): m_permutation(length), m_rev(length), m_T_buffer(length), m_X_buffer(length) {
|
||||
for (unsigned i = 0; i < length; i++) { // do not change the direction of the loop because of the vectorization bug in clang3.3
|
||||
m_permutation[i] = m_rev[i] = i;
|
||||
|
@ -50,7 +50,7 @@ void permutation_matrix<T, X>::apply_from_left(vector<X> & w, lp_settings & ) {
|
|||
// deb.apply_from_left(deb_w);
|
||||
#endif
|
||||
// std::cout << " apply_from_left " << std::endl;
|
||||
lean_assert(m_X_buffer.size() == w.size());
|
||||
lp_assert(m_X_buffer.size() == w.size());
|
||||
unsigned i = size();
|
||||
while (i-- > 0) {
|
||||
m_X_buffer[i] = w[m_permutation[i]];
|
||||
|
@ -60,7 +60,7 @@ void permutation_matrix<T, X>::apply_from_left(vector<X> & w, lp_settings & ) {
|
|||
w[i] = m_X_buffer[i];
|
||||
}
|
||||
#ifdef LEAN_DEBUG
|
||||
// lean_assert(vectors_are_equal<L>(deb_w, w, row_count()));
|
||||
// lp_assert(vectors_are_equal<L>(deb_w, w, row_count()));
|
||||
// delete [] deb_w;
|
||||
#endif
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ template <typename T, typename X> void permutation_matrix<T, X>::apply_from_righ
|
|||
// T * deb_w = clone_vector<T>(w, row_count());
|
||||
// deb.apply_from_right(deb_w);
|
||||
#endif
|
||||
lean_assert(m_T_buffer.size() == w.size());
|
||||
lp_assert(m_T_buffer.size() == w.size());
|
||||
for (unsigned i = 0; i < size(); i++) {
|
||||
m_T_buffer[i] = w[m_rev[i]];
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ template <typename T, typename X> void permutation_matrix<T, X>::apply_from_righ
|
|||
w[i] = m_T_buffer[i];
|
||||
}
|
||||
#ifdef LEAN_DEBUG
|
||||
// lean_assert(vectors_are_equal<T>(deb_w, w, row_count()));
|
||||
// lp_assert(vectors_are_equal<T>(deb_w, w, row_count()));
|
||||
// delete [] deb_w;
|
||||
#endif
|
||||
}
|
||||
|
@ -117,9 +117,9 @@ template <typename T, typename X> void permutation_matrix<T, X>::apply_from_righ
|
|||
unsigned pj = m_permutation[j];
|
||||
w.set_value(buffer[i], pj);
|
||||
}
|
||||
lean_assert(w.is_OK());
|
||||
lp_assert(w.is_OK());
|
||||
#ifdef LEAN_DEBUG
|
||||
lean_assert(vectors_are_equal(wcopy, w.m_data));
|
||||
lp_assert(vectors_are_equal(wcopy, w.m_data));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -166,7 +166,7 @@ void permutation_matrix<T, X>::apply_reverse_from_left(indexed_vector<L> & w) {
|
|||
w.m_index[i] = j;
|
||||
}
|
||||
#ifdef LEAN_DEBUG
|
||||
// lean_assert(vectors_are_equal<L>(deb_w, w.m_data, row_count()));
|
||||
// lp_assert(vectors_are_equal<L>(deb_w, w.m_data, row_count()));
|
||||
// delete [] deb_w;
|
||||
#endif
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ void permutation_matrix<T, X>::apply_reverse_from_left(indexed_vector<L> & w) {
|
|||
template <typename T, typename X>
|
||||
void permutation_matrix<T, X>::apply_reverse_from_left_to_T(vector<T> & w) {
|
||||
// the result will be w = p(-1) * w
|
||||
lean_assert(m_T_buffer.size() == w.size());
|
||||
lp_assert(m_T_buffer.size() == w.size());
|
||||
unsigned i = size();
|
||||
while (i-- > 0) {
|
||||
m_T_buffer[m_permutation[i]] = w[i];
|
||||
|
@ -187,7 +187,7 @@ void permutation_matrix<T, X>::apply_reverse_from_left_to_T(vector<T> & w) {
|
|||
template <typename T, typename X>
|
||||
void permutation_matrix<T, X>::apply_reverse_from_left_to_X(vector<X> & w) {
|
||||
// the result will be w = p(-1) * w
|
||||
lean_assert(m_X_buffer.size() == w.size());
|
||||
lp_assert(m_X_buffer.size() == w.size());
|
||||
unsigned i = size();
|
||||
while (i-- > 0) {
|
||||
m_X_buffer[m_permutation[i]] = w[i];
|
||||
|
@ -201,7 +201,7 @@ void permutation_matrix<T, X>::apply_reverse_from_left_to_X(vector<X> & w) {
|
|||
template <typename T, typename X>
|
||||
void permutation_matrix<T, X>::apply_reverse_from_right_to_T(vector<T> & w) {
|
||||
// the result will be w = w * p(-1)
|
||||
lean_assert(m_T_buffer.size() == w.size());
|
||||
lp_assert(m_T_buffer.size() == w.size());
|
||||
unsigned i = size();
|
||||
while (i-- > 0) {
|
||||
m_T_buffer[i] = w[m_permutation[i]];
|
||||
|
@ -219,7 +219,7 @@ void permutation_matrix<T, X>::apply_reverse_from_right_to_T(indexed_vector<T> &
|
|||
// vector<T> wcopy(w.m_data);
|
||||
// apply_reverse_from_right_to_T(wcopy);
|
||||
#endif
|
||||
lean_assert(w.is_OK());
|
||||
lp_assert(w.is_OK());
|
||||
vector<T> tmp;
|
||||
vector<unsigned> tmp_index(w.m_index);
|
||||
for (auto i : w.m_index) {
|
||||
|
@ -232,15 +232,15 @@ void permutation_matrix<T, X>::apply_reverse_from_right_to_T(indexed_vector<T> &
|
|||
w.set_value(tmp[k], m_rev[j]);
|
||||
}
|
||||
|
||||
// lean_assert(w.is_OK());
|
||||
// lean_assert(vectors_are_equal(w.m_data, wcopy));
|
||||
// lp_assert(w.is_OK());
|
||||
// lp_assert(vectors_are_equal(w.m_data, wcopy));
|
||||
}
|
||||
|
||||
|
||||
template <typename T, typename X>
|
||||
void permutation_matrix<T, X>::apply_reverse_from_right_to_X(vector<X> & w) {
|
||||
// the result will be w = w * p(-1)
|
||||
lean_assert(m_X_buffer.size() == w.size());
|
||||
lp_assert(m_X_buffer.size() == w.size());
|
||||
unsigned i = size();
|
||||
while (i-- > 0) {
|
||||
m_X_buffer[i] = w[m_permutation[i]];
|
||||
|
@ -253,7 +253,7 @@ void permutation_matrix<T, X>::apply_reverse_from_right_to_X(vector<X> & w) {
|
|||
|
||||
template <typename T, typename X> void permutation_matrix<T, X>::transpose_from_left(unsigned i, unsigned j) {
|
||||
// the result will be this = (i,j)*this
|
||||
lean_assert(i < size() && j < size() && i != j);
|
||||
lp_assert(i < size() && j < size() && i != j);
|
||||
auto pi = m_rev[i];
|
||||
auto pj = m_rev[j];
|
||||
set_val(pi, j);
|
||||
|
@ -262,7 +262,7 @@ template <typename T, typename X> void permutation_matrix<T, X>::transpose_from_
|
|||
|
||||
template <typename T, typename X> void permutation_matrix<T, X>::transpose_from_right(unsigned i, unsigned j) {
|
||||
// the result will be this = this * (i,j)
|
||||
lean_assert(i < size() && j < size() && i != j);
|
||||
lp_assert(i < size() && j < size() && i != j);
|
||||
auto pi = m_permutation[i];
|
||||
auto pj = m_permutation[j];
|
||||
set_val(i, pj);
|
||||
|
@ -271,7 +271,7 @@ template <typename T, typename X> void permutation_matrix<T, X>::transpose_from_
|
|||
|
||||
template <typename T, typename X> void permutation_matrix<T, X>::multiply_by_permutation_from_left(permutation_matrix<T, X> & p) {
|
||||
m_work_array = m_permutation;
|
||||
lean_assert(p.size() == size());
|
||||
lp_assert(p.size() == size());
|
||||
unsigned i = size();
|
||||
while (i-- > 0) {
|
||||
set_val(i, m_work_array[p[i]]); // we have m(P)*m(Q) = m(QP), where m is the matrix of the permutation
|
||||
|
@ -281,7 +281,7 @@ template <typename T, typename X> void permutation_matrix<T, X>::multiply_by_per
|
|||
// this is multiplication in the matrix sense
|
||||
template <typename T, typename X> void permutation_matrix<T, X>::multiply_by_permutation_from_right(permutation_matrix<T, X> & p) {
|
||||
m_work_array = m_permutation;
|
||||
lean_assert(p.size() == size());
|
||||
lp_assert(p.size() == size());
|
||||
unsigned i = size();
|
||||
while (i-- > 0)
|
||||
set_val(i, p[m_work_array[i]]); // we have m(P)*m(Q) = m(QP), where m is the matrix of the permutation
|
||||
|
@ -289,7 +289,7 @@ template <typename T, typename X> void permutation_matrix<T, X>::multiply_by_per
|
|||
}
|
||||
|
||||
template <typename T, typename X> void permutation_matrix<T, X>::multiply_by_reverse_from_right(permutation_matrix<T, X> & q){ // todo : condensed permutations ?
|
||||
lean_assert(q.size() == size());
|
||||
lp_assert(q.size() == size());
|
||||
m_work_array = m_permutation;
|
||||
// the result is this = this*q(-1)
|
||||
unsigned i = size();
|
||||
|
|
|
@ -6,50 +6,50 @@
|
|||
#include "util/vector.h"
|
||||
#include "util/lp/permutation_matrix.hpp"
|
||||
#include "util/lp/numeric_pair.h"
|
||||
template void lean::permutation_matrix<double, double>::apply_from_right(vector<double>&);
|
||||
template void lean::permutation_matrix<double, double>::init(unsigned int);
|
||||
template void lean::permutation_matrix<lean::mpq, lean::mpq>::init(unsigned int);
|
||||
template void lean::permutation_matrix<lean::mpq, lean::numeric_pair<lean::mpq>>::init(unsigned int);
|
||||
template bool lean::permutation_matrix<double, double>::is_identity() const;
|
||||
template void lean::permutation_matrix<double, double>::multiply_by_permutation_from_left(lean::permutation_matrix<double, double>&);
|
||||
template void lean::permutation_matrix<double, double>::multiply_by_permutation_reverse_from_left(lean::permutation_matrix<double, double>&);
|
||||
template void lean::permutation_matrix<double, double>::multiply_by_reverse_from_right(lean::permutation_matrix<double, double>&);
|
||||
template lean::permutation_matrix<double, double>::permutation_matrix(unsigned int, vector<unsigned int> const&);
|
||||
template void lean::permutation_matrix<double, double>::transpose_from_left(unsigned int, unsigned int);
|
||||
template void lp::permutation_matrix<double, double>::apply_from_right(vector<double>&);
|
||||
template void lp::permutation_matrix<double, double>::init(unsigned int);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::mpq>::init(unsigned int);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::numeric_pair<lp::mpq>>::init(unsigned int);
|
||||
template bool lp::permutation_matrix<double, double>::is_identity() const;
|
||||
template void lp::permutation_matrix<double, double>::multiply_by_permutation_from_left(lp::permutation_matrix<double, double>&);
|
||||
template void lp::permutation_matrix<double, double>::multiply_by_permutation_reverse_from_left(lp::permutation_matrix<double, double>&);
|
||||
template void lp::permutation_matrix<double, double>::multiply_by_reverse_from_right(lp::permutation_matrix<double, double>&);
|
||||
template lp::permutation_matrix<double, double>::permutation_matrix(unsigned int, vector<unsigned int> const&);
|
||||
template void lp::permutation_matrix<double, double>::transpose_from_left(unsigned int, unsigned int);
|
||||
|
||||
template void lean::permutation_matrix<lean::mpq, lean::mpq>::apply_from_right(vector<lean::mpq>&);
|
||||
template bool lean::permutation_matrix<lean::mpq, lean::mpq>::is_identity() const;
|
||||
template void lean::permutation_matrix<lean::mpq, lean::mpq>::multiply_by_permutation_from_left(lean::permutation_matrix<lean::mpq, lean::mpq>&);
|
||||
template void lean::permutation_matrix<lean::mpq, lean::mpq>::multiply_by_permutation_from_right(lean::permutation_matrix<lean::mpq, lean::mpq>&);
|
||||
template void lean::permutation_matrix<lean::mpq, lean::mpq>::multiply_by_permutation_reverse_from_left(lean::permutation_matrix<lean::mpq, lean::mpq>&);
|
||||
template void lean::permutation_matrix<lean::mpq, lean::mpq>::multiply_by_reverse_from_right(lean::permutation_matrix<lean::mpq, lean::mpq>&);
|
||||
template lean::permutation_matrix<lean::mpq, lean::mpq>::permutation_matrix(unsigned int);
|
||||
template void lean::permutation_matrix<lean::mpq, lean::mpq>::transpose_from_left(unsigned int, unsigned int);
|
||||
template void lean::permutation_matrix<lean::mpq, lean::mpq>::transpose_from_right(unsigned int, unsigned int);
|
||||
template void lean::permutation_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::apply_from_right(vector<lean::mpq>&);
|
||||
template bool lean::permutation_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::is_identity() const;
|
||||
template void lean::permutation_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::multiply_by_permutation_from_left(lean::permutation_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >&);
|
||||
template void lean::permutation_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::multiply_by_permutation_from_right(lean::permutation_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >&);
|
||||
template void lean::permutation_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::multiply_by_permutation_reverse_from_left(lean::permutation_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >&);
|
||||
template void lean::permutation_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::multiply_by_reverse_from_right(lean::permutation_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >&);
|
||||
template lean::permutation_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::permutation_matrix(unsigned int);
|
||||
template void lean::permutation_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::transpose_from_left(unsigned int, unsigned int);
|
||||
template void lean::permutation_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::transpose_from_right(unsigned int, unsigned int);
|
||||
template void lean::permutation_matrix<double, double>::apply_reverse_from_left<double>(lean::indexed_vector<double>&);
|
||||
template void lean::permutation_matrix<double, double>::apply_reverse_from_left_to_T(vector<double>&);
|
||||
template void lean::permutation_matrix<double, double>::apply_reverse_from_right_to_T(vector<double>&);
|
||||
template void lean::permutation_matrix<double, double>::transpose_from_right(unsigned int, unsigned int);
|
||||
template void lean::permutation_matrix<lean::mpq, lean::mpq>::apply_reverse_from_left<lean::mpq>(lean::indexed_vector<lean::mpq>&);
|
||||
template void lean::permutation_matrix<lean::mpq, lean::mpq>::apply_reverse_from_left_to_T(vector<lean::mpq>&);
|
||||
template void lean::permutation_matrix<lean::mpq, lean::mpq>::apply_reverse_from_right_to_T(vector<lean::mpq>&);
|
||||
template void lean::permutation_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::apply_reverse_from_left<lean::mpq>(lean::indexed_vector<lean::mpq>&);
|
||||
template void lean::permutation_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::apply_reverse_from_left_to_T(vector<lean::mpq>&);
|
||||
template void lean::permutation_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::apply_reverse_from_right_to_T(vector<lean::mpq >&);
|
||||
template void lean::permutation_matrix<double, double>::multiply_by_permutation_from_right(lean::permutation_matrix<double, double>&);
|
||||
template lean::permutation_matrix<double, double>::permutation_matrix(unsigned int);
|
||||
template void lean::permutation_matrix<double, double>::apply_reverse_from_left_to_X(vector<double> &);
|
||||
template void lean::permutation_matrix< lean::mpq, lean::mpq>::apply_reverse_from_left_to_X(vector<lean::mpq> &);
|
||||
template void lean::permutation_matrix< lean::mpq, lean::numeric_pair< lean::mpq> >::apply_reverse_from_left_to_X(vector<lean::numeric_pair< lean::mpq>> &);
|
||||
template void lean::permutation_matrix<double, double>::apply_reverse_from_right_to_T(lean::indexed_vector<double>&);
|
||||
template void lean::permutation_matrix<lean::mpq, lean::mpq>::apply_reverse_from_right_to_T(lean::indexed_vector<lean::mpq>&);
|
||||
template void lean::permutation_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::apply_reverse_from_right_to_T(lean::indexed_vector<lean::mpq>&);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::mpq>::apply_from_right(vector<lp::mpq>&);
|
||||
template bool lp::permutation_matrix<lp::mpq, lp::mpq>::is_identity() const;
|
||||
template void lp::permutation_matrix<lp::mpq, lp::mpq>::multiply_by_permutation_from_left(lp::permutation_matrix<lp::mpq, lp::mpq>&);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::mpq>::multiply_by_permutation_from_right(lp::permutation_matrix<lp::mpq, lp::mpq>&);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::mpq>::multiply_by_permutation_reverse_from_left(lp::permutation_matrix<lp::mpq, lp::mpq>&);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::mpq>::multiply_by_reverse_from_right(lp::permutation_matrix<lp::mpq, lp::mpq>&);
|
||||
template lp::permutation_matrix<lp::mpq, lp::mpq>::permutation_matrix(unsigned int);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::mpq>::transpose_from_left(unsigned int, unsigned int);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::mpq>::transpose_from_right(unsigned int, unsigned int);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::apply_from_right(vector<lp::mpq>&);
|
||||
template bool lp::permutation_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::is_identity() const;
|
||||
template void lp::permutation_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::multiply_by_permutation_from_left(lp::permutation_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >&);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::multiply_by_permutation_from_right(lp::permutation_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >&);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::multiply_by_permutation_reverse_from_left(lp::permutation_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >&);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::multiply_by_reverse_from_right(lp::permutation_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >&);
|
||||
template lp::permutation_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::permutation_matrix(unsigned int);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::transpose_from_left(unsigned int, unsigned int);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::transpose_from_right(unsigned int, unsigned int);
|
||||
template void lp::permutation_matrix<double, double>::apply_reverse_from_left<double>(lp::indexed_vector<double>&);
|
||||
template void lp::permutation_matrix<double, double>::apply_reverse_from_left_to_T(vector<double>&);
|
||||
template void lp::permutation_matrix<double, double>::apply_reverse_from_right_to_T(vector<double>&);
|
||||
template void lp::permutation_matrix<double, double>::transpose_from_right(unsigned int, unsigned int);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::mpq>::apply_reverse_from_left<lp::mpq>(lp::indexed_vector<lp::mpq>&);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::mpq>::apply_reverse_from_left_to_T(vector<lp::mpq>&);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::mpq>::apply_reverse_from_right_to_T(vector<lp::mpq>&);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::apply_reverse_from_left<lp::mpq>(lp::indexed_vector<lp::mpq>&);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::apply_reverse_from_left_to_T(vector<lp::mpq>&);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::apply_reverse_from_right_to_T(vector<lp::mpq >&);
|
||||
template void lp::permutation_matrix<double, double>::multiply_by_permutation_from_right(lp::permutation_matrix<double, double>&);
|
||||
template lp::permutation_matrix<double, double>::permutation_matrix(unsigned int);
|
||||
template void lp::permutation_matrix<double, double>::apply_reverse_from_left_to_X(vector<double> &);
|
||||
template void lp::permutation_matrix< lp::mpq, lp::mpq>::apply_reverse_from_left_to_X(vector<lp::mpq> &);
|
||||
template void lp::permutation_matrix< lp::mpq, lp::numeric_pair< lp::mpq> >::apply_reverse_from_left_to_X(vector<lp::numeric_pair< lp::mpq>> &);
|
||||
template void lp::permutation_matrix<double, double>::apply_reverse_from_right_to_T(lp::indexed_vector<double>&);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::mpq>::apply_reverse_from_right_to_T(lp::indexed_vector<lp::mpq>&);
|
||||
template void lp::permutation_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::apply_reverse_from_right_to_T(lp::indexed_vector<lp::mpq>&);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
Author: Lev Nachmanson
|
||||
*/
|
||||
#include "util/lp/lar_solver.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
quick_xplain::quick_xplain(vector<std::pair<mpq, constraint_index>> & explanation, const lar_solver & ls, lar_solver & qsol) :
|
||||
m_explanation(explanation),
|
||||
m_parent_solver(ls),
|
||||
|
@ -29,7 +29,7 @@ void quick_xplain::copy_constraint_and_add_constraint_vars(const lar_constraint&
|
|||
|
||||
bool quick_xplain::infeasible() {
|
||||
m_qsol.solve();
|
||||
return m_qsol.get_status() == INFEASIBLE;
|
||||
return m_qsol.get_status() == lp_status::INFEASIBLE;
|
||||
}
|
||||
|
||||
// u - unexplored constraints
|
||||
|
@ -56,7 +56,7 @@ void quick_xplain::minimize(const vector<unsigned>& u) {
|
|||
}
|
||||
}
|
||||
if (m > 0) {
|
||||
lean_assert(m_qsol.constraint_stack_size() >= initial_stack_size);
|
||||
lp_assert(m_qsol.constraint_stack_size() >= initial_stack_size);
|
||||
m_qsol.pop(m_qsol.constraint_stack_size() - initial_stack_size);
|
||||
for (auto j : m_x)
|
||||
add_constraint_to_qsol(j);
|
||||
|
@ -73,7 +73,7 @@ void quick_xplain::minimize(const vector<unsigned>& u) {
|
|||
void quick_xplain::run(vector<std::pair<mpq, constraint_index>> & explanation, const lar_solver & ls){
|
||||
if (explanation.size() <= 2) return;
|
||||
lar_solver qsol;
|
||||
lean_assert(ls.explanation_is_correct(explanation));
|
||||
lp_assert(ls.explanation_is_correct(explanation));
|
||||
quick_xplain q(explanation, ls, qsol);
|
||||
q.solve();
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ bool quick_xplain::is_feasible(const vector<unsigned> & x, unsigned k) const {
|
|||
l.add_constraint(ls, c.m_kind, c.m_right_side);
|
||||
}
|
||||
l.solve();
|
||||
return l.get_status() != INFEASIBLE;
|
||||
return l.get_status() != lp_status::INFEASIBLE;
|
||||
}
|
||||
|
||||
bool quick_xplain::x_is_minimal() const {
|
||||
|
@ -109,7 +109,7 @@ bool quick_xplain::x_is_minimal() const {
|
|||
x.push_back(j);
|
||||
|
||||
for (unsigned k = 0; k < x.size(); k++) {
|
||||
lean_assert(is_feasible(x, x[k]));
|
||||
lp_assert(is_feasible(x, x[k]));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ bool quick_xplain::x_is_minimal() const {
|
|||
void quick_xplain::solve() {
|
||||
copy_constraints_to_local_constraints();
|
||||
m_qsol.push();
|
||||
lean_assert(m_qsol.constraint_count() == 0)
|
||||
lp_assert(m_qsol.constraint_count() == 0)
|
||||
vector<unsigned> u;
|
||||
for (unsigned k = 0; k < m_constraints_in_local_vars.size(); k++)
|
||||
u.push_back(k);
|
||||
|
@ -127,10 +127,10 @@ void quick_xplain::solve() {
|
|||
for (unsigned i : m_x)
|
||||
add_constraint_to_qsol(i);
|
||||
m_qsol.solve();
|
||||
lean_assert(m_qsol.get_status() == INFEASIBLE);
|
||||
lp_assert(m_qsol.get_status() == lp_status::INFEASIBLE);
|
||||
m_qsol.get_infeasibility_explanation(m_explanation);
|
||||
lean_assert(m_qsol.explanation_is_correct(m_explanation));
|
||||
lean_assert(x_is_minimal());
|
||||
lp_assert(m_qsol.explanation_is_correct(m_explanation));
|
||||
lp_assert(x_is_minimal());
|
||||
for (auto & p : m_explanation) {
|
||||
p.second = this->m_local_constraint_offset_to_external_ci[m_local_ci_to_constraint_offsets[p.second]];
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ Author: Lev Nachmanson
|
|||
#include "util/vector.h"
|
||||
#include <unordered_set>
|
||||
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
class lar_solver; // forward definition
|
||||
|
||||
class quick_xplain {
|
||||
|
|
|
@ -12,7 +12,7 @@ Author: Lev Nachmanson
|
|||
#include "util/lp/linear_combination_iterator.h"
|
||||
// see http://research.microsoft.com/projects/z3/smt07.pdf
|
||||
// The class searches for a feasible solution with as many different values of variables as it can find
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T> struct numeric_pair; // forward definition
|
||||
class lar_core_solver; // forward definition
|
||||
class random_updater {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "util/lp/static_matrix.h"
|
||||
#include "util/lp/lar_solver.h"
|
||||
#include "util/vector.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
|
||||
|
||||
|
||||
|
@ -36,7 +36,7 @@ random_updater::interval random_updater::get_interval_of_non_basic_var(unsigned
|
|||
ret.set_upper_bound(m_core_solver.m_r_upper_bounds[j]);
|
||||
break;
|
||||
default:
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -44,15 +44,15 @@ random_updater::interval random_updater::get_interval_of_non_basic_var(unsigned
|
|||
void random_updater::diminish_interval_for_basic_var(numeric_pair<mpq>& nb_x, unsigned j,
|
||||
mpq & a,
|
||||
interval & r) {
|
||||
lean_assert(m_core_solver.m_r_heading[j] >= 0);
|
||||
lp_assert(m_core_solver.m_r_heading[j] >= 0);
|
||||
numeric_pair<mpq> delta;
|
||||
lean_assert(a != zero_of_type<mpq>());
|
||||
lp_assert(a != zero_of_type<mpq>());
|
||||
switch (m_core_solver.get_column_type(j)) {
|
||||
case column_type::free_column:
|
||||
break;
|
||||
case column_type::low_bound:
|
||||
delta = m_core_solver.m_r_x[j] - m_core_solver.m_r_low_bounds[j];
|
||||
lean_assert(delta >= zero_of_type<numeric_pair<mpq>>());
|
||||
lp_assert(delta >= zero_of_type<numeric_pair<mpq>>());
|
||||
if (a > 0) {
|
||||
r.set_upper_bound(nb_x + delta / a);
|
||||
} else {
|
||||
|
@ -61,7 +61,7 @@ void random_updater::diminish_interval_for_basic_var(numeric_pair<mpq>& nb_x, un
|
|||
break;
|
||||
case column_type::upper_bound:
|
||||
delta = m_core_solver.m_r_upper_bounds()[j] - m_core_solver.m_r_x[j];
|
||||
lean_assert(delta >= zero_of_type<numeric_pair<mpq>>());
|
||||
lp_assert(delta >= zero_of_type<numeric_pair<mpq>>());
|
||||
if (a > 0) {
|
||||
r.set_low_bound(nb_x - delta / a);
|
||||
} else {
|
||||
|
@ -71,17 +71,17 @@ void random_updater::diminish_interval_for_basic_var(numeric_pair<mpq>& nb_x, un
|
|||
case column_type::boxed:
|
||||
if (a > 0) {
|
||||
delta = m_core_solver.m_r_x[j] - m_core_solver.m_r_low_bounds[j];
|
||||
lean_assert(delta >= zero_of_type<numeric_pair<mpq>>());
|
||||
lp_assert(delta >= zero_of_type<numeric_pair<mpq>>());
|
||||
r.set_upper_bound(nb_x + delta / a);
|
||||
delta = m_core_solver.m_r_upper_bounds()[j] - m_core_solver.m_r_x[j];
|
||||
lean_assert(delta >= zero_of_type<numeric_pair<mpq>>());
|
||||
lp_assert(delta >= zero_of_type<numeric_pair<mpq>>());
|
||||
r.set_low_bound(nb_x - delta / a);
|
||||
} else { // a < 0
|
||||
delta = m_core_solver.m_r_upper_bounds()[j] - m_core_solver.m_r_x[j];
|
||||
lean_assert(delta >= zero_of_type<numeric_pair<mpq>>());
|
||||
lp_assert(delta >= zero_of_type<numeric_pair<mpq>>());
|
||||
r.set_upper_bound(nb_x - delta / a);
|
||||
delta = m_core_solver.m_r_x[j] - m_core_solver.m_r_low_bounds[j];
|
||||
lean_assert(delta >= zero_of_type<numeric_pair<mpq>>());
|
||||
lp_assert(delta >= zero_of_type<numeric_pair<mpq>>());
|
||||
r.set_low_bound(nb_x + delta / a);
|
||||
}
|
||||
break;
|
||||
|
@ -90,7 +90,7 @@ void random_updater::diminish_interval_for_basic_var(numeric_pair<mpq>& nb_x, un
|
|||
r.set_upper_bound(nb_x);
|
||||
break;
|
||||
default:
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,15 +113,15 @@ random_updater::interval random_updater::find_shift_interval(unsigned j) {
|
|||
}
|
||||
|
||||
void random_updater::shift_var(unsigned j, interval & r) {
|
||||
lean_assert(r.contains(m_core_solver.m_r_x[j]));
|
||||
lean_assert(m_core_solver.m_r_solver.column_is_feasible(j));
|
||||
lp_assert(r.contains(m_core_solver.m_r_x[j]));
|
||||
lp_assert(m_core_solver.m_r_solver.column_is_feasible(j));
|
||||
auto old_x = m_core_solver.m_r_x[j];
|
||||
remove_value(old_x);
|
||||
auto new_val = m_core_solver.m_r_x[j] = get_random_from_interval(r);
|
||||
add_value(new_val);
|
||||
|
||||
lean_assert(r.contains(m_core_solver.m_r_x[j]));
|
||||
lean_assert(m_core_solver.m_r_solver.column_is_feasible(j));
|
||||
lp_assert(r.contains(m_core_solver.m_r_x[j]));
|
||||
lp_assert(m_core_solver.m_r_solver.column_is_feasible(j));
|
||||
auto delta = m_core_solver.m_r_x[j] - old_x;
|
||||
|
||||
unsigned i;
|
||||
|
@ -130,9 +130,9 @@ void random_updater::shift_var(unsigned j, interval & r) {
|
|||
while(m_column_j->next(a, i)) {
|
||||
unsigned bj = m_core_solver.m_r_basis[i];
|
||||
m_core_solver.m_r_x[bj] -= a * delta;
|
||||
lean_assert(m_core_solver.m_r_solver.column_is_feasible(bj));
|
||||
lp_assert(m_core_solver.m_r_solver.column_is_feasible(bj));
|
||||
}
|
||||
lean_assert(m_core_solver.m_r_solver.A_mult_x_is_off() == false);
|
||||
lp_assert(m_core_solver.m_r_solver.A_mult_x_is_off() == false);
|
||||
}
|
||||
|
||||
numeric_pair<mpq> random_updater::get_random_from_interval(interval & r) {
|
||||
|
@ -143,7 +143,7 @@ numeric_pair<mpq> random_updater::get_random_from_interval(interval & r) {
|
|||
return r.low_bound + numeric_pair<mpq>(rand % range, 0);
|
||||
if ((!r.low_bound_is_set) && r.upper_bound_is_set)
|
||||
return r.upper_bound - numeric_pair<mpq>(rand % range, 0);
|
||||
lean_assert(r.low_bound_is_set && r.upper_bound_is_set);
|
||||
lp_assert(r.low_bound_is_set && r.upper_bound_is_set);
|
||||
return r.low_bound + (rand % range) * (r.upper_bound - r.low_bound)/ range;
|
||||
}
|
||||
|
||||
|
@ -183,7 +183,7 @@ void random_updater::add_value(numeric_pair<mpq>& v) {
|
|||
|
||||
void random_updater::remove_value(numeric_pair<mpq>& v) {
|
||||
std::unordered_map<numeric_pair<mpq>, unsigned>::iterator it = m_values.find(v);
|
||||
lean_assert(it != m_values.end());
|
||||
lp_assert(it != m_values.end());
|
||||
it->second--;
|
||||
if (it->second == 0)
|
||||
m_values.erase((std::unordered_map<numeric_pair<mpq>, unsigned>::const_iterator)it);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "util/lp/sparse_vector.h"
|
||||
#include "util/lp/indexed_vector.h"
|
||||
#include "util/lp/permutation_matrix.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
// This is the sum of a unit matrix and a lower triangular matrix
|
||||
// with non-zero elements only in one row
|
||||
template <typename T, typename X>
|
||||
|
@ -55,7 +55,7 @@ public:
|
|||
}
|
||||
|
||||
void push_back(unsigned row_index, T val ) {
|
||||
lean_assert(row_index != m_row);
|
||||
lp_assert(row_index != m_row);
|
||||
m_row_vector.push_back(row_index, val);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
#include "util/vector.h"
|
||||
#include "util/lp/row_eta_matrix.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T, typename X>
|
||||
void row_eta_matrix<T, X>::apply_from_left(vector<X> & w, lp_settings &) {
|
||||
// #ifdef LEAN_DEBUG
|
||||
|
@ -19,7 +19,7 @@ void row_eta_matrix<T, X>::apply_from_left(vector<X> & w, lp_settings &) {
|
|||
}
|
||||
// w[m_row] = w_at_row;
|
||||
// #ifdef LEAN_DEBUG
|
||||
// lean_assert(vectors_are_equal<T>(clone_w, w, m_dimension));
|
||||
// lp_assert(vectors_are_equal<T>(clone_w, w, m_dimension));
|
||||
// delete [] clone_w;
|
||||
// #endif
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ void row_eta_matrix<T, X>::apply_from_left_local_to_T(indexed_vector<T> & w, lp_
|
|||
auto it = std::find(w.m_index.begin(), w.m_index.end(), m_row);
|
||||
w.m_index.erase(it);
|
||||
}
|
||||
// TBD: lean_assert(check_vector_for_small_values(w, settings));
|
||||
// TBD: lp_assert(check_vector_for_small_values(w, settings));
|
||||
}
|
||||
|
||||
template <typename T, typename X>
|
||||
|
@ -65,7 +65,7 @@ void row_eta_matrix<T, X>::apply_from_left_local_to_X(indexed_vector<X> & w, lp_
|
|||
auto it = std::find(w.m_index.begin(), w.m_index.end(), m_row);
|
||||
w.m_index.erase(it);
|
||||
}
|
||||
// TBD: does not compile lean_assert(check_vector_for_small_values(w, settings));
|
||||
// TBD: does not compile lp_assert(check_vector_for_small_values(w, settings));
|
||||
}
|
||||
|
||||
template <typename T, typename X>
|
||||
|
@ -81,14 +81,14 @@ void row_eta_matrix<T, X>::apply_from_right(vector<T> & w) {
|
|||
w[it.first] += w_row * it.second;
|
||||
}
|
||||
#ifdef LEAN_DEBUG
|
||||
// lean_assert(vectors_are_equal<T>(clone_w, w, m_dimension));
|
||||
// lp_assert(vectors_are_equal<T>(clone_w, w, m_dimension));
|
||||
// delete clone_w;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T, typename X>
|
||||
void row_eta_matrix<T, X>::apply_from_right(indexed_vector<T> & w) {
|
||||
lean_assert(w.is_OK());
|
||||
lp_assert(w.is_OK());
|
||||
const T & w_row = w[m_row];
|
||||
if (numeric_traits<T>::is_zero(w_row)) return;
|
||||
#ifdef LEAN_DEBUG
|
||||
|
@ -130,7 +130,7 @@ void row_eta_matrix<T, X>::apply_from_right(indexed_vector<T> & w) {
|
|||
}
|
||||
}
|
||||
#ifdef LEAN_DEBUG
|
||||
// lean_assert(vectors_are_equal(wcopy, w.m_data));
|
||||
// lp_assert(vectors_are_equal(wcopy, w.m_data));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ void row_eta_matrix<T, X>::conjugate_by_permutation(permutation_matrix<T, X> & p
|
|||
for (unsigned i = static_cast<unsigned>(columns.size()); i-- > 0;)
|
||||
m_row_vector.m_data[i].first = p.get_rev(columns[i]);
|
||||
#ifdef LEAN_DEBUG
|
||||
// lean_assert(deb == *this);
|
||||
// lp_assert(deb == *this);
|
||||
#endif
|
||||
}
|
||||
#ifdef LEAN_DEBUG
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <memory>
|
||||
#include "util/lp/row_eta_matrix.hpp"
|
||||
#include "util/lp/lu.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template void row_eta_matrix<double, double>::conjugate_by_permutation(permutation_matrix<double, double>&);
|
||||
template void row_eta_matrix<mpq, numeric_pair<mpq> >::conjugate_by_permutation(permutation_matrix<mpq, numeric_pair<mpq> >&);
|
||||
template void row_eta_matrix<mpq, mpq>::conjugate_by_permutation(permutation_matrix<mpq, mpq>&);
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include <stdlib.h> /* exit, EXIT_FAILURE */
|
||||
#include "util/lp/lp_utils.h"
|
||||
#include "util/lp/static_matrix.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
// for scaling an LP
|
||||
template <typename T, typename X>
|
||||
class scaler {
|
||||
|
@ -31,7 +31,7 @@ public:
|
|||
m_scaling_maximum(scaling_maximum),
|
||||
m_column_scale(column_scale),
|
||||
m_settings(settings) {
|
||||
lean_assert(m_column_scale.size() == 0);
|
||||
lp_assert(m_column_scale.size() == 0);
|
||||
m_column_scale.resize(m_A.column_count(), numeric_traits<T>::one());
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include <algorithm>
|
||||
#include "util/lp/scaler.h"
|
||||
#include "util/lp/numeric_pair.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
// for scaling an LP
|
||||
template <typename T, typename X> T scaler<T, X>::right_side_balance() {
|
||||
T ret = zero_of_type<T>();
|
||||
|
@ -41,7 +41,7 @@ template <typename T, typename X> T scaler<T, X>::A_max() const {
|
|||
template <typename T, typename X> T scaler<T, X>::get_A_ratio() const {
|
||||
T min = A_min();
|
||||
T max = A_max();
|
||||
lean_assert(!m_settings.abs_val_is_smaller_than_zero_tolerance(min));
|
||||
lp_assert(!m_settings.abs_val_is_smaller_than_zero_tolerance(min));
|
||||
T ratio = max / min;
|
||||
return ratio;
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ template <typename T, typename X> T scaler<T, X>::get_max_ratio_on_rows() con
|
|||
unsigned i = m_A.row_count();
|
||||
while (i--) {
|
||||
T den = m_A.get_min_abs_in_row(i);
|
||||
lean_assert(!m_settings.abs_val_is_smaller_than_zero_tolerance(den));
|
||||
lp_assert(!m_settings.abs_val_is_smaller_than_zero_tolerance(den));
|
||||
T t = m_A.get_max_abs_in_row(i)/ den;
|
||||
if (t > ret)
|
||||
ret = t;
|
||||
|
@ -78,7 +78,7 @@ template <typename T, typename X> void scaler<T, X>::scale_rows_with_geometri
|
|||
while (i--) {
|
||||
T max = m_A.get_max_abs_in_row(i);
|
||||
T min = m_A.get_min_abs_in_row(i);
|
||||
lean_assert(max > zero_of_type<T>() && min > zero_of_type<T>());
|
||||
lp_assert(max > zero_of_type<T>() && min > zero_of_type<T>());
|
||||
if (is_zero(max) || is_zero(min))
|
||||
continue;
|
||||
T gm = T(sqrt(numeric_traits<T>::get_double(max*min)));
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
Author: Lev Nachmanson
|
||||
*/
|
||||
#include "util/lp/scaler.hpp"
|
||||
template bool lean::scaler<double, double>::scale();
|
||||
template bool lean::scaler<lean::mpq, lean::mpq>::scale();
|
||||
template bool lp::scaler<double, double>::scale();
|
||||
template bool lp::scaler<lp::mpq, lp::mpq>::scale();
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#pragma once
|
||||
#include "util/lp/lp_settings.h"
|
||||
#include "util/lp/lar_constraints.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
struct bound_signature {
|
||||
unsigned m_i;
|
||||
bool m_at_low;
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "util/lp/binary_heap_upair_queue.h"
|
||||
#include "util/lp/numeric_pair.h"
|
||||
#include "util/lp/int_set.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
// it is a square matrix
|
||||
template <typename T, typename X>
|
||||
class sparse_matrix
|
||||
|
@ -206,19 +206,19 @@ public:
|
|||
void multiply_from_right(permutation_matrix<T, X>& p) {
|
||||
// m_dense = m_dense * p;
|
||||
m_column_permutation.multiply_by_permutation_from_right(p);
|
||||
// lean_assert(*this == m_dense);
|
||||
// lp_assert(*this == m_dense);
|
||||
}
|
||||
|
||||
void multiply_from_left(permutation_matrix<T, X>& p) {
|
||||
// m_dense = p * m_dense;
|
||||
m_row_permutation.multiply_by_permutation_from_left(p);
|
||||
// lean_assert(*this == m_dense);
|
||||
// lp_assert(*this == m_dense);
|
||||
}
|
||||
|
||||
void multiply_from_left_with_reverse(permutation_matrix<T, X>& p) {
|
||||
// m_dense = p * m_dense;
|
||||
m_row_permutation.multiply_by_permutation_reverse_from_left(p);
|
||||
// lean_assert(*this == m_dense);
|
||||
// lp_assert(*this == m_dense);
|
||||
}
|
||||
|
||||
// adding delta columns at the end of the matrix
|
||||
|
@ -231,13 +231,13 @@ public:
|
|||
// dense_matrix<T, X> d(*this);
|
||||
m_column_permutation.transpose_from_left(a, b);
|
||||
// d.swap_columns(a, b);
|
||||
// lean_assert(*this == d);
|
||||
// lp_assert(*this == d);
|
||||
}
|
||||
|
||||
void swap_rows(unsigned a, unsigned b) {
|
||||
m_row_permutation.transpose_from_right(a, b);
|
||||
// m_dense.swap_rows(a, b);
|
||||
// lean_assert(*this == m_dense);
|
||||
// lp_assert(*this == m_dense);
|
||||
}
|
||||
|
||||
void divide_row_by_constant(unsigned i, const T & t, lp_settings & settings);
|
||||
|
@ -393,7 +393,7 @@ public:
|
|||
void process_index_recursively_for_y_U(unsigned j, vector<unsigned> & sorted_rows);
|
||||
void resize(unsigned new_dim) {
|
||||
unsigned old_dim = dimension();
|
||||
lean_assert(new_dim >= old_dim);
|
||||
lp_assert(new_dim >= old_dim);
|
||||
for (unsigned j = old_dim; j < new_dim; j++) {
|
||||
m_rows.push_back(vector<indexed_value<T>>());
|
||||
m_columns.push_back(col_header());
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "util/lp/sparse_matrix.h"
|
||||
#include <set>
|
||||
#include <queue>
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T, typename X>
|
||||
void sparse_matrix<T, X>::copy_column_from_static_matrix(unsigned col, static_matrix<T, X> const &A, unsigned col_index_in_the_new_matrix) {
|
||||
vector<column_cell> const & A_col_vector = A.m_columns[col];
|
||||
|
@ -82,12 +82,12 @@ void sparse_matrix<T, X>::set_with_no_adjusting(unsigned row, unsigned col, T va
|
|||
|
||||
template <typename T, typename X>
|
||||
void sparse_matrix<T, X>::set(unsigned row, unsigned col, T val) { // should not be used in efficient code
|
||||
lean_assert(row < dimension() && col < dimension());
|
||||
lp_assert(row < dimension() && col < dimension());
|
||||
// m_dense.set_elem(row, col, val);
|
||||
row = adjust_row(row);
|
||||
col = adjust_column(col);
|
||||
set_with_no_adjusting(row, col, val);
|
||||
// lean_assert(*this == m_dense);
|
||||
// lp_assert(*this == m_dense);
|
||||
}
|
||||
|
||||
template <typename T, typename X>
|
||||
|
@ -261,8 +261,8 @@ vector<T> sparse_matrix<T, X>::get_full_row(unsigned i) const {
|
|||
// Returns false if the resulting row is all zeroes, and true otherwise
|
||||
template <typename T, typename X>
|
||||
bool sparse_matrix<T, X>::pivot_row_to_row(unsigned i, const T& alpha, unsigned i0, lp_settings & settings ) {
|
||||
lean_assert(i < dimension() && i0 < dimension());
|
||||
lean_assert(i != i0);
|
||||
lp_assert(i < dimension() && i0 < dimension());
|
||||
lp_assert(i != i0);
|
||||
unsigned pivot_col = adjust_column(i);
|
||||
i = adjust_row(i);
|
||||
i0 = adjust_row(i0);
|
||||
|
@ -327,7 +327,7 @@ bool sparse_matrix<T, X>::set_row_from_work_vector_and_clean_work_vector_not_adj
|
|||
if (numeric_traits<T>::is_zero(work_vec[j])) {
|
||||
continue;
|
||||
}
|
||||
lean_assert(!settings.abs_val_is_smaller_than_drop_tolerance(work_vec[j]));
|
||||
lp_assert(!settings.abs_val_is_smaller_than_drop_tolerance(work_vec[j]));
|
||||
add_new_element(i0, adjust_column(j), work_vec[j]);
|
||||
work_vec[j] = numeric_traits<T>::zero();
|
||||
}
|
||||
|
@ -372,7 +372,7 @@ void sparse_matrix<T, X>::remove_zero_elements_and_set_data_on_existing_elements
|
|||
T val = work_vec[rj];
|
||||
if (settings.abs_val_is_smaller_than_drop_tolerance(val)) {
|
||||
remove_element(row_vals, row_el_iv);
|
||||
lean_assert(numeric_traits<T>::is_zero(val));
|
||||
lp_assert(numeric_traits<T>::is_zero(val));
|
||||
} else {
|
||||
m_columns[j].m_values[row_el_iv.m_other].set_value(row_el_iv.m_value = val);
|
||||
work_vec[rj] = numeric_traits<T>::zero();
|
||||
|
@ -393,7 +393,7 @@ void sparse_matrix<T, X>::add_columns_at_the_end(unsigned delta) {
|
|||
|
||||
template <typename T, typename X>
|
||||
void sparse_matrix<T, X>::delete_column(int i) {
|
||||
lean_assert(i < dimension());
|
||||
lp_assert(i < dimension());
|
||||
for (auto cell = m_columns[i].m_head; cell != nullptr;) {
|
||||
auto next_cell = cell->m_down;
|
||||
kill_cell(cell);
|
||||
|
@ -403,7 +403,7 @@ void sparse_matrix<T, X>::delete_column(int i) {
|
|||
|
||||
template <typename T, typename X>
|
||||
void sparse_matrix<T, X>::divide_row_by_constant(unsigned i, const T & t, lp_settings & settings) {
|
||||
lean_assert(!settings.abs_val_is_smaller_than_zero_tolerance(t));
|
||||
lp_assert(!settings.abs_val_is_smaller_than_zero_tolerance(t));
|
||||
i = adjust_row(i);
|
||||
for (auto & iv : m_rows[i]) {
|
||||
T &v = iv.m_value;
|
||||
|
@ -440,7 +440,7 @@ void sparse_matrix<T, X>::solve_y_U(vector<T> & y) const { // works by rows
|
|||
// dense_matrix<T> deb(*this);
|
||||
// T * clone_y = clone_vector<T>(y, dimension());
|
||||
// deb.apply_from_right(clone_y);
|
||||
// lean_assert(vectors_are_equal(rs, clone_y, dimension()));
|
||||
// lp_assert(vectors_are_equal(rs, clone_y, dimension()));
|
||||
// delete [] clone_y;
|
||||
// delete [] rs;
|
||||
#endif
|
||||
|
@ -474,10 +474,10 @@ void sparse_matrix<T, X>::solve_y_U_indexed(indexed_vector<T> & y, const lp_sett
|
|||
y.m_data[j] = zero_of_type<T>();
|
||||
}
|
||||
|
||||
lean_assert(y.is_OK());
|
||||
lp_assert(y.is_OK());
|
||||
#if 0 && LEAN_DEBUG
|
||||
if (numeric_traits<T>::precise() == false)
|
||||
lean_assert(vectors_are_equal(ycopy, y.m_data));
|
||||
lp_assert(vectors_are_equal(ycopy, y.m_data));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -537,8 +537,8 @@ void sparse_matrix<T, X>::add_delta_to_solution(const vector<L>& del, vector<L>
|
|||
template <typename T, typename X>
|
||||
template <typename L>
|
||||
void sparse_matrix<T, X>::add_delta_to_solution(const indexed_vector<L>& del, indexed_vector<L> & y) {
|
||||
// lean_assert(del.is_OK());
|
||||
// lean_assert(y.is_OK());
|
||||
// lp_assert(del.is_OK());
|
||||
// lp_assert(y.is_OK());
|
||||
for (auto i : del.m_index) {
|
||||
y.add_value_at_index(i, del[i]);
|
||||
}
|
||||
|
@ -546,11 +546,11 @@ void sparse_matrix<T, X>::add_delta_to_solution(const indexed_vector<L>& del, in
|
|||
template <typename T, typename X>
|
||||
template <typename L>
|
||||
void sparse_matrix<T, X>::double_solve_U_y(indexed_vector<L>& y, const lp_settings & settings){
|
||||
lean_assert(y.is_OK());
|
||||
lp_assert(y.is_OK());
|
||||
indexed_vector<L> y_orig(y); // copy y aside
|
||||
vector<unsigned> active_rows;
|
||||
solve_U_y_indexed_only(y, settings, active_rows);
|
||||
lean_assert(y.is_OK());
|
||||
lp_assert(y.is_OK());
|
||||
find_error_in_solution_U_y_indexed(y_orig, y, active_rows);
|
||||
// y_orig contains the error now
|
||||
if (y_orig.m_index.size() * ratio_of_index_size_to_all_size<T>() < 32 * dimension()) {
|
||||
|
@ -563,7 +563,7 @@ void sparse_matrix<T, X>::double_solve_U_y(indexed_vector<L>& y, const lp_settin
|
|||
add_delta_to_solution(y_orig.m_data, y.m_data);
|
||||
y.restore_index_and_clean_from_data();
|
||||
}
|
||||
lean_assert(y.is_OK());
|
||||
lp_assert(y.is_OK());
|
||||
}
|
||||
template <typename T, typename X>
|
||||
template <typename L>
|
||||
|
@ -599,12 +599,12 @@ void sparse_matrix<T, X>::solve_U_y(vector<L> & y) { // it is a column wise vers
|
|||
// dense_matrix<T> deb(*this);
|
||||
// T * clone_y = clone_vector<T>(y, dimension());
|
||||
// deb.apply_from_left(clone_y);
|
||||
// lean_assert(vectors_are_equal(rs, clone_y, dimension()));
|
||||
// lp_assert(vectors_are_equal(rs, clone_y, dimension()));
|
||||
#endif
|
||||
}
|
||||
template <typename T, typename X>
|
||||
void sparse_matrix<T, X>::process_index_recursively_for_y_U(unsigned j, vector<unsigned> & sorted_active_rows) {
|
||||
lean_assert(m_processed[j] == false);
|
||||
lp_assert(m_processed[j] == false);
|
||||
m_processed[j]=true;
|
||||
auto & row = m_rows[adjust_row(j)];
|
||||
for (auto & c : row) {
|
||||
|
@ -619,7 +619,7 @@ void sparse_matrix<T, X>::process_index_recursively_for_y_U(unsigned j, vector<u
|
|||
|
||||
template <typename T, typename X>
|
||||
void sparse_matrix<T, X>::process_column_recursively(unsigned j, vector<unsigned> & sorted_active_rows) {
|
||||
lean_assert(m_processed[j] == false);
|
||||
lp_assert(m_processed[j] == false);
|
||||
auto & mc = m_columns[adjust_column(j)].m_values;
|
||||
for (auto & iv : mc) {
|
||||
unsigned i = adjust_row_inverse(iv.m_index);
|
||||
|
@ -684,12 +684,12 @@ void sparse_matrix<T, X>::solve_U_y_indexed_only(indexed_vector<L> & y, const lp
|
|||
y[j] = zero_of_type<L>();
|
||||
}
|
||||
|
||||
lean_assert(y.is_OK());
|
||||
lp_assert(y.is_OK());
|
||||
#ifdef LEAN_DEBUG
|
||||
// dense_matrix<T,X> deb(this);
|
||||
// vector<T> clone_y(y.m_data);
|
||||
// deb.apply_from_left(clone_y);
|
||||
// lean_assert(vectors_are_equal(rs, clone_y));
|
||||
// lp_assert(vectors_are_equal(rs, clone_y));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -802,7 +802,7 @@ void sparse_matrix<T, X>::add_new_elements_of_w_and_clear_w(unsigned column_to_r
|
|||
unsigned ai = adjust_row(i);
|
||||
add_new_element(ai, column_to_replace, w_at_i);
|
||||
auto & row_chunk = m_rows[ai];
|
||||
lean_assert(row_chunk.size() > 0);
|
||||
lp_assert(row_chunk.size() > 0);
|
||||
if (abs(w_at_i) > abs(row_chunk[0].m_value))
|
||||
put_max_index_to_0(row_chunk, static_cast<unsigned>(row_chunk.size()) - 1);
|
||||
}
|
||||
|
@ -833,7 +833,7 @@ unsigned sparse_matrix<T, X>::pivot_score(unsigned i, unsigned j) {
|
|||
|
||||
template <typename T, typename X>
|
||||
void sparse_matrix<T, X>::enqueue_domain_into_pivot_queue() {
|
||||
lean_assert(m_pivot_queue.size() == 0);
|
||||
lp_assert(m_pivot_queue.size() == 0);
|
||||
for (unsigned i = 0; i < dimension(); i++) {
|
||||
auto & rh = m_rows[i];
|
||||
unsigned rnz = static_cast<unsigned>(rh.size());
|
||||
|
@ -919,7 +919,7 @@ void sparse_matrix<T, X>::update_active_pivots(unsigned row) {
|
|||
for (const auto & iv : m_rows[arow]) {
|
||||
col_header & ch = m_columns[iv.m_index];
|
||||
int cols = static_cast<int>(ch.m_values.size()) - ch.m_shortened_markovitz - 1;
|
||||
lean_assert(cols >= 0);
|
||||
lp_assert(cols >= 0);
|
||||
for (const auto &ivc : ch.m_values) {
|
||||
unsigned i = ivc.m_index;
|
||||
if (adjust_row_inverse(i) <= row) continue; // the i is not an active row
|
||||
|
@ -945,7 +945,7 @@ bool sparse_matrix<T, X>::shorten_active_matrix(unsigned row, eta_matrix<T, X> *
|
|||
for (auto & iv : row_values) {
|
||||
const col_header& ch = m_columns[iv.m_index];
|
||||
int cnz = static_cast<int>(ch.m_values.size()) - ch.m_shortened_markovitz - 1;
|
||||
lean_assert(cnz >= 0);
|
||||
lp_assert(cnz >= 0);
|
||||
m_pivot_queue.enqueue(row, iv.m_index, rnz * cnz);
|
||||
}
|
||||
}
|
||||
|
@ -961,7 +961,7 @@ unsigned sparse_matrix<T, X>::pivot_score_without_shortened_counters(unsigned i,
|
|||
if (adjust_row_inverse(iv.m_index) < k)
|
||||
cnz--;
|
||||
}
|
||||
lean_assert(cnz > 0);
|
||||
lp_assert(cnz > 0);
|
||||
return m_rows[i].m_values.size() * (cnz - 1);
|
||||
}
|
||||
#ifdef LEAN_DEBUG
|
||||
|
@ -971,15 +971,15 @@ bool sparse_matrix<T, X>::can_improve_score_for_row(unsigned row, unsigned score
|
|||
auto & row_vals = m_rows[arow].m_values;
|
||||
auto & begin_iv = row_vals[0];
|
||||
T row_max = abs(begin_iv.m_value);
|
||||
lean_assert(adjust_column_inverse(begin_iv.m_index) >= k);
|
||||
lp_assert(adjust_column_inverse(begin_iv.m_index) >= k);
|
||||
if (pivot_score_without_shortened_counters(arow, begin_iv.m_index, k) < score) {
|
||||
print_active_matrix(k);
|
||||
return true;
|
||||
}
|
||||
for (unsigned jj = 1; jj < row_vals.size(); jj++) {
|
||||
auto & iv = row_vals[jj];
|
||||
lean_assert(adjust_column_inverse(iv.m_index) >= k);
|
||||
lean_assert(abs(iv.m_value) <= row_max);
|
||||
lp_assert(adjust_column_inverse(iv.m_index) >= k);
|
||||
lp_assert(abs(iv.m_value) <= row_max);
|
||||
if (c_partial_pivoting * abs(iv.m_value) < row_max) continue;
|
||||
if (pivot_score_without_shortened_counters(arow, iv.m_index, k) < score) {
|
||||
print_active_matrix(k);
|
||||
|
@ -993,7 +993,7 @@ template <typename T, typename X>
|
|||
bool sparse_matrix<T, X>::really_best_pivot(unsigned i, unsigned j, T const & c_partial_pivoting, unsigned k) {
|
||||
unsigned queue_pivot_score = pivot_score_without_shortened_counters(i, j, k);
|
||||
for (unsigned ii = k; ii < dimension(); ii++) {
|
||||
lean_assert(!can_improve_score_for_row(ii, queue_pivot_score, c_partial_pivoting, k));
|
||||
lp_assert(!can_improve_score_for_row(ii, queue_pivot_score, c_partial_pivoting, k));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1026,7 +1026,7 @@ template <typename T, typename X>
|
|||
bool sparse_matrix<T, X>::pivot_queue_is_correct_for_row(unsigned i, unsigned k) {
|
||||
unsigned arow = adjust_row(i);
|
||||
for (auto & iv : m_rows[arow].m_values) {
|
||||
lean_assert(pivot_score_without_shortened_counters(arow, iv.m_index, k + 1) ==
|
||||
lp_assert(pivot_score_without_shortened_counters(arow, iv.m_index, k + 1) ==
|
||||
m_pivot_queue.get_priority(arow, iv.m_index));
|
||||
}
|
||||
return true;
|
||||
|
@ -1035,8 +1035,8 @@ bool sparse_matrix<T, X>::pivot_queue_is_correct_for_row(unsigned i, unsigned k)
|
|||
template <typename T, typename X>
|
||||
bool sparse_matrix<T, X>::pivot_queue_is_correct_after_pivoting(int k) {
|
||||
for (unsigned i = k + 1; i < dimension(); i++ )
|
||||
lean_assert(pivot_queue_is_correct_for_row(i, k));
|
||||
lean_assert(m_pivot_queue.is_correct());
|
||||
lp_assert(pivot_queue_is_correct_for_row(i, k));
|
||||
lp_assert(m_pivot_queue.is_correct());
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
@ -1050,12 +1050,12 @@ bool sparse_matrix<T, X>::get_pivot_for_column(unsigned &i, unsigned &j, int c_p
|
|||
if (i_inv < k) continue;
|
||||
unsigned j_inv = adjust_column_inverse(j);
|
||||
if (j_inv < k) continue;
|
||||
int small = elem_is_too_small(i, j, c_partial_pivoting);
|
||||
if (!small) {
|
||||
int _small = elem_is_too_small(i, j, c_partial_pivoting);
|
||||
if (!_small) {
|
||||
#ifdef LEAN_DEBUG
|
||||
// if (!really_best_pivot(i, j, c_partial_pivoting, k)) {
|
||||
// print_active_matrix(k);
|
||||
// lean_assert(false);
|
||||
// lp_assert(false);
|
||||
// }
|
||||
#endif
|
||||
recover_pivot_queue(pivots_candidates_that_are_too_small);
|
||||
|
@ -1063,7 +1063,7 @@ bool sparse_matrix<T, X>::get_pivot_for_column(unsigned &i, unsigned &j, int c_p
|
|||
j = j_inv;
|
||||
return true;
|
||||
}
|
||||
if (small != 2) { // 2 means that the pair is not in the matrix
|
||||
if (_small != 2) { // 2 means that the pair is not in the matrix
|
||||
pivots_candidates_that_are_too_small.push_back(std::make_pair(i, j));
|
||||
}
|
||||
}
|
||||
|
@ -1088,7 +1088,7 @@ bool sparse_matrix<T, X>::shorten_columns_by_pivot_row(unsigned i, unsigned pivo
|
|||
for (indexed_value<T> & iv : row_chunk) {
|
||||
unsigned j = iv.m_index;
|
||||
if (j == pivot_column) {
|
||||
lean_assert(!col_is_active(j));
|
||||
lp_assert(!col_is_active(j));
|
||||
continue;
|
||||
}
|
||||
m_columns[j].shorten_markovich_by_one();
|
||||
|
@ -1151,11 +1151,11 @@ template <typename T, typename X>
|
|||
bool sparse_matrix<T, X>::is_upper_triangular_and_maximums_are_set_correctly_in_rows(lp_settings & settings) const {
|
||||
for (unsigned i = 0; i < dimension(); i++) {
|
||||
vector<indexed_value<T>> const & row_chunk = get_row_values(i);
|
||||
lean_assert(row_chunk.size());
|
||||
lp_assert(row_chunk.size());
|
||||
T const & max = abs(row_chunk[0].m_value);
|
||||
unsigned ai = adjust_row_inverse(i);
|
||||
for (auto & iv : row_chunk) {
|
||||
lean_assert(abs(iv.m_value) <= max);
|
||||
lp_assert(abs(iv.m_value) <= max);
|
||||
unsigned aj = adjust_column_inverse(iv.m_index);
|
||||
if (!(ai <= aj || numeric_traits<T>::is_zero(iv.m_value)))
|
||||
return false;
|
||||
|
@ -1193,18 +1193,18 @@ void sparse_matrix<T, X>::check_column_vs_rows(unsigned col) {
|
|||
indexed_value<T> & row_iv = column_iv_other(column_iv);
|
||||
if (row_iv.m_index != col) {
|
||||
// std::cout << "m_other in row does not belong to column " << col << ", but to column " << row_iv.m_index << std::endl;
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
}
|
||||
|
||||
if (& row_iv_other(row_iv) != &column_iv) {
|
||||
// std::cout << "row and col do not point to each other" << std::endl;
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
}
|
||||
|
||||
if (row_iv.m_value != column_iv.m_value) {
|
||||
// std::cout << "the data from col " << col << " for row " << column_iv.m_index << " is different in the column " << std::endl;
|
||||
// std::cout << "in the col it is " << column_iv.m_value << ", but in the row it is " << row_iv.m_value << std::endl;
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1217,18 +1217,18 @@ void sparse_matrix<T, X>::check_row_vs_columns(unsigned row) {
|
|||
|
||||
if (column_iv.m_index != row) {
|
||||
// std::cout << "col_iv does not point to correct row " << row << " but to " << column_iv.m_index << std::endl;
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
}
|
||||
|
||||
if (& row_iv != & column_iv_other(column_iv)) {
|
||||
// std::cout << "row and col do not point to each other" << std::endl;
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
}
|
||||
|
||||
if (row_iv.m_value != column_iv.m_value) {
|
||||
// std::cout << "the data from col " << column_iv.m_index << " for row " << row << " is different in the column " << std::endl;
|
||||
// std::cout << "in the col it is " << column_iv.m_value << ", but in the row it is " << row_iv.m_value << std::endl;
|
||||
lean_assert(false);
|
||||
lp_assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
Copyright (c) 2017 Microsoft Corporation
|
||||
Author: Lev Nachmanson
|
||||
*/
|
||||
#include "util/vector.h"
|
||||
#include <memory>
|
||||
#include "util/vector.h"
|
||||
#include "util/lp/lp_settings.h"
|
||||
#include "util/lp/lu.h"
|
||||
#include "util/lp/sparse_matrix.hpp"
|
||||
#include "util/lp/dense_matrix.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template double sparse_matrix<double, double>::dot_product_with_row<double>(unsigned int, vector<double> const&) const;
|
||||
template void sparse_matrix<double, double>::add_new_element(unsigned int, unsigned int, const double&);
|
||||
template void sparse_matrix<double, double>::divide_row_by_constant(unsigned int, const double&, lp_settings&);
|
||||
|
@ -65,37 +65,37 @@ template void sparse_matrix<double, double>::double_solve_U_y<double>(indexed_ve
|
|||
template void sparse_matrix<mpq, mpq>::double_solve_U_y<mpq>(indexed_vector<mpq>&, const lp_settings&);
|
||||
template void sparse_matrix<mpq, numeric_pair<mpq>>::double_solve_U_y<mpq>(indexed_vector<mpq>&, const lp_settings&);
|
||||
template void sparse_matrix<mpq, numeric_pair<mpq> >::double_solve_U_y<numeric_pair<mpq> >(indexed_vector<numeric_pair<mpq>>&, const lp_settings&);
|
||||
template void lean::sparse_matrix<double, double>::solve_U_y_indexed_only<double>(lean::indexed_vector<double>&, const lp_settings&, vector<unsigned> &);
|
||||
template void lean::sparse_matrix<lean::mpq, lean::mpq>::solve_U_y_indexed_only<lean::mpq>(lean::indexed_vector<lean::mpq>&, const lp_settings &, vector<unsigned> &);
|
||||
template void lp::sparse_matrix<double, double>::solve_U_y_indexed_only<double>(lp::indexed_vector<double>&, const lp_settings&, vector<unsigned> &);
|
||||
template void lp::sparse_matrix<lp::mpq, lp::mpq>::solve_U_y_indexed_only<lp::mpq>(lp::indexed_vector<lp::mpq>&, const lp_settings &, vector<unsigned> &);
|
||||
#ifdef LEAN_DEBUG
|
||||
template bool sparse_matrix<double, double>::is_upper_triangular_and_maximums_are_set_correctly_in_rows(lp_settings&) const;
|
||||
template bool sparse_matrix<mpq, mpq>::is_upper_triangular_and_maximums_are_set_correctly_in_rows(lp_settings&) const;
|
||||
template bool sparse_matrix<mpq, numeric_pair<mpq> >::is_upper_triangular_and_maximums_are_set_correctly_in_rows(lp_settings&) const;
|
||||
#endif
|
||||
}
|
||||
template void lean::sparse_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::solve_U_y_indexed_only<lean::mpq>(lean::indexed_vector<lean::mpq>&, const lp_settings &, vector<unsigned> &);
|
||||
template void lean::sparse_matrix<lean::mpq, lean::mpq>::solve_U_y<lean::mpq>(vector<lean::mpq>&);
|
||||
template void lean::sparse_matrix<lean::mpq, lean::mpq>::double_solve_U_y<lean::mpq>(vector<lean::mpq >&);
|
||||
template void lean::sparse_matrix<double, double>::solve_U_y<double>(vector<double>&);
|
||||
template void lean::sparse_matrix<double, double>::double_solve_U_y<double>(vector<double>&);
|
||||
template void lean::sparse_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::solve_U_y<lean::numeric_pair<lean::mpq> >(vector<lean::numeric_pair<lean::mpq> >&);
|
||||
template void lean::sparse_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::double_solve_U_y<lean::numeric_pair<lean::mpq> >(vector<lean::numeric_pair<lean::mpq> >&);
|
||||
template void lean::sparse_matrix<double, double>::find_error_in_solution_U_y_indexed<double>(lean::indexed_vector<double>&, lean::indexed_vector<double>&, const vector<unsigned> &);
|
||||
template double lean::sparse_matrix<double, double>::dot_product_with_row<double>(unsigned int, lean::indexed_vector<double> const&) const;
|
||||
template void lean::sparse_matrix<lean::mpq, lean::mpq>::find_error_in_solution_U_y_indexed<lean::mpq>(lean::indexed_vector<lean::mpq>&, lean::indexed_vector<lean::mpq>&, const vector<unsigned> &);
|
||||
template lean::mpq lean::sparse_matrix<lean::mpq, lean::mpq>::dot_product_with_row<lean::mpq>(unsigned int, lean::indexed_vector<lean::mpq> const&) const;
|
||||
template void lean::sparse_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::find_error_in_solution_U_y_indexed<lean::mpq>(lean::indexed_vector<lean::mpq>&, lean::indexed_vector<lean::mpq>&, const vector<unsigned> &);
|
||||
template lean::mpq lean::sparse_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::dot_product_with_row<lean::mpq>(unsigned int, lean::indexed_vector<lean::mpq> const&) const;
|
||||
template void lean::sparse_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::find_error_in_solution_U_y_indexed<lean::numeric_pair<lean::mpq> >(lean::indexed_vector<lean::numeric_pair<lean::mpq> >&, lean::indexed_vector<lean::numeric_pair<lean::mpq> >&, const vector<unsigned> &);
|
||||
template lean::numeric_pair<lean::mpq> lean::sparse_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::dot_product_with_row<lean::numeric_pair<lean::mpq> >(unsigned int, lean::indexed_vector<lean::numeric_pair<lean::mpq> > const&) const;
|
||||
template void lean::sparse_matrix<lean::mpq, lean::mpq>::extend_and_sort_active_rows(vector<unsigned int> const&, vector<unsigned int>&);
|
||||
template void lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_U_y_indexed_only<lp::mpq>(lp::indexed_vector<lp::mpq>&, const lp_settings &, vector<unsigned> &);
|
||||
template void lp::sparse_matrix<lp::mpq, lp::mpq>::solve_U_y<lp::mpq>(vector<lp::mpq>&);
|
||||
template void lp::sparse_matrix<lp::mpq, lp::mpq>::double_solve_U_y<lp::mpq>(vector<lp::mpq >&);
|
||||
template void lp::sparse_matrix<double, double>::solve_U_y<double>(vector<double>&);
|
||||
template void lp::sparse_matrix<double, double>::double_solve_U_y<double>(vector<double>&);
|
||||
template void lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_U_y<lp::numeric_pair<lp::mpq> >(vector<lp::numeric_pair<lp::mpq> >&);
|
||||
template void lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::double_solve_U_y<lp::numeric_pair<lp::mpq> >(vector<lp::numeric_pair<lp::mpq> >&);
|
||||
template void lp::sparse_matrix<double, double>::find_error_in_solution_U_y_indexed<double>(lp::indexed_vector<double>&, lp::indexed_vector<double>&, const vector<unsigned> &);
|
||||
template double lp::sparse_matrix<double, double>::dot_product_with_row<double>(unsigned int, lp::indexed_vector<double> const&) const;
|
||||
template void lp::sparse_matrix<lp::mpq, lp::mpq>::find_error_in_solution_U_y_indexed<lp::mpq>(lp::indexed_vector<lp::mpq>&, lp::indexed_vector<lp::mpq>&, const vector<unsigned> &);
|
||||
template lp::mpq lp::sparse_matrix<lp::mpq, lp::mpq>::dot_product_with_row<lp::mpq>(unsigned int, lp::indexed_vector<lp::mpq> const&) const;
|
||||
template void lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::find_error_in_solution_U_y_indexed<lp::mpq>(lp::indexed_vector<lp::mpq>&, lp::indexed_vector<lp::mpq>&, const vector<unsigned> &);
|
||||
template lp::mpq lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::dot_product_with_row<lp::mpq>(unsigned int, lp::indexed_vector<lp::mpq> const&) const;
|
||||
template void lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::find_error_in_solution_U_y_indexed<lp::numeric_pair<lp::mpq> >(lp::indexed_vector<lp::numeric_pair<lp::mpq> >&, lp::indexed_vector<lp::numeric_pair<lp::mpq> >&, const vector<unsigned> &);
|
||||
template lp::numeric_pair<lp::mpq> lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::dot_product_with_row<lp::numeric_pair<lp::mpq> >(unsigned int, lp::indexed_vector<lp::numeric_pair<lp::mpq> > const&) const;
|
||||
template void lp::sparse_matrix<lp::mpq, lp::mpq>::extend_and_sort_active_rows(vector<unsigned int> const&, vector<unsigned int>&);
|
||||
|
||||
template void lean::sparse_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::extend_and_sort_active_rows(vector<unsigned int> const&, vector<unsigned int>&);
|
||||
template void lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::extend_and_sort_active_rows(vector<unsigned int> const&, vector<unsigned int>&);
|
||||
|
||||
template void lean::sparse_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::solve_U_y<lean::mpq>(vector<lean::mpq >&);
|
||||
template void lean::sparse_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::double_solve_U_y<lean::mpq>(vector<lean::mpq >&);
|
||||
template void lean::sparse_matrix< lean::mpq,lean::numeric_pair< lean::mpq> >::set(unsigned int,unsigned int, lean::mpq);
|
||||
template void lean::sparse_matrix<double, double>::solve_y_U_indexed(lean::indexed_vector<double>&, const lp_settings & );
|
||||
template void lean::sparse_matrix<lean::mpq, lean::mpq>::solve_y_U_indexed(lean::indexed_vector<lean::mpq>&, const lp_settings &);
|
||||
template void lean::sparse_matrix<lean::mpq, lean::numeric_pair<lean::mpq> >::solve_y_U_indexed(lean::indexed_vector<lean::mpq>&, const lp_settings &);
|
||||
template void lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_U_y<lp::mpq>(vector<lp::mpq >&);
|
||||
template void lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::double_solve_U_y<lp::mpq>(vector<lp::mpq >&);
|
||||
template void lp::sparse_matrix< lp::mpq,lp::numeric_pair< lp::mpq> >::set(unsigned int,unsigned int, lp::mpq);
|
||||
template void lp::sparse_matrix<double, double>::solve_y_U_indexed(lp::indexed_vector<double>&, const lp_settings & );
|
||||
template void lp::sparse_matrix<lp::mpq, lp::mpq>::solve_y_U_indexed(lp::indexed_vector<lp::mpq>&, const lp_settings &);
|
||||
template void lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_y_U_indexed(lp::indexed_vector<lp::mpq>&, const lp_settings &);
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "util/debug.h"
|
||||
#include "util/lp/lp_utils.h"
|
||||
#include "util/lp/lp_settings.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
|
||||
template <typename T>
|
||||
class sparse_vector {
|
||||
|
@ -27,7 +27,7 @@ public:
|
|||
}
|
||||
#endif
|
||||
void divide(T const & a) {
|
||||
lean_assert(!lp_settings::is_eps_small_general(a, 1e-12));
|
||||
lp_assert(!lp_settings::is_eps_small_general(a, 1e-12));
|
||||
for (auto & t : m_data) { t.second /= a; }
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "util/lp/eta_matrix.h"
|
||||
#include "util/lp/binary_heap_upair_queue.h"
|
||||
#include "util/lp/sparse_matrix.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T, typename X>
|
||||
class square_dense_submatrix : public tail_matrix<T, X> {
|
||||
// the submatrix uses the permutations of the parent matrix to access the elements
|
||||
|
@ -30,11 +30,11 @@ class square_dense_submatrix : public tail_matrix<T, X> {
|
|||
ref(unsigned i, square_dense_submatrix & s) :
|
||||
m_i_offset((i - s.m_index_start) * s.m_dim), m_s(s){}
|
||||
T & operator[] (unsigned j) {
|
||||
lean_assert(j >= m_s.m_index_start);
|
||||
lp_assert(j >= m_s.m_index_start);
|
||||
return m_s.m_v[m_i_offset + m_s.adjust_column(j) - m_s.m_index_start];
|
||||
}
|
||||
const T & operator[] (unsigned j) const {
|
||||
lean_assert(j >= m_s.m_index_start);
|
||||
lp_assert(j >= m_s.m_index_start);
|
||||
return m_s.m_v[m_i_offset + m_s.adjust_column(j) - m_s.m_index_start];
|
||||
}
|
||||
};
|
||||
|
@ -58,8 +58,8 @@ public:
|
|||
bool is_dense() const { return true; }
|
||||
|
||||
ref operator[] (unsigned i) {
|
||||
lean_assert(i >= m_index_start);
|
||||
lean_assert(i < m_parent->dimension());
|
||||
lp_assert(i >= m_index_start);
|
||||
lp_assert(i < m_parent->dimension());
|
||||
return ref(i, *this);
|
||||
}
|
||||
|
||||
|
@ -148,7 +148,7 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
lean_assert(wcopy.is_OK());
|
||||
lp_assert(wcopy.is_OK());
|
||||
apply_from_right(w.m_data);
|
||||
w.m_index.clear();
|
||||
if (numeric_traits<T>::precise()) {
|
||||
|
@ -167,11 +167,11 @@ public:
|
|||
}
|
||||
}
|
||||
#else
|
||||
lean_assert(w.is_OK());
|
||||
lean_assert(m_work_vector.is_OK());
|
||||
lp_assert(w.is_OK());
|
||||
lp_assert(m_work_vector.is_OK());
|
||||
m_work_vector.resize(w.data_size());
|
||||
m_work_vector.clear();
|
||||
lean_assert(m_work_vector.is_OK());
|
||||
lp_assert(m_work_vector.is_OK());
|
||||
unsigned end = m_index_start + m_dim;
|
||||
for (unsigned k : w.m_index) {
|
||||
// find j such that k = adjust_row_inverse(j)
|
||||
|
@ -188,7 +188,7 @@ public:
|
|||
}
|
||||
}
|
||||
m_work_vector.clean_up();
|
||||
lean_assert(m_work_vector.is_OK());
|
||||
lp_assert(m_work_vector.is_OK());
|
||||
w = m_work_vector;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
#include "util/vector.h"
|
||||
#include "util/lp/square_dense_submatrix.h"
|
||||
namespace lean {
|
||||
namespace lp {
|
||||
template <typename T, typename X>
|
||||
square_dense_submatrix<T, X>::square_dense_submatrix (sparse_matrix<T, X> *parent_matrix, unsigned index_start) :
|
||||
m_index_start(index_start),
|
||||
|
@ -18,7 +18,7 @@ square_dense_submatrix<T, X>::square_dense_submatrix (sparse_matrix<T, X> *paren
|
|||
unsigned row = parent_matrix->adjust_row(i);
|
||||
for (auto & iv : parent_matrix->get_row_values(row)) {
|
||||
unsigned j = parent_matrix->adjust_column_inverse(iv.m_index);
|
||||
lean_assert(j>= m_index_start);
|
||||
lp_assert(j>= m_index_start);
|
||||
m_v[row_offset + j] = iv.m_value;
|
||||
}
|
||||
row_offset += m_dim;
|
||||
|
@ -43,7 +43,7 @@ template <typename T, typename X> void square_dense_submatrix<T, X>::init(sparse
|
|||
template <typename T, typename X> int square_dense_submatrix<T, X>::find_pivot_column_in_row(unsigned i) const {
|
||||
int j = -1;
|
||||
T max = zero_of_type<T>();
|
||||
lean_assert(i >= m_index_start);
|
||||
lp_assert(i >= m_index_start);
|
||||
unsigned row_start = (i - m_index_start) * m_dim;
|
||||
for (unsigned k = i; k < m_parent->dimension(); k++) {
|
||||
unsigned col = adjust_column(k); // this is where the column is in the row
|
||||
|
@ -64,14 +64,14 @@ template <typename T, typename X> void square_dense_submatrix<T, X>::pivot(un
|
|||
}
|
||||
|
||||
template <typename T, typename X> void square_dense_submatrix<T, X>::pivot_row_to_row(unsigned i, unsigned row, lp_settings & settings) {
|
||||
lean_assert(i < row);
|
||||
lp_assert(i < row);
|
||||
unsigned pj = adjust_column(i); // the pivot column
|
||||
unsigned pjd = pj - m_index_start;
|
||||
unsigned pivot_row_offset = (i-m_index_start)*m_dim;
|
||||
T pivot = m_v[pivot_row_offset + pjd];
|
||||
unsigned row_offset= (row-m_index_start)*m_dim;
|
||||
T m = m_v[row_offset + pjd];
|
||||
lean_assert(!is_zero(pivot));
|
||||
lp_assert(!is_zero(pivot));
|
||||
m_v[row_offset + pjd] = -m * pivot; // creating L matrix
|
||||
for (unsigned j = m_index_start; j < m_parent->dimension(); j++) {
|
||||
if (j == pj) {
|
||||
|
@ -94,7 +94,7 @@ template <typename T, typename X> void square_dense_submatrix<T, X>::divide_r
|
|||
unsigned pj = adjust_column(i); // the pivot column
|
||||
unsigned irow_offset = (i - m_index_start) * m_dim;
|
||||
T pivot = m_v[irow_offset + pj - m_index_start];
|
||||
lean_assert(!is_zero(pivot));
|
||||
lp_assert(!is_zero(pivot));
|
||||
for (unsigned k = m_index_start; k < m_parent->dimension(); k++) {
|
||||
if (k == pj){
|
||||
m_v[irow_offset++] = one_of_type<T>() / pivot; // creating the L matrix diagonal
|
||||
|
@ -158,7 +158,7 @@ template <typename T, typename X> void square_dense_submatrix<T, X>::push_new
|
|||
template <typename T, typename X>
|
||||
template <typename L>
|
||||
L square_dense_submatrix<T, X>::row_by_vector_product(unsigned i, const vector<L> & v) {
|
||||
lean_assert(i >= m_index_start);
|
||||
lp_assert(i >= m_index_start);
|
||||
|
||||
unsigned row_in_subm = i - m_index_start;
|
||||
unsigned row_offset = row_in_subm * m_dim;
|
||||
|
@ -171,7 +171,7 @@ L square_dense_submatrix<T, X>::row_by_vector_product(unsigned i, const vector<L
|
|||
template <typename T, typename X>
|
||||
template <typename L>
|
||||
L square_dense_submatrix<T, X>::column_by_vector_product(unsigned j, const vector<L> & v) {
|
||||
lean_assert(j >= m_index_start);
|
||||
lp_assert(j >= m_index_start);
|
||||
|
||||
unsigned offset = j - m_index_start;
|
||||
L r = zero_of_type<L>();
|
||||
|
@ -182,7 +182,7 @@ L square_dense_submatrix<T, X>::column_by_vector_product(unsigned j, const vecto
|
|||
template <typename T, typename X>
|
||||
template <typename L>
|
||||
L square_dense_submatrix<T, X>::row_by_indexed_vector_product(unsigned i, const indexed_vector<L> & v) {
|
||||
lean_assert(i >= m_index_start);
|
||||
lp_assert(i >= m_index_start);
|
||||
|
||||
unsigned row_in_subm = i - m_index_start;
|
||||
unsigned row_offset = row_in_subm * m_dim;
|
||||
|
@ -249,8 +249,8 @@ void square_dense_submatrix<T, X>::apply_from_left_local(indexed_vector<L> & w,
|
|||
#ifdef LEAN_DEBUG
|
||||
// cout << "w final" << endl;
|
||||
// print_vector(w.m_data);
|
||||
// lean_assert(vectors_are_equal<T>(deb_w, w.m_data));
|
||||
// lean_assert(w.is_OK());
|
||||
// lp_assert(vectors_are_equal<T>(deb_w, w.m_data));
|
||||
// lp_assert(w.is_OK());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -280,16 +280,16 @@ void square_dense_submatrix<T, X>::apply_from_left_to_vector(vector<L> & w) {
|
|||
#ifdef LEAN_DEBUG
|
||||
// cout << "w final" << endl;
|
||||
// print_vector(w.m_data);
|
||||
// lean_assert(vectors_are_equal<L>(deb_w, w));
|
||||
// lp_assert(vectors_are_equal<L>(deb_w, w));
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T, typename X> bool square_dense_submatrix<T, X>::is_L_matrix() const {
|
||||
#ifdef LEAN_DEBUG
|
||||
lean_assert(m_row_permutation.is_identity());
|
||||
lp_assert(m_row_permutation.is_identity());
|
||||
for (unsigned i = 0; i < m_parent->dimension(); i++) {
|
||||
if (i < m_index_start) {
|
||||
lean_assert(m_column_permutation[i] == i);
|
||||
lp_assert(m_column_permutation[i] == i);
|
||||
continue;
|
||||
}
|
||||
unsigned row_offs = (i-m_index_start)*m_dim;
|
||||
|
@ -297,9 +297,9 @@ template <typename T, typename X> bool square_dense_submatrix<T, X>::is_L_mat
|
|||
unsigned j = m_index_start + k;
|
||||
unsigned jex = adjust_column_inverse(j);
|
||||
if (jex > i) {
|
||||
lean_assert(is_zero(m_v[row_offs + k]));
|
||||
lp_assert(is_zero(m_v[row_offs + k]));
|
||||
} else if (jex == i) {
|
||||
lean_assert(!is_zero(m_v[row_offs + k]));
|
||||
lp_assert(!is_zero(m_v[row_offs + k]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -327,7 +327,7 @@ template <typename T, typename X> void square_dense_submatrix<T, X>::apply_from_
|
|||
}
|
||||
w = t;
|
||||
#ifdef LEAN_DEBUG
|
||||
// lean_assert(vector_are_equal<T>(deb_w, w));
|
||||
// lp_assert(vector_are_equal<T>(deb_w, w));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue