Improved garbage collection for TheoryArith. The merges all of the code over from...
authorTim King <taking@cs.nyu.edu>
Wed, 5 Dec 2012 21:45:12 +0000 (21:45 +0000)
committerTim King <taking@cs.nyu.edu>
Wed, 5 Dec 2012 21:45:12 +0000 (21:45 +0000)
15 files changed:
src/theory/arith/Makefile.am
src/theory/arith/arithvar.cpp [new file with mode: 0644]
src/theory/arith/arithvar.h
src/theory/arith/arithvar_node_map.h
src/theory/arith/congruence_manager.cpp
src/theory/arith/constraint.cpp
src/theory/arith/constraint.h
src/theory/arith/linear_equality.cpp
src/theory/arith/linear_equality.h
src/theory/arith/matrix.cpp
src/theory/arith/matrix.h
src/theory/arith/theory_arith.cpp
src/theory/arith/theory_arith.h
src/theory/quantifiers/inst_strategy_cbqi.cpp
src/util/dense_map.h

index b2d1b9f09a6101ae90e197a567409c8a59f095e2..76d8d9083b1d5ce95327c0e39c3590cecac8bac8 100644 (file)
@@ -9,6 +9,7 @@ libarith_la_SOURCES = \
        theory_arith_type_rules.h \
        type_enumerator.h \
        arithvar.h \
+       arithvar.cpp \
        arith_rewriter.h \
        arith_rewriter.cpp \
        arith_static_learner.h \
