-/********************* */
-/*! \file tableau.cpp
- ** \verbatim
- ** Original author: taking
- ** Major contributors: none
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009, 2010 The Analysis of Computer Systems Group (ACSys)
- ** Courant Institute of Mathematical Sciences
- ** New York University
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief [[ Add one-line brief description here ]]
- **
- ** [[ Add lengthier description here ]]
- ** \todo document this file
- **/
+/******************************************************************************
+ * Top contributors (to current version):
+ * Tim King
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved. See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * [[ Add one-line brief description here ]]
+ *
+ * [[ Add lengthier description here ]]
+ * \todo document this file
+ */
+
+#include "base/output.h"
+#include "theory/arith/tableau.h"
+using namespace std;
+namespace cvc5 {
+namespace theory {
+namespace arith {
-#include "theory/arith/tableau.h"
-using namespace CVC4;
-using namespace CVC4::theory;
-using namespace CVC4::theory::arith;
+void Tableau::pivot(ArithVar oldBasic, ArithVar newBasic, CoefficientChangeCallback& cb){
+ Assert(isBasic(oldBasic));
+ Assert(!isBasic(newBasic));
+ Assert(d_mergeBuffer.empty());
-Row::Row(ArithVar basic,
- const std::vector< Rational >& coefficients,
- const std::vector< ArithVar >& variables):
- d_x_i(basic),
- d_coeffs(){
+ Debug("tableau") << "Tableau::pivot(" << oldBasic <<", " << newBasic <<")" << endl;
- Assert(coefficients.size() == variables.size() );
+ RowIndex ridx = basicToRowIndex(oldBasic);
- std::vector<Rational>::const_iterator coeffIter = coefficients.begin();
- std::vector<Rational>::const_iterator coeffEnd = coefficients.end();
- std::vector<ArithVar>::const_iterator varIter = variables.begin();
+ rowPivot(oldBasic, newBasic, cb);
+ Assert(ridx == basicToRowIndex(newBasic));
- for(; coeffIter != coeffEnd; ++coeffIter, ++varIter){
- const Rational& coeff = *coeffIter;
- ArithVar var_i = *varIter;
+ loadRowIntoBuffer(ridx);
- Assert(var_i != d_x_i);
- Assert(!has(var_i));
- Assert(coeff != Rational(0,1));
+ ColIterator colIter = colIterator(newBasic);
+ while(!colIter.atEnd()){
+ EntryID id = colIter.getID();
+ Entry& entry = d_entries.get(id);
- d_coeffs[var_i] = coeff;
- Assert(d_coeffs[var_i] != Rational(0,1));
- }
-}
-void Row::substitute(Row& row_s){
- ArithVar x_s = row_s.basicVar();
-
- Assert(has(x_s));
- Assert(x_s != d_x_i);
-
- Rational zero(0,1);
-
- Rational a_rs = lookup(x_s);
- Assert(a_rs != zero);
- d_coeffs.erase(x_s);
-
- for(iterator iter = row_s.begin(), iter_end = row_s.end();
- iter != iter_end; ++iter){
- ArithVar x_j = iter->first;
- Rational a_sj = iter->second;
- a_sj *= a_rs;
- CoefficientTable::iterator coeff_iter = d_coeffs.find(x_j);
-
- if(coeff_iter != d_coeffs.end()){
- coeff_iter->second += a_sj;
- if(coeff_iter->second == zero){
- d_coeffs.erase(coeff_iter);
- }
+ ++colIter; //needs to be incremented before the variable is removed
+ if(entry.getRowIndex() == ridx){ continue; }
+
+ RowIndex to = entry.getRowIndex();
+ Rational coeff = entry.getCoefficient();
+ if(cb.canUseRow(to)){
+ rowPlusBufferTimesConstant(to, coeff, cb);
}else{
- d_coeffs.insert(std::make_pair(x_j,a_sj));
+ rowPlusBufferTimesConstant(to, coeff);
}
}
+ clearBuffer();
+
+ //Clear the column for used for this variable
+
+ Assert(d_mergeBuffer.empty());
+ Assert(!isBasic(oldBasic));
+ Assert(isBasic(newBasic));
+ Assert(getColLength(newBasic) == 1);
}
-void Row::pivot(ArithVar x_j){
- Rational negInverseA_rs = -(lookup(x_j).inverse());
- d_coeffs[d_x_i] = Rational(Integer(-1));
- d_coeffs.erase(x_j);
+/**
+ * Changes basic to newbasic (a variable on the row).
+ */
+void Tableau::rowPivot(ArithVar basicOld, ArithVar basicNew, CoefficientChangeCallback& cb){
+ Assert(isBasic(basicOld));
+ Assert(!isBasic(basicNew));
- d_x_i = x_j;
+ RowIndex rid = basicToRowIndex(basicOld);
- for(iterator nonbasicIter = begin(), nonbasicIter_end = end();
- nonbasicIter != nonbasicIter_end; ++nonbasicIter){
- nonbasicIter->second *= negInverseA_rs;
- }
+ EntryID newBasicID = findOnRow(rid, basicNew);
-}
+ Assert(newBasicID != ENTRYID_SENTINEL);
+
+ Tableau::Entry& newBasicEntry = d_entries.get(newBasicID);
+ const Rational& a_rs = newBasicEntry.getCoefficient();
+ int a_rs_sgn = a_rs.sgn();
+ Rational negInverseA_rs = -(a_rs.inverse());
-void Row::printRow(){
- Debug("tableau") << d_x_i << " ";
- for(iterator nonbasicIter = d_coeffs.begin();
- nonbasicIter != d_coeffs.end();
- ++nonbasicIter){
- ArithVar nb = nonbasicIter->first;
- Debug("tableau") << "{" << nb << "," << d_coeffs[nb] << "}";
+ for(RowIterator i = basicRowIterator(basicOld); !i.atEnd(); ++i){
+ EntryID id = i.getID();
+ Tableau::Entry& entry = d_entries.get(id);
+
+ entry.getCoefficient() *= negInverseA_rs;
}
- Debug("tableau") << std::endl;
+
+ d_basic2RowIndex.remove(basicOld);
+ d_basic2RowIndex.set(basicNew, rid);
+ d_rowIndex2basic.set(rid, basicNew);
+
+ cb.multiplyRow(rid, -a_rs_sgn);
}
-void Tableau::addRow(ArithVar basicVar,
- const std::vector<Rational>& coeffs,
- const std::vector<ArithVar>& variables){
+void Tableau::addRow(ArithVar basic,
+ const std::vector<Rational>& coefficients,
+ const std::vector<ArithVar>& variables)
+{
+ Assert(basic < getNumColumns());
+ Assert(debugIsASet(variables));
+ Assert(coefficients.size() == variables.size());
+ Assert(!isBasic(basic));
+
+ RowIndex newRow = Matrix<Rational>::addRow(coefficients, variables);
+ addEntry(newRow, basic, Rational(-1));
+
+ Assert(!d_basic2RowIndex.isKey(basic));
+ Assert(!d_rowIndex2basic.isKey(newRow));
- Assert(coeffs.size() == variables.size());
- Assert(d_basicManager.isBasic(basicVar));
+ d_basic2RowIndex.set(basic, newRow);
+ d_rowIndex2basic.set(newRow, basic);
- //The new basic variable cannot already be a basic variable
- Assert(!isActiveBasicVariable(basicVar));
- d_activeBasicVars.insert(basicVar);
- Row* row_current = new Row(basicVar,coeffs,variables);
- d_rowsTable[basicVar] = row_current;
- //A variable in the row may have been made non-basic already.
- //If this is the case we fake pivoting this variable
- std::vector<Rational>::const_iterator coeffsIter = coeffs.begin();
- std::vector<Rational>::const_iterator coeffsEnd = coeffs.end();
+ if(Debug.isOn("matrix")){ printMatrix(); }
- std::vector<ArithVar>::const_iterator varsIter = variables.begin();
+ NoEffectCCCB noeffect;
+ NoEffectCCCB* nep = &noeffect;
+ CoefficientChangeCallback* cccb = static_cast<CoefficientChangeCallback*>(nep);
- for( ; coeffsIter != coeffsEnd; ++coeffsIter, ++ varsIter){
+ vector<Rational>::const_iterator coeffIter = coefficients.begin();
+ vector<ArithVar>::const_iterator varsIter = variables.begin();
+ vector<ArithVar>::const_iterator varsEnd = variables.end();
+ for(; varsIter != varsEnd; ++coeffIter, ++varsIter){
ArithVar var = *varsIter;
- if(d_basicManager.isBasic(var)){
- if(!isActiveBasicVariable(var)){
- reinjectBasic(var);
- }
- Assert(isActiveBasicVariable(var));
+ if(isBasic(var)){
+ Rational coeff = *coeffIter;
- Row* row_var = lookup(var);
- row_current->substitute(*row_var);
+ RowIndex ri = basicToRowIndex(var);
+
+ loadRowIntoBuffer(ri);
+ rowPlusBufferTimesConstant(newRow, coeff, *cccb);
+ clearBuffer();
}
}
-}
-void Tableau::pivot(ArithVar x_r, ArithVar x_s){
- Assert(d_basicManager.isBasic(x_r));
- Assert(!d_basicManager.isBasic(x_s));
+ if(Debug.isOn("matrix")) { printMatrix(); }
- Row* row_s = lookup(x_r);
- Assert(row_s->has(x_s));
+ Assert(debugNoZeroCoefficients(newRow));
+ Assert(debugMatchingCountsForRow(newRow));
+ Assert(getColLength(basic) == 1);
+}
- //Swap x_r and x_s in d_activeRows
- d_rowsTable[x_s] = row_s;
- d_rowsTable[x_r] = NULL;
+void Tableau::removeBasicRow(ArithVar basic){
+ RowIndex rid = basicToRowIndex(basic);
- d_activeBasicVars.erase(x_r);
- d_basicManager.makeNonbasic(x_r);
+ removeRow(rid);
+ d_basic2RowIndex.remove(basic);
+ d_rowIndex2basic.remove(rid);
+}
- d_activeBasicVars.insert(x_s);
- d_basicManager.makeBasic(x_s);
+void Tableau::substitutePlusTimesConstant(ArithVar to, ArithVar from, const Rational& mult, CoefficientChangeCallback& cb){
+ if(!mult.isZero()){
+ RowIndex to_idx = basicToRowIndex(to);
+ addEntry(to_idx, from, mult); // Add an entry to be cancelled out
+ RowIndex from_idx = basicToRowIndex(from);
- row_s->pivot(x_s);
+ cb.update(to_idx, from, 0, mult.sgn());
- for(ArithVarSet::iterator basicIter = begin(), endIter = end();
- basicIter != endIter; ++basicIter){
- ArithVar basic = *basicIter;
- Row* row_k = lookup(basic);
- if(row_k->has(x_s)){
- d_activityMonitor.increaseActivity(basic, 30);
- row_k->substitute(*row_s);
- }
+ loadRowIntoBuffer(from_idx);
+ rowPlusBufferTimesConstant(to_idx, mult, cb);
+ clearBuffer();
}
}
-void Tableau::printTableau(){
- Debug("tableau") << "Tableau::d_activeRows" << endl;
-
- typedef RowsTable::iterator table_iter;
- for(table_iter rowIter = d_rowsTable.begin(), end = d_rowsTable.end();
- rowIter != end; ++rowIter){
- Row* row_k = *rowIter;
- if(row_k != NULL){
- row_k->printRow();
- }
+
+uint32_t Tableau::rowComplexity(ArithVar basic) const{
+ uint32_t complexity = 0;
+ for(RowIterator i = basicRowIterator(basic); !i.atEnd(); ++i){
+ const Entry& e = *i;
+ complexity += e.getCoefficient().complexity();
}
+ return complexity;
}
-
-void Tableau::updateRow(Row* row){
- for(Row::iterator i=row->begin(), endIter = row->end(); i != endIter; ){
- ArithVar var = i->first;
- ++i;
- if(d_basicManager.isBasic(var)){
- Row* row_var = isActiveBasicVariable(var) ? lookup(var) : lookupEjected(var);
-
- Assert(row_var != row);
- row->substitute(*row_var);
-
- i = row->begin();
- endIter = row->end();
- }
+double Tableau::avgRowComplexity() const{
+ double sum = 0;
+ uint32_t rows = 0;
+ for(BasicIterator i = beginBasic(), i_end = endBasic(); i != i_end; ++i){
+ sum += rowComplexity(*i);
+ rows++;
}
+ return (rows == 0) ? 0 : (sum/rows);
}
+
+void Tableau::printBasicRow(ArithVar basic, std::ostream& out){
+ printRow(basicToRowIndex(basic), out);
+}
+
+} // namespace arith
+} // namespace theory
+} // namespace cvc5