diff --git a/src/theory/arith/arithvar.cpp b/src/theory/arith/arithvar.cpp
new file mode 100644 (file)
index 0000000..76b143f
--- /dev/null
@@ -0,0 +1,13 @@
+
+#include "theory/arith/arithvar.h"
+#include <limits>
+
+namespace CVC4 {
+namespace theory {
+namespace arith {
+
+const ArithVar ARITHVAR_SENTINEL = std::numeric_limits<ArithVar>::max();
+
+}/* CVC4::theory::arith namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
index eac238cba9346fb199540a9479e8fe7eccb6d320..95614a0110cb761fe6bebe6178c998c29669bc87 100644 (file)
 #ifndef __CVC4__THEORY__ARITH__ARITHVAR_H
 #define __CVC4__THEORY__ARITH__ARITHVAR_H
 
-#include <limits>
 #include <ext/hash_map>
 #include "expr/node.h"
 #include "context/cdhashset.h"
-#include "context/cdhashset.h"
 
 #include "util/index.h"
+#include "util/dense_map.h"
 
 namespace CVC4 {
 namespace theory {
 namespace arith {
 
 typedef Index ArithVar;
-const ArithVar ARITHVAR_SENTINEL = std::numeric_limits<ArithVar>::max();
+extern const ArithVar ARITHVAR_SENTINEL;
 
 //Maps from Nodes -> ArithVars, and vice versa
 typedef __gnu_cxx::hash_map<Node, ArithVar, NodeHashFunction> NodeToArithVarMap;
-typedef __gnu_cxx::hash_map<ArithVar, Node> ArithVarToNodeMap;
+typedef DenseMap<Node> ArithVarToNodeMap;
 
 /**
  * ArithVarCallBack provides a mechanism for agreeing on callbacks while
index 3a2cff2363024abceb970c2ce1a3d008122d2eb4..e0e589e577098765867e8742cf390327caf9b72d 100644 (file)
@@ -40,31 +40,50 @@ private:
   ArithVarToNodeMap d_arithVarToNodeMap;
 
 public:
+
+  typedef ArithVarToNodeMap::const_iterator var_iterator;
+
   ArithVarNodeMap() {}
 
   inline bool hasArithVar(TNode x) const {
     return d_nodeToArithVarMap.find(x) != d_nodeToArithVarMap.end();
   }
 
+  inline bool hasNode(ArithVar a) const {
+    return d_arithVarToNodeMap.isKey(a);
+  }
+
   inline ArithVar asArithVar(TNode x) const{
     Assert(hasArithVar(x));
     Assert((d_nodeToArithVarMap.find(x))->second <= ARITHVAR_SENTINEL);
     return (d_nodeToArithVarMap.find(x))->second;
   }
+
   inline Node asNode(ArithVar a) const{
-    Assert(d_arithVarToNodeMap.find(a) != d_arithVarToNodeMap.end());
-    return (d_arithVarToNodeMap.find(a))->second;
+    Assert(hasNode(a));
+    return d_arithVarToNodeMap[a];
   }
 
   inline void setArithVar(TNode x, ArithVar a){
     Assert(!hasArithVar(x));
-    Assert(d_arithVarToNodeMap.find(a) == d_arithVarToNodeMap.end());
-    d_arithVarToNodeMap[a] = x;
+    Assert(!d_arithVarToNodeMap.isKey(a));
+    d_arithVarToNodeMap.set(a, x);
     d_nodeToArithVarMap[x] = a;
   }
 
-  const ArithVarToNodeMap& getArithVarToNodeMap() const {
-    return d_arithVarToNodeMap;
+  inline void remove(ArithVar x){
+    Assert(hasNode(x));
+    Node node = asNode(x);
+
+    d_nodeToArithVarMap.erase(d_nodeToArithVarMap.find(node));
+    d_arithVarToNodeMap.remove(x);
+  }
+
+  var_iterator var_begin() const {
+    return d_arithVarToNodeMap.begin();
+  }
+  var_iterator var_end() const {
+    return d_arithVarToNodeMap.end();
   }
 
 };/* class ArithVarNodeMap */
index 5ee250c09204bfc294a923f767bb924a245f3666..de4c7eac33ac584aa0e6dc5f62b9afc53267bfd6 100644 (file)
@@ -272,7 +272,7 @@ void ArithCongruenceManager::addWatchedPair(ArithVar s, TNode x, TNode y){
   d_watchedVariables.add(s);
 
   Node eq = x.eqNode(y);
-  d_watchedEqualities[s] = eq;
+  d_watchedEqualities.set(s, eq);
 }
 
 void ArithCongruenceManager::assertionToEqualityEngine(bool isEquality, ArithVar s, TNode reason){
index 392d04f6c8c4c2862a4f5a2221ba9757fc5a07d7..cf3aeafee0e112c9b08faf1e5e61f54c7899a41f 100644 (file)
@@ -371,6 +371,10 @@ void ConstraintValue::setAssertedToTheTheory(TNode witness) {
   d_database->pushAssertionOrderWatch(this, witness);
 }
 
+// bool ConstraintValue::isPsuedoConstraint() const {
+//   return d_proof == d_database->d_psuedoConstraintProof;
+// }
+
 bool ConstraintValue::isSelfExplaining() const {
   return d_proof == d_database->d_selfExplainingProof;
 }
@@ -481,6 +485,9 @@ ConstraintDatabase::ConstraintDatabase(context::Context* satContext, context::Co
 
   d_equalityEngineProof = d_proofs.size();
   d_proofs.push_back(NullConstraint);
+
+  // d_psuedoConstraintProof = d_proofs.size();
+  // d_proofs.push_back(NullConstraint);
 }
 
 Constraint ConstraintDatabase::getConstraint(ArithVar v, ConstraintType t, const DeltaRational& r){
@@ -566,8 +573,32 @@ ConstraintDatabase::Statistics::~Statistics(){
 }
 
 void ConstraintDatabase::addVariable(ArithVar v){
-  Assert(v == d_varDatabases.size());
-  d_varDatabases.push_back(new PerVariableDatabase(v));
+  if(d_reclaimable.isMember(v)){
+    SortedConstraintMap& scm = getVariableSCM(v);
+
+    std::vector<Constraint> constraintList;
+
+    for(SortedConstraintMapIterator i = scm.begin(), end = scm.end(); i != end; ++i){
+      (i->second).push_into(constraintList);
+    }
+    while(!constraintList.empty()){
+      Constraint c = constraintList.back();
+      constraintList.pop_back();
+      Assert(c->safeToGarbageCollect());
+      delete c;
+    }
+    Assert(scm.empty());
+
+    d_reclaimable.remove(v);
+  }else{
+    Assert(v == d_varDatabases.size());
+    d_varDatabases.push_back(new PerVariableDatabase(v));
+  }
+}
+
+void ConstraintDatabase::removeVariable(ArithVar v){
+  Assert(!d_reclaimable.isMember(v));
+  d_reclaimable.add(v);
 }
 
 bool ConstraintValue::safeToGarbageCollect() const{
@@ -802,6 +833,13 @@ void ConstraintValue::impliedBy(const std::vector<Constraint>& b){
   }
 }
 
+// void ConstraintValue::setPsuedoConstraint(){
+//   Assert(truthIsUnknown());
+//   Assert(!hasLiteral());
+
+//   d_database->pushProofWatch(this, d_database->d_psuedoConstraintProof);
+// }
+
 void ConstraintValue::setEqualityEngineProof(){
   Assert(truthIsUnknown());
   Assert(hasLiteral());
@@ -818,6 +856,7 @@ void ConstraintValue::markAsTrue(){
 void ConstraintValue::markAsTrue(Constraint imp){
   Assert(truthIsUnknown());
   Assert(imp->hasProof());
+  //Assert(!imp->isPsuedoConstraint());
 
   d_database->d_proofs.push_back(NullConstraint);
   d_database->d_proofs.push_back(imp);
@@ -829,6 +868,8 @@ void ConstraintValue::markAsTrue(Constraint impA, Constraint impB){
   Assert(truthIsUnknown());
   Assert(impA->hasProof());
   Assert(impB->hasProof());
+  //Assert(!impA->isPsuedoConstraint());
+  //Assert(!impB->isPsuedoConstraint());
 
   d_database->d_proofs.push_back(NullConstraint);
   d_database->d_proofs.push_back(impA);
@@ -845,6 +886,7 @@ void ConstraintValue::markAsTrue(const vector<Constraint>& a){
   for(vector<Constraint>::const_iterator i = a.begin(), end = a.end(); i != end; ++i){
     Constraint c_i = *i;
     Assert(c_i->hasProof());
+    //Assert(!c_i->isPsuedoConstraint());
     d_database->d_proofs.push_back(c_i);
   }
 
@@ -861,6 +903,7 @@ SortedConstraintMap& ConstraintValue::constraintSet() const{
 bool ConstraintValue::proofIsEmpty() const{
   Assert(hasProof());
   bool result = d_database->d_proofs[d_proof] == NullConstraint;
+  //Assert((!result) || isSelfExplaining() || hasEqualityEngineProof() || isPsuedoConstraint());
   Assert((!result) || isSelfExplaining() || hasEqualityEngineProof());
   return result;
 }
@@ -869,6 +912,7 @@ void ConstraintValue::explainBefore(NodeBuilder<>& nb, AssertionOrder order) con
   Assert(hasProof());
   Assert(!isSelfExplaining() || assertedToTheTheory());
 
+
   if(assertedBefore(order)){
     nb << getWitness();
   }else if(hasEqualityEngineProof()){
index 331fd2bcb691214c2ed848555dedba5c5e00c5fd..52aa5a5cedd2c4eaae383ed240d60f447895aaef 100644 (file)
@@ -485,6 +485,15 @@ public:
   void setEqualityEngineProof();
   bool hasEqualityEngineProof() const;
 
+
+  /**
+   * There cannot be a literal associated with this constraint.
+   * The explanation is the constant true.
+   * explainInto() does nothing.
+   */
+  //void setPsuedoConstraint();
+  //bool isPsuedoConstraint() const;
+
   /**
    * Returns a explanation of the constraint that is appropriate for conflicts.
    *
@@ -694,6 +703,14 @@ private:
    */
   ProofId d_equalityEngineProof;
 
+  /**
+   * Marks a node as being true always.
+   * This is only okay for purely internal things.
+   *
+   * This is a special proof that is always a member of the list.
+   */
+  //ProofId d_psuedoConstraintProof;
+
   typedef context::CDList<Constraint, ConstraintValue::ProofCleanup> ProofCleanupList;
   typedef context::CDList<Constraint, ConstraintValue::CanBePropagatedCleanup> CBPList;
   typedef context::CDList<Constraint, ConstraintValue::AssertionOrderCleanup> AOList;
@@ -817,6 +834,7 @@ public:
 
   void addVariable(ArithVar v);
   bool variableDatabaseIsSetup(ArithVar v) const;
+  void removeVariable(ArithVar v);
 
   Node eeExplain(ConstConstraint c) const;
   void eeExplain(ConstConstraint c, NodeBuilder<>& nb) const;
@@ -881,6 +899,8 @@ public:
 private:
   void raiseUnateConflict(Constraint ant, Constraint cons);
 
+  DenseSet d_reclaimable;
+
   class Statistics {
   public:
     IntStat d_unatePropagateCalls;
index 360e45289ad3a48be10b426ce0dc52809cca1e81..5063a05c7686d2d41bef51e6784055e54aecbf91 100644 (file)
@@ -80,7 +80,7 @@ void LinearEqualityModule::update(ArithVar x_i, const DeltaRational& v){
   if(Debug.isOn("paranoid:check_tableau")){  debugCheckTableau(); }
 }
 
-void LinearEqualityModule::pivotAndUpdate(ArithVar x_i, ArithVar x_j, DeltaRational& v){
+void LinearEqualityModule::pivotAndUpdate(ArithVar x_i, ArithVar x_j, const DeltaRational& v){
   Assert(x_i != x_j);
 
   TimerStat::CodeTimer codeTimer(d_statistics.d_pivotTime);
@@ -188,6 +188,23 @@ void LinearEqualityModule::debugCheckTableau(){
     Assert(sum == shouldBe);
   }
 }
+bool LinearEqualityModule::debugEntireLinEqIsConsistent(const string& s){
+  bool result = true;
+  for(ArithVar var = 0, end = d_tableau.getNumColumns(); var != end; ++var){
+    //  for(VarIter i = d_variables.begin(), end = d_variables.end(); i != end; ++i){
+    //ArithVar var = d_arithvarNodeMap.asArithVar(*i);
+    if(!d_partialModel.assignmentIsConsistent(var)){
+      d_partialModel.printModel(var);
+      Warning() << s << ":" << "Assignment is not consistent for " << var ;
+      if(d_tableau.isBasic(var)){
+        Warning() << " (basic)";
+      }
+      Warning() << endl;
+      result = false;
+    }
+  }
+  return result;
+}
 
 DeltaRational LinearEqualityModule::computeBound(ArithVar basic, bool upperBound){
   DeltaRational sum(0,0);
index f337ef0dbcced5db3d6d649b751c1ab5b6b00409..7df5ee9c3184c796c33595b9eaacc1709ab9bd9a 100644 (file)
@@ -79,7 +79,7 @@ public:
    * and then pivots x_i with the nonbasic variable in its row x_j.
    * Updates the assignment of the other basic variables accordingly.
    */
-  void pivotAndUpdate(ArithVar x_i, ArithVar x_j, DeltaRational& v);
+  void pivotAndUpdate(ArithVar x_i, ArithVar x_j, const DeltaRational& v);
 
 
   ArithPartialModel& getPartialModel() const{ return d_partialModel; }
@@ -141,6 +141,11 @@ public:
   /** Debugging information for a pivot. */
   void debugPivot(ArithVar x_i, ArithVar x_j);
 
+  /**
+   * 
+   */
+  bool debugEntireLinEqIsConsistent(const std::string& s);
+
 
 private:
   /** These fields are designed to be accessible to TheoryArith methods. */
index 8e7fe7894e8bb5255edd38c6887b50e0ec993314..cd7a8a9aababbc45ae1cc7baa12c55f73c82761c 100644 (file)
@@ -247,7 +247,7 @@ void Tableau::rowPivot(ArithVar basicOld, ArithVar basicNew){
 
   d_basic2RowIndex.remove(basicOld);
   d_basic2RowIndex.set(basicNew, rid);
-  d_rowIndex2basic[rid] = basicNew;
+  d_rowIndex2basic.set(rid, basicNew);
 }
 
 // void Tableau::addEntry(ArithVar row, ArithVar col, const Rational& coeff){
@@ -397,10 +397,11 @@ void Tableau::addRow(ArithVar basic,
   RowIndex newRow = Matrix<Rational>::addRow(coefficients, variables);
   addEntry(newRow, basic, Rational(-1));
 
-  Assert(d_rowIndex2basic.size() == newRow);
+  Assert(!d_basic2RowIndex.isKey(basic));
+  Assert(!d_rowIndex2basic.isKey(newRow));
 
   d_basic2RowIndex.set(basic, newRow);
-  d_rowIndex2basic.push_back(basic);
+  d_rowIndex2basic.set(newRow, basic);
 
 
   if(Debug.isOn("matrix")){ printMatrix(); }
@@ -558,6 +559,15 @@ void ReducedRowVector::enqueueNonBasicVariablesAndCoefficients(std::vector< Arit
 //   return newId;
 // }
 
+void Tableau::removeBasicRow(ArithVar basic){
+  RowIndex rid = basicToRowIndex(basic);
+
+  removeRow(rid);
+  d_basic2RowIndex.remove(basic);
+  d_rowIndex2basic.remove(rid);
+  
+}
+
 
 }/* CVC4::theory::arith namespace */
 }/* CVC4::theory namespace */
index ea6c389b954f87c81b5d31cbd657e95dfa490b0a..027397b6a474a08cfab2ff71454bf5c4ef0106c2 100644 (file)
@@ -25,6 +25,7 @@
 #include "util/dense_map.h"
 
 #include "theory/arith/arithvar.h"
+#include "theory/arith/arithvar_node_map.h"
 #include "theory/arith/normal_form.h"
 
 #include <queue>
@@ -377,6 +378,8 @@ protected:
   uint32_t d_entriesInUse;
   MatrixEntryVector<T> d_entries;
 
+  std::vector<RowIndex> d_pool;
+
   T d_zero;
 
 public:
@@ -446,6 +449,23 @@ protected:
     d_entries.freeEntry(id);
   }
 
+ private:
+  RowIndex requestRowIndex(){
+    if(d_pool.empty()){
+      RowIndex ridx = d_rows.size();
+      d_rows.push_back(RowVectorT(&d_entries));
+      return ridx;
+    }else{
+      RowIndex rid = d_pool.back();
+      d_pool.pop_back();
+      return rid;
+    }
+  }
+
+  void releaseRowIndex(RowIndex rid){
+    d_pool.push_back(rid);
+  }
+
 public:
 
   size_t getNumRows() const {
@@ -485,8 +505,11 @@ public:
    */
   RowIndex addRow(const std::vector<T>& coeffs,
                   const std::vector<ArithVar>& variables){
-    RowIndex ridx = d_rows.size();
-    d_rows.push_back(RowVectorT(&d_entries));
+
+    RowIndex ridx = requestRowIndex();
+
+    //RowIndex ridx = d_rows.size();
+    //d_rows.push_back(RowVectorT(&d_entries));
 
     std::vector<Rational>::const_iterator coeffIter = coeffs.begin();
     std::vector<ArithVar>::const_iterator varsIter = variables.begin();
@@ -701,36 +724,7 @@ public:
       EntryID id = i.getID();
       removeEntry(id);
     }
-  }
-
-
-  Node rowAsEquality(RowIndex rid, const ArithVarToNodeMap& map){
-    using namespace CVC4::kind;
-
-    Assert(getRowLength(rid) >= 2);
-
-    std::vector<Node> pairs;
-    for(RowIterator i = getRow(rid); !i.atEnd(); ++i){
-      const Entry& entry = *i;
-      ArithVar colVar = entry.getColVar();
-
-      Node var = (map.find(colVar))->second;
-      Node coeff = mkRationalNode(entry.getCoefficient());
-
-      Node mult = NodeBuilder<2>(MULT) << coeff << var;
-      pairs.push_back(mult);
-    }
-
-    Node sum = Node::null();
-    if(pairs.size() == 1 ){
-      sum = pairs.front();
-    }else{
-      Assert(pairs.size() >= 2);
-      NodeBuilder<> sumBuilder(PLUS);
-      sumBuilder.append(pairs);
-      sum = sumBuilder;
-    }
-    return NodeBuilder<2>(EQUAL) << sum << mkRationalNode(d_zero);
+    releaseRowIndex(rid);
   }
 
   double densityMeasure() const{
@@ -754,6 +748,15 @@ public:
     }
   }
 
+  void loadSignQueries(RowIndex rid, DenseMap<int>& target) const{
+
+    RowIterator i = getRow(rid).begin(), i_end = getRow(rid).end();
+    for(; i != i_end; ++i){
+      const MatrixEntry<T>& entry = *i;
+      target.set(entry.getColVar(), entry.getCoefficient().sgn());
+    }
+  }
+
 protected:
   uint32_t numNonZeroEntries() const { return size(); }
 
@@ -833,8 +836,10 @@ private:
   // Set of all of the basic variables in the tableau.
   // ArithVarMap<RowIndex> : ArithVar |-> RowIndex
   BasicToRowMap d_basic2RowIndex;
+
   // RowIndex |-> Basic Variable
-  std::vector<ArithVar> d_rowIndex2basic;
+  typedef DenseMap<ArithVar> RowIndexToBasicMap;
+  RowIndexToBasicMap d_rowIndex2basic;
 
 public:
 
@@ -882,10 +887,6 @@ public:
     return getRow(basicToRowIndex(basic)).begin();
   }
 
-  // RowIterator rowIterator(RowIndex r) const {
-  //   return getRow(r).begin();
-  // }
-
   /**
    * Adds a row to the tableau.
    * The new row is equivalent to:
@@ -911,7 +912,6 @@ public:
 
   void removeBasicRow(ArithVar basic);
 
-
 private:
   /* Changes the basic variable on the row for basicOld to basicNew. */
   void rowPivot(ArithVar basicOld, ArithVar basicNew);
index d2814348ae653138eb73704fed0cd917099160d6..f036e20fd34b864d898d5b4598b1b7272edba321 100644 (file)
@@ -62,6 +62,8 @@ TheoryArith::TheoryArith(context::Context* c, context::UserContext* u, OutputCha
   d_unknownsInARow(0),
   d_hasDoneWorkSinceCut(false),
   d_learner(u),
+  d_numberOfVariables(0),
+  d_pool(),
   d_setupLiteralCallback(this),
   d_assertionsThatDoNotMatchTheirLiterals(c),
   d_nextIntegerCheckVar(0),
@@ -79,6 +81,7 @@ TheoryArith::TheoryArith(context::Context* c, context::UserContext* u, OutputCha
   d_tableauResetPeriod(10),
   d_conflicts(c),
   d_raiseConflict(d_conflicts),
+  d_tempVarMalloc(*this),
   d_congruenceManager(c, d_constraintDatabase, d_setupLiteralCallback, d_arithvarNodeMap, d_raiseConflict),
   d_simplex(d_linEq, d_raiseConflict),
   d_constraintDatabase(c, u, d_arithvarNodeMap, d_congruenceManager, d_raiseConflict),
@@ -822,8 +825,9 @@ void TheoryArith::setupVariable(const Variable& x){
   Assert(!isSetup(n));
 
   ++(d_statistics.d_statUserVariables);
-  ArithVar varN = requestArithVar(n,false);
-  setupInitialValue(varN);
+  requestArithVar(n,false);
+  //ArithVar varN = requestArithVar(n,false);
+  //setupInitialValue(varN);
 
   markSetup(n);
 
@@ -860,8 +864,9 @@ void TheoryArith::setupVariableList(const VarList& vl){
     d_nlIncomplete = true;
 
     ++(d_statistics.d_statUserVariables);
-    ArithVar av = requestArithVar(vlNode, false);
-    setupInitialValue(av);
+    requestArithVar(vlNode, false);
+    //ArithVar av = requestArithVar(vlNode, false);
+    //setupInitialValue(av);
 
     markSetup(vlNode);
   }
@@ -1054,7 +1059,7 @@ void TheoryArith::setupPolynomial(const Polynomial& poly) {
 
     ArithVar varSlack = requestArithVar(polyNode, true);
     d_tableau.addRow(varSlack, coefficients, variables);
-    setupInitialValue(varSlack);
+    setupBasicValue(varSlack);
 
     //Add differences to the difference manager
     Polynomial::iterator i = poly.begin(), end = poly.end();
@@ -1125,6 +1130,14 @@ void TheoryArith::preRegisterTerm(TNode n) {
   Debug("arith::preregister") << "end arith::preRegisterTerm("<< n <<")" << endl;
 }
 
+void TheoryArith::releaseArithVar(ArithVar v){
+  Assert(d_arithvarNodeMap.hasNode(v));
+  
+  d_constraintDatabase.removeVariable(v);
+  d_arithvarNodeMap.remove(v);
+
+  d_pool.push_back(v);
+}
 
 ArithVar TheoryArith::requestArithVar(TNode x, bool slack){
   //TODO : The VarList trick is good enough?
@@ -1135,32 +1148,73 @@ ArithVar TheoryArith::requestArithVar(TNode x, bool slack){
   Assert(!d_arithvarNodeMap.hasArithVar(x));
   Assert(x.getType().isReal());// real or integer
 
-  ArithVar varX = d_variables.size();
-  d_variables.push_back(Node(x));
-  Debug("integers") << "isInteger[[" << x << "]]: " << x.getType().isInteger() << endl;
+  // ArithVar varX = d_variables.size();
+  // d_variables.push_back(Node(x));
+
+  bool reclaim = !d_pool.empty();
+  ArithVar varX;
+
+  if(reclaim){
+    varX = d_pool.back();
+    d_pool.pop_back();
+
+    d_partialModel.setAssignment(varX, d_DELTA_ZERO, d_DELTA_ZERO);
+  }else{
+    varX = d_numberOfVariables;
+    ++d_numberOfVariables;
+
+    d_slackVars.push_back(true);
+    d_variableTypes.push_back(ATReal);
 
+    d_simplex.increaseMax();
+
+    d_tableau.increaseSize();
+    d_tableauSizeHasBeenModified = true;
+
+    d_partialModel.initialize(varX, d_DELTA_ZERO);
+  }
+
+  ArithType type;
   if(slack){
     //The type computation is not quite accurate for Rationals that are integral.
     //We'll use the isIntegral check from the polynomial package instead.
     Polynomial p = Polynomial::parsePolynomial(x);
-    d_variableTypes.push_back(p.isIntegral() ? ATInteger : ATReal);
+    type = p.isIntegral() ? ATInteger : ATReal;
   }else{
-    d_variableTypes.push_back(nodeToArithType(x));
+    type = nodeToArithType(x);
   }
+  d_variableTypes[varX] = type;
+  d_slackVars[varX] = slack;
 
-  d_slackVars.push_back(slack);
-
-  d_simplex.increaseMax();
+  d_constraintDatabase.addVariable(varX);
 
   d_arithvarNodeMap.setArithVar(x,varX);
 
-  d_tableau.increaseSize();
-  d_tableauSizeHasBeenModified = true;
+  // Debug("integers") << "isInteger[[" << x << "]]: " << x.getType().isInteger() << endl;
 
-  d_constraintDatabase.addVariable(varX);
+  // if(slack){
+  //   //The type computation is not quite accurate for Rationals that are integral.
+  //   //We'll use the isIntegral check from the polynomial package instead.
+  //   Polynomial p = Polynomial::parsePolynomial(x);
+  //   d_variableTypes.push_back(p.isIntegral() ? ATInteger : ATReal);
+  // }else{
+  //   d_variableTypes.push_back(nodeToArithType(x));
+  // }
+
+  // d_slackVars.push_back(slack);
+
+  // d_simplex.increaseMax();
+
+  // d_tableau.increaseSize();
+  // d_tableauSizeHasBeenModified = true;
+
+  // d_constraintDatabase.addVariable(varX);
 
   Debug("arith::arithvar") << x << " |-> " << varX << endl;
 
+  Assert(!d_partialModel.hasUpperBound(varX));
+  Assert(!d_partialModel.hasLowerBound(varX));
+
   return varX;
 }
 
@@ -1179,18 +1233,7 @@ void TheoryArith::asVectors(const Polynomial& p, std::vector<Rational>& coeffs,
     Assert(theoryOf(n) != THEORY_ARITH || d_arithvarNodeMap.hasArithVar(n));
 
     Assert(d_arithvarNodeMap.hasArithVar(n));
-    ArithVar av;
-    // The first if is likely dead is likely dead code:
-    // if (theoryOf(n) != THEORY_ARITH && !d_arithvarNodeMap.hasArithVar(n)) {
-    //   // The only way not to get it through pre-register is if it's a foreign term
-    //   ++(d_statistics.d_statUserVariables);
-    //   av = requestArithVar(n,false);
-    //   setupInitialValue(av);
-    // } else {
-    //   // Otherwise, we already have it's variable
-    //   av = d_arithvarNodeMap.asArithVar(n);
-    // }
-    av = d_arithvarNodeMap.asArithVar(n);
+    ArithVar av = d_arithvarNodeMap.asArithVar(n);
 
     coeffs.push_back(constant.getValue());
     variables.push_back(av);
@@ -1200,11 +1243,12 @@ void TheoryArith::asVectors(const Polynomial& p, std::vector<Rational>& coeffs,
 /* Requirements:
  * For basic variables the row must have been added to the tableau.
  */
-void TheoryArith::setupInitialValue(ArithVar x){
+void TheoryArith::setupBasicValue(ArithVar x){
+  Assert(d_tableau.isBasic(x));
 
-  if(!d_tableau.isBasic(x)){
-    d_partialModel.initialize(x, d_DELTA_ZERO);
-  }else{
+  // if(!d_tableau.isBasic(x)){
+  //   d_partialModel.setAssignment(x, d_DELTA_ZERO, d_DELTA_ZERO);
+  // }else{
     //If the variable is basic, assertions may have already happened and updates
     //may have occured before setting this variable up.
 
@@ -1212,9 +1256,11 @@ void TheoryArith::setupInitialValue(ArithVar x){
     //time instead of register
     DeltaRational safeAssignment = d_linEq.computeRowValue(x, true);
     DeltaRational assignment = d_linEq.computeRowValue(x, false);
-    d_partialModel.initialize(x,safeAssignment);
-    d_partialModel.setAssignment(x,assignment);
-  }
+    //d_partialModel.initialize(x,safeAssignment);
+    //d_partialModel.setAssignment(x,assignment);
+    d_partialModel.setAssignment(x,safeAssignment,assignment);
+
+    //  }
   Debug("arith") << "setupVariable("<<x<<")"<<std::endl;
 }
 
@@ -1254,8 +1300,8 @@ Node TheoryArith::dioCutting(){
   context::Context::ScopedPush speculativePush(getSatContext());
   //DO NOT TOUCH THE OUTPUTSTREAM
 
-  //TODO: Improve this
-  for(ArithVar v = 0, end = d_variables.size(); v != end; ++v){
+  for(var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
+    ArithVar v = *vi;
     if(isInteger(v)){
       const DeltaRational& dr = d_partialModel.getAssignment(v);
       if(d_partialModel.equalsUpperBound(v, dr) || d_partialModel.equalsLowerBound(v, dr)){
@@ -1485,7 +1531,8 @@ bool TheoryArith::assertionCases(Constraint constraint){
  * If this returns true, all integer variables have an integer assignment.
  */
 bool TheoryArith::hasIntegerModel(){
-  if(d_variables.size() > 0){
+  //if(d_variables.size() > 0){
+  if(getNumberOfVariables()){
     const ArithVar rrEnd = d_nextIntegerCheckVar;
     do {
       //Do not include slack variables
@@ -1495,7 +1542,7 @@ bool TheoryArith::hasIntegerModel(){
           return false;
         }
       }
-    } while((d_nextIntegerCheckVar = (1 + d_nextIntegerCheckVar == d_variables.size() ? 0 : 1 + d_nextIntegerCheckVar)) != rrEnd);
+    } while((d_nextIntegerCheckVar = (1 + d_nextIntegerCheckVar == getNumberOfVariables() ? 0 : 1 + d_nextIntegerCheckVar)) != rrEnd);
   }
   return true;
 }
@@ -1576,6 +1623,7 @@ void TheoryArith::check(Effort effortLevel){
   Assert(d_conflicts.empty());
 
   d_qflraStatus = d_simplex.findModel(fullEffort(effortLevel));
+
   switch(d_qflraStatus){
   case Result::SAT:
     if(newFacts){
@@ -1822,7 +1870,8 @@ bool TheoryArith::splitDisequalities(){
  */
 void TheoryArith::debugPrintAssertions() {
   Debug("arith::print_assertions") << "Assertions:" << endl;
-  for (ArithVar i = 0; i < d_variables.size(); ++ i) {
+  for (var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
+    ArithVar i = *vi;
     if (d_partialModel.hasLowerBound(i)) {
       Constraint lConstr = d_partialModel.getLowerBoundConstraint(i);
       Debug("arith::print_assertions") << lConstr << endl;
@@ -1842,13 +1891,15 @@ void TheoryArith::debugPrintAssertions() {
 
 void TheoryArith::debugPrintModel(){
   Debug("arith::print_model") << "Model:" << endl;
-
-  for (ArithVar i = 0; i < d_variables.size(); ++ i) {
-    Debug("arith::print_model") << d_variables[i] << " : " <<
-      d_partialModel.getAssignment(i);
-    if(d_tableau.isBasic(i))
-      Debug("arith::print_model") << " (basic)";
-    Debug("arith::print_model") << endl;
+  for (var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
+    ArithVar i = *vi;
+    if(d_arithvarNodeMap.hasNode(i)){
+      Debug("arith::print_model") << d_arithvarNodeMap.asNode(i) << " : " <<
+        d_partialModel.getAssignment(i);
+      if(d_tableau.isBasic(i))
+        Debug("arith::print_model") << " (basic)";
+      Debug("arith::print_model") << endl;
+    }
   }
 }
 
@@ -2057,7 +2108,8 @@ Rational TheoryArith::deltaValueForTotalOrder() const{
     relevantDeltaValues.insert(val);
   }
 
-  for(ArithVar v = 0; v < d_variables.size(); ++v){
+  for(var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
+    ArithVar v = *vi;
     const DeltaRational& value = d_partialModel.getAssignment(v);
     relevantDeltaValues.insert(value);
     if( d_partialModel.hasLowerBound(v)){
@@ -2108,7 +2160,8 @@ void TheoryArith::collectModelInfo( TheoryModel* m, bool fullModel ){
   // TODO:
   // This is not very good for user push/pop....
   // Revisit when implementing push/pop
-  for(ArithVar v = 0; v < d_variables.size(); ++v){
+  for(var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
+    ArithVar v = *vi;
     if(!isSlackVariable(v)){
       Node term = d_arithvarNodeMap.asNode(v);
 
@@ -2187,13 +2240,13 @@ void TheoryArith::notifyRestart(){
 }
 
 bool TheoryArith::entireStateIsConsistent(const string& s){
-  typedef std::vector<Node>::const_iterator VarIter;
   bool result = true;
-  for(VarIter i = d_variables.begin(), end = d_variables.end(); i != end; ++i){
-    ArithVar var = d_arithvarNodeMap.asArithVar(*i);
+  for(var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
+    ArithVar var = *vi;
+    //ArithVar var = d_arithvarNodeMap.asArithVar(*i);
     if(!d_partialModel.assignmentIsConsistent(var)){
       d_partialModel.printModel(var);
-      Warning() << s << ":" << "Assignment is not consistent for " << var << *i;
+      Warning() << s << ":" << "Assignment is not consistent for " << var << d_arithvarNodeMap.asNode(var);
       if(d_tableau.isBasic(var)){
         Warning() << " (basic)";
       }
@@ -2205,15 +2258,14 @@ bool TheoryArith::entireStateIsConsistent(const string& s){
 }
 
 bool TheoryArith::unenqueuedVariablesAreConsistent(){
-  typedef std::vector<Node>::const_iterator VarIter;
   bool result = true;
-  for(VarIter i = d_variables.begin(), end = d_variables.end(); i != end; ++i){
-    ArithVar var = d_arithvarNodeMap.asArithVar(*i);
+  for(var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
+    ArithVar var = *vi;
     if(!d_partialModel.assignmentIsConsistent(var)){
       if(!d_simplex.debugIsInCollectionQueue(var)){
 
         d_partialModel.printModel(var);
-        Warning() << "Unenqueued var is not consistent for " << var << *i;
+        Warning() << "Unenqueued var is not consistent for " << var <<  d_arithvarNodeMap.asNode(var);
         if(d_tableau.isBasic(var)){
           Warning() << " (basic)";
         }
@@ -2221,7 +2273,7 @@ bool TheoryArith::unenqueuedVariablesAreConsistent(){
         result = false;
       } else if(Debug.isOn("arith::consistency::initial")){
         d_partialModel.printModel(var);
-        Warning() << "Initial var is not consistent for " << var << *i;
+        Warning() << "Initial var is not consistent for " << var <<  d_arithvarNodeMap.asNode(var);
         if(d_tableau.isBasic(var)){
           Warning() << " (basic)";
         }
index b791186cf10c698d586c3385821ad04d9cf6cdea..7d1150fb15f889044de0eda99d644240cfb0bd5a 100644 (file)
@@ -89,17 +89,20 @@ private:
   /** Static learner. */
   ArithStaticLearner d_learner;
 
-  /**
-   * List of the variables in the system.
-   * This is needed to keep a positive ref count on slack variables.
-   */
-  std::vector<Node> d_variables;
+
+  ArithVar d_numberOfVariables;
+  inline ArithVar getNumberOfVariables() const { return d_numberOfVariables; }
+  std::vector<ArithVar> d_pool;
+  void releaseArithVar(ArithVar v);
 
   /**
    * The map between arith variables to nodes.
    */
   ArithVarNodeMap d_arithvarNodeMap;
 
+  typedef ArithVarNodeMap::var_iterator var_iterator;
+  var_iterator var_begin() const { return d_arithvarNodeMap.var_begin(); }
+  var_iterator var_end() const { return d_arithvarNodeMap.var_end(); }
 
   NodeSet d_setupNodes;
   bool isSetup(Node n) const {
@@ -273,6 +276,18 @@ private:
   void outputConflicts();
 
 
+  class TempVarMalloc : public ArithVarMalloc {
+  private:
+    TheoryArith& d_ta;
+  public:
+    TempVarMalloc(TheoryArith& ta) : d_ta(ta) {}
+    ArithVar request(){
+      Node skolem = mkRealSkolem("tmpVar");
+      return d_ta.requestArithVar(skolem, false);
+    }
+    void release(ArithVar v){ d_ta.releaseArithVar(v); }
+  } d_tempVarMalloc;
+
   /**
    * A copy of the tableau.
    * This is equivalent  to the original tableau if d_tableauSizeHasBeenModified
@@ -433,7 +448,7 @@ private:
   ArithVar requestArithVar(TNode x, bool slack);
 
   /** Initial (not context dependent) sets up for a variable.*/
-  void setupInitialValue(ArithVar x);
+  void setupBasicValue(ArithVar x);
 
   /** Initial (not context dependent) sets up for a new slack variable.*/
   void setupSlack(TNode left);
index d79ddee3181c07684e98fc15bcb6a9b2fc7d065b..ddf763b73d0ab6aee5a9b7ecafa0e2d135f23508 100755 (executable)
@@ -46,11 +46,12 @@ void InstStrategySimplex::processResetInstantiationRound( Theory::Effort effort
   d_tableaux.clear();\r
   d_ceTableaux.clear();\r
   //search for instantiation rows in simplex tableaux\r
-  ArithVarToNodeMap avtnm = d_th->d_arithvarNodeMap.getArithVarToNodeMap();\r
-  for( ArithVarToNodeMap::iterator it = avtnm.begin(); it != avtnm.end(); ++it ){\r
-    ArithVar x = (*it).first;\r
+  ArithVarNodeMap& avnm = d_th->d_arithvarNodeMap;\r
+  ArithVarNodeMap::var_iterator vi, vend;\r
+  for(vi = avnm.var_begin(), vend = avnm.var_end(); vi != vend; ++vi ){\r
+    ArithVar x = *vi;\r
     if( d_th->d_partialModel.hasEitherBound( x ) ){\r
-      Node n = (*it).second;\r
+      Node n = avnm.asNode(x);\r
       Node f;\r
       NodeBuilder<> t(kind::PLUS);\r
       if( n.getKind()==PLUS ){\r
@@ -167,10 +168,11 @@ void InstStrategySimplex::addTermToRow( ArithVar x, Node n, Node& f, NodeBuilder
 }\r
 \r
 void InstStrategySimplex::debugPrint( const char* c ){\r
-  ArithVarToNodeMap avtnm = d_th->d_arithvarNodeMap.getArithVarToNodeMap();\r
-  for( ArithVarToNodeMap::iterator it = avtnm.begin(); it != avtnm.end(); ++it ){\r
-    ArithVar x = (*it).first;\r
-    Node n = (*it).second;\r
+  const ArithVarNodeMap& avnm = d_th->d_arithvarNodeMap;\r
+  ArithVarNodeMap::var_iterator vi, vend;\r
+  for(vi = avnm.var_begin(), vend = avnm.var_end(); vi != vend; ++vi ){\r
+    ArithVar x = *vi;\r
+    Node n = avnm.asNode(x);\r
     //if( ((TheoryArith*)getTheory())->d_partialModel.hasEitherBound( x ) ){\r
       Debug(c) << x << " : " << n << ", bounds = ";\r
       if( d_th->d_partialModel.hasLowerBound( x ) ){\r
index fa78e67877fa7498dced8a8597e41ee677a0c333..222a761c3ffa216412ba6e6646b404398425c223 100644 (file)
@@ -151,6 +151,7 @@ public:
     pop_back();
   }
 
+  /** Returns the key at the back of a non-empty list.*/
   Key back() const {
     return d_list.back();
   }
@@ -164,6 +165,27 @@ public:
     d_list.pop_back();
   }
 
+
+  /** Adds at least a constant fraction of the elements in the current map to another map. */
+  void splitInto(DenseMap<T>& target){
+    uint32_t targetSize = size()/2;
+    while(size() > targetSize){
+      Key key = back();
+      target.set(key, get(key));
+      pop_back();
+    }
+  }
+
+  /** Adds the current target map to the current map.*/
+  void addAll(const DenseMap<T>& target){
+    for(const_iterator i = target.begin(), e = target.end(); i != e; ++i){
+      Key k = *i;
+      set(k, target[k]);
+    }
+  }
+
+
+
  private:
 
   size_t allocated() const {