// For debugging: there are missing cases: user-defined types, symbols inside of quantifiers, etc.
void VCCmd::printSymbols(Expr e, ExprMap<bool>& cache)
{
  if (cache.find(e) != cache.end()) return;
  switch (e.getKind()) {
    case SKOLEM_VAR:
    case UCONST: {
      cout << e << " : ";
      ExprStream os(d_vc->getEM());
      os.dagFlag(false);
      os << e.getType().getExpr();
      cout << ";" << endl;
      break;
    }
    case APPLY: {
      Expr op = e.getOpExpr();
      if ((op.getKind() == UFUNC) && (cache.find(op) == cache.end())) {
        cout << op << " : ";
        ExprStream os(d_vc->getEM());
        os.dagFlag(false);
        os << op.getType().getExpr();
        cout << ";" << endl;
        cache[op] = true;
      }
      // fall through
    }
    default: {
      Expr::iterator i = e.begin(), iend = e.end();
      for (; i != iend; ++i) {
        printSymbols(*i, cache);
      }
      break;
    }
  }
  cache[e] = true;
}
Exemple #2
0
unsigned compute_degree(ExprManager& exprManager, const Expr& term) {
  unsigned n = term.getNumChildren();    
  unsigned degree = 0;

  // boolean stuff
  if (term.getType() == exprManager.booleanType()) {
    for (unsigned i = 0; i < n; ++ i) {
      degree = std::max(degree, compute_degree(exprManager, term[i]));
    }
    return degree;
  }

  // terms
  if (n == 0) {
    if (term.getKind() == kind::CONST_RATIONAL) {
      return 0;
    } else {
      return 1;
    }
  } else {
    unsigned degree = 0;  
    if (term.getKind() == kind::MULT) {
      for (unsigned i = 0; i < n; ++ i) {
        degree += std::max(degree, compute_degree(exprManager, term[i]));
      }
    } else {
      for (unsigned i = 0; i < n; ++ i) {
        degree = std::max(degree, compute_degree(exprManager, term[i]));
      }
    }    
    return degree;    
  }
}
//! find all bound variables in e and maps them to true in boundVars
void QuantTheoremProducer::recFindBoundVars(const Expr& e,
		           ExprMap<bool> & boundVars, ExprMap<bool> &visited)
{
  if(visited.count(e)>0)
    return;
  else
    visited[e] = true;
  if(e.getKind() == BOUND_VAR)
    boundVars[e] = true;
  if(e.getKind() == EXISTS || e.getKind() == FORALL)
    recFindBoundVars(e.getBody(), boundVars, visited);
  for(Expr::iterator it = e.begin(); it!=e.end(); ++it)
    recFindBoundVars(*it, boundVars, visited);

}
Exemple #4
0
void Tptp::checkLetBinding(const std::vector<Expr>& bvlist, Expr lhs, Expr rhs,
                           bool formula) {
  if (lhs.getKind() != CVC4::kind::APPLY_UF) {
    parseError("malformed let: LHS must be a flat function application");
  }
  const std::multiset<CVC4::Expr> vars{lhs.begin(), lhs.end()};
  if(formula && !lhs.getType().isBoolean()) {
    parseError("malformed let: LHS must be formula");
  }
  for (const CVC4::Expr& var : vars) {
    if (var.hasOperator()) {
      parseError("malformed let: LHS must be flat, illegal child: " +
                 var.toString());
    }
  }

  // ensure all let-bound variables appear on the LHS, and appear only once
  for (const Expr& bound_var : bvlist) {
    const size_t count = vars.count(bound_var);
    if (count == 0) {
      parseError(
          "malformed let: LHS must make use of all quantified variables, "
          "missing `" +
          bound_var.toString() + "'");
    } else if (count >= 2) {
      parseError("malformed let: LHS cannot use same bound variable twice: " +
                 bound_var.toString());
    }
  }
}
bool TheoryArith::isSyntacticRational(const Expr& e, Rational& r)
{
  if (e.getKind() == REAL_CONST) {
    r = e[0].getRational();
    return true;
  }
  else if (e.isRational()) {
    r = e.getRational();
    return true;
  }
  else if (isUMinus(e)) {
    if (isSyntacticRational(e[0], r)) {
      r = -r;
      return true;
    }
  }
  else if (isDivide(e)) {
    Rational num;
    if (isSyntacticRational(e[0], num)) {
      Rational den;
      if (isSyntacticRational(e[1], den)) {
        if (den != 0) {
          r = num / den;
          return true;
        }
      }
    }
  }
  return false;
}
Exemple #6
0
// returns 0 if b is structurally equal to *this
int Expr::compare(const Expr &b, ExprEquivSet &equivs) const {
  if (this == &b) return 0;

  const Expr *ap, *bp;
  if (this < &b) {
    ap = this; bp = &b;
  } else {
    ap = &b; bp = this;
  }

  if (equivs.count(std::make_pair(ap, bp)))
    return 0;

  Kind ak = getKind(), bk = b.getKind();
  if (ak!=bk)
    return (ak < bk) ? -1 : 1;

  if (hashValue != b.hashValue) 
    return (hashValue < b.hashValue) ? -1 : 1;

  if (int res = compareContents(b)) 
    return res;

  unsigned aN = getNumKids();
  for (unsigned i=0; i<aN; i++)
    if (int res = getKid(i)->compare(*b.getKid(i), equivs))
      return res;

  equivs.insert(std::make_pair(ap, bp));
  return 0;
}
bool TheoryArith::isAtomicArithTerm(const Expr& e)
{
  switch (e.getKind()) {
    case RATIONAL_EXPR:
      return true;
    case ITE:
      return false;
    case UMINUS:
    case PLUS:
    case MINUS:
    case MULT:
    case DIVIDE:
    case POW:
    case INTDIV:
    case MOD: {
      int i=0, iend=e.arity();
      for(; i!=iend; ++i) {
        if (!isAtomicArithTerm(e[i])) return false;
      }
      break;
    }
    default:
      break;
  }
  return true;
}
Expr ExprManager::mkExpr(Expr opExpr, const std::vector<Expr>& children) {
  const unsigned n = children.size();
  Kind kind = NodeManager::operatorToKind(opExpr.getNode());
  CheckArgument(opExpr.getKind() == kind::BUILTIN || kind::metaKindOf(kind) == kind::metakind::PARAMETERIZED, opExpr,
                "This Expr constructor is for parameterized kinds only");
  CheckArgument(n >= minArity(kind) && n <= maxArity(kind), kind,
                "Exprs with kind %s must have at least %u children and "
                "at most %u children (the one under construction has %u)",
                kind::kindToString(kind).c_str(),
                minArity(kind), maxArity(kind), n);

  NodeManagerScope nms(d_nodeManager);

  vector<Node> nodes;
  vector<Expr>::const_iterator it = children.begin();
  vector<Expr>::const_iterator it_end = children.end();
  while(it != it_end) {
    nodes.push_back(it->getNode());
    ++it;
  }
  try {
    INC_STAT(kind);
    return Expr(this,d_nodeManager->mkNodePtr(opExpr.getNode(), nodes));
  } catch (const TypeCheckingExceptionPrivate& e) {
    throw TypeCheckingException(this, &e);
  }
}
Exemple #9
0
ExprVisitor::Action ExprEvaluator::visitExprPost(const Expr& e) {
  // When evaluating an assignment we should fold NotOptimizedExpr
  // nodes so we can fully evaluate.
  if (e.getKind() == Expr::NotOptimized) {
    return Action::changeTo(static_cast<const NotOptimizedExpr&>(e).src);
  }
  return Action::skipChildren();
}
Exemple #10
0
Theorem CNF_Manager::replaceITErec(const Expr& e, Var v, bool translateOnly)
{
  // Quick exit for atomic expressions
  if (e.isAtomic()) return d_commonRules->reflexivityRule(e);

  // Check cache
  Theorem thm;
  bool foundInCache = false;
  ExprHashMap<Theorem>::iterator iMap = d_iteMap.find(e);
  if (iMap != d_iteMap.end()) {
    thm = (*iMap).second;
    foundInCache = true;
  }

  if (e.getKind() == ITE) {
    // Replace non-Bool ITE expressions
    DebugAssert(!e.getType().isBool(), "Expected non-Bool ITE");
    // generate e = x for new x
    if (!foundInCache) thm = d_commonRules->varIntroSkolem(e);
    Theorem thm2 = d_commonRules->symmetryRule(thm);
    thm2 = d_commonRules->iffMP(thm2, d_rules->ifLiftRule(thm2.getExpr(), 1));
    d_translateQueueVars.push_back(v);
    d_translateQueueThms.push_back(thm2);
    d_translateQueueFlags.push_back(translateOnly);
  }
  else {
    // Recursively traverse, replacing ITE's
    vector<Theorem> thms;
    vector<unsigned> changed;
    unsigned index = 0;
    Expr::iterator i, iend;
    if (foundInCache) {
      for(i = e.begin(), iend = e.end(); i!=iend; ++i, ++index) {
        replaceITErec(*i, v, translateOnly);
      }
    }
    else {
      for(i = e.begin(), iend = e.end(); i!=iend; ++i, ++index) {
        thm = replaceITErec(*i, v, translateOnly);
        if (!thm.isRefl()) {
          thms.push_back(thm);
          changed.push_back(index);
        }
      }
      if(changed.size() > 0) {
        thm = d_commonRules->substitutivityRule(e, changed, thms);
      }
      else thm = d_commonRules->reflexivityRule(e);
    }
  }

  // Update cache and return
  if (!foundInCache) d_iteMap[e] = thm;
  return thm;
}
Exemple #11
0
bool TheoryArith::isAtomicArithFormula(const Expr& e)
{
  switch (e.getKind()) {
    case LT:
    case GT:
    case LE:
    case GE:
    case EQ:
      return isAtomicArithTerm(e[0]) && isAtomicArithTerm(e[1]);
  }
  return false;
}
Expr ExprManager::mkExpr(Expr opExpr, Expr child1) {
  const unsigned n = 1;
  Kind kind = NodeManager::operatorToKind(opExpr.getNode());
  CheckArgument(opExpr.getKind() == kind::BUILTIN || kind::metaKindOf(kind) == kind::metakind::PARAMETERIZED, opExpr,
                "This Expr constructor is for parameterized kinds only");
  CheckArgument(n >= minArity(kind) && n <= maxArity(kind), kind,
                "Exprs with kind %s must have at least %u children and "
                "at most %u children (the one under construction has %u)",
                kind::kindToString(kind).c_str(),
                minArity(kind), maxArity(kind), n);
  NodeManagerScope nms(d_nodeManager);
  try {
    INC_STAT(kind);
    return Expr(this, d_nodeManager->mkNodePtr(opExpr.getNode(), child1.getNode()));
  } catch (const TypeCheckingExceptionPrivate& e) {
    throw TypeCheckingException(this, &e);
  }
}
Exemple #13
0
// returns 0 if b is structurally equal to *this
int Expr::compare(const Expr &b) const {
    if (this == &b) return 0;

    Kind ak = getKind(), bk = b.getKind();
    if (ak!=bk)
        return (ak < bk) ? -1 : 1;

    if (hashValue != b.hashValue)
        return (hashValue < b.hashValue) ? -1 : 1;

    if (int res = compareContents(b))
        return res;

    unsigned aN = getNumKids();
    for (unsigned i=0; i<aN; i++)
        if (int res = getKid(i).compare(b.getKid(i)))
            return res;

    return 0;
}
Exemple #14
0
 Expr collectSortsExpr(Expr e)
 {
   if(substitutions.find(e) != substitutions.end()) {
     return substitutions[e];
   }
   ++depth;
   Expr old_e = e;
   for(unsigned i = 0; i < e.getNumChildren(); ++i) {
     collectSortsExpr(e[i]);
   }
   e = e.substitute(substitutions);
   // cout << "[debug] " << e << " " << e.getKind() << " " << theory::kindToTheoryId(e.getKind()) << endl;
   if(theory::kindToTheoryId(e.getKind()) == theory::THEORY_SETS) {
     SetType t = SetType(e.getType().isBoolean() ? e[1].getType() : e.getType());
     substitutions[e] = add(t, e);
     e = e.substitute(substitutions);
   }
   substitutions[old_e] = e;
   // cout << ";"; for(int i = 0; i < depth; ++i) cout << " "; cout << old_e << " => " << e << endl;
   --depth;
   return e;
 }
Exemple #15
0
void translate_to_redlog(const map<Expr, unsigned>& variables, const Expr& assertion) {
  bool first;
  
  unsigned n = assertion.getNumChildren();
  
  if (n == 0) {
    if (assertion.isConst()) {
      if (assertion.getConst<bool>()) {
        cout << "(1 > 0)";
      } else {
        cout << "(1 < 0)";
      }
    } else {
      assert(false);
    }
  } else {
    
    std::string op;
    bool binary = false;
    bool theory = false;
    
    switch (assertion.getKind()) {
      case kind::NOT: 
        cout << "(not ";
        translate_to_redlog(variables, assertion[0]);
        cout << ")";
        break;
      case kind::OR:
        first = true;
        cout << "(";
        for (unsigned i = 0; i < n; ++ i) {
          if (!first) {
            cout << " or ";
          }
          first = false;
          translate_to_redlog(variables, assertion[i]);
        }
        cout << ")";
        break;
      case kind::AND:
        first = true;
        cout << "(";
        for (unsigned i = 0; i < n; ++ i) {
          if (!first) {
            cout << " and ";
          }
          first = false;
          translate_to_redlog(variables, assertion[i]);
        }
        cout << ")";
        break;      
      case kind::IMPLIES:
        cout << "(";
        translate_to_redlog(variables, assertion[0]);
        cout << " impl ";
        translate_to_redlog(variables, assertion[1]);
        cout << ")";
        break;
      case kind::IFF:
        cout << "(";
        translate_to_redlog(variables, assertion[0]);
        cout << " equiv ";
        translate_to_redlog(variables, assertion[1]);
        cout << ")";
        break;            
      case kind::EQUAL:
        op = "=";
        theory = true;
	break;
      case kind::LT:
        op = "<";
        theory = true;
        break;
      case kind::LEQ:
        op = "<=";
        theory = true;
        break;
      case kind::GT:
        op = ">";
        theory = true;
        break;
      case kind::GEQ:
        op = ">=";
        theory = true;
        break;
      default:
        assert(false);
        break;
    }

    if (binary) {
      cout << "(";
      translate_to_redlog(variables, assertion[0]);
      cout << " " << op << " ";
      translate_to_redlog(variables, assertion[1]);
      cout << ")";
    }      

    if (theory) {
      cout << "(";
      translate_to_redlog_term(variables, assertion[0]);
      cout << " " << op << " ";
      translate_to_redlog_term(variables, assertion[1]);
      cout << ")";
    }      
  }  
}
Exemple #16
0
void translate_to_redlog_term(const map<Expr, unsigned>& variables, const Expr& term) {
  bool first;

  unsigned n = term.getNumChildren();
  
  if (n == 0) {
    if (term.getKind() == kind::CONST_RATIONAL) {
      cout << term.getConst<Rational>();
    } else {
      assert(variables.find(term) != variables.end());
      cout << "x" << variables.find(term)->second;
    }
  } else {
        
    switch (term.getKind()) {
      case kind::PLUS:
        cout << "(";
        first = true;
        for (unsigned i = 0; i < n; ++ i) {
          if (!first) {
            cout << " + ";
          }
          first = false;
          translate_to_redlog_term(variables, term[i]);
        }
        cout << ")";
        break;
      case kind::MULT:
        cout << "(";
        first = true;
        for (unsigned i = 0; i < n; ++ i) {
          if (!first) {
            cout << " * ";
          }
          first = false;
          translate_to_redlog_term(variables, term[i]);
        }
        cout << ")";
        break;      
      case kind::MINUS:
        cout << "(";
        translate_to_redlog_term(variables, term[0]);
        cout << " - ";
        translate_to_redlog_term(variables, term[1]);
        cout << ")";
        break;
      case kind::DIVISION:
        cout << "(";
        translate_to_redlog_term(variables, term[0]);
        cout << " / ";
        translate_to_redlog_term(variables, term[1]);
        cout << ")";
        break;
      case kind::UMINUS:
        cout << "(-(";
        translate_to_redlog_term(variables, term[0]);
        cout << "))";
        break;
      default:
        assert(false);
        break;
    }
  }  
}
Exemple #17
0
LFSCProof* LFSCProof::Make_CNF( const Expr& form, const Expr& reason, int pos )
{
  Expr ec = cascade_expr( form );
#ifdef PRINT_MAJOR_METHODS
  cout << ";[M] CNF " << reason << " " << pos << std::endl;
#endif
  int m = queryM( ec );
  if( m>0 )
  {
    ostringstream os1;
    ostringstream os2;
    RefPtr< LFSCProof > p;
    if( reason==d_or_final_s )
    {
#if 0
      //this is the version that cascades
      //make the proof for the or
      p = LFSCPfVar::Make( "@v", abs(m) );
      //clausify the or statement
      p = LFSCClausify::Make( ec, p.get(), true );
      //return
      return LFSCAssume::Make( m, p.get(), true );
#else
      //this is the version that does not expand the last
      ostringstream oss1, oss2;
      p = LFSCPfVar::Make( "@v", abs(m) );
      for( int a=(form.arity()-2); a>=0; a-- ){
        int m1 = queryM( form[a] );
        oss1 << "(or_elim_1 _ _ ";
        oss1 << ( m1<0 ? "(not_not_intro _ " : "" );
        oss1 << "@v" << abs( m1 );
        oss1 << ( m1<0 ? ") " : " " );
        oss2 << ")";
      }
      p = LFSCProofGeneric::Make( oss1.str(), p.get(), oss2.str() );
      //p = LFSCClausify::Make( form[form.arity()-1], p.get() );
      p = LFSCClausify::Make( queryM( form[form.arity()-1] ), p.get() );
      for( int a=0; a<(form.arity()-1); a++ ){
        p = LFSCAssume::Make( queryM( form[a] ), p.get(), false );
      }
      return LFSCAssume::Make( m, p.get() );
#endif
    }
    else if( reason==d_and_final_s )
    {
#if 1
      //this is the version that does not expand the last
      p = LFSCPfVar::Make( "@v", abs(m) );
      os1 << "(contra _ ";
      for( int a=0; a<form.arity(); a++ ){
        if( a<(form.arity()-1))
          os1 << "(and_intro _ _ ";
        os1 << "@v" << abs( queryM( form[a] ) );
        if( a<(form.arity()-1)){
          os1 << " ";
          os2 << ")";
        }
      }
      os2 << " @v" << abs(m) << ")";
      os1 << os2.str();
      p = LFSCProofGeneric::MakeStr( os1.str().c_str() );
      for( int a=0; a<form.arity(); a++ ){
        p = LFSCAssume::Make( queryM( form[a] ), p.get() );
      }
      return LFSCAssume::Make( m, p.get(), false );
#else
      //this is the version that cascades
      std::vector< Expr > assumes;
      Expr ce = cascade_expr( form );
      Expr curr = ce;
      os1 << "(contra _ ";
      while( curr.getKind()==AND ){
        os1 << "(and_intro _ _ ";
        os1 << "@v" << abs( queryM( curr[0] ) ) << " ";
        os2 << ")";
        assumes.push_back( curr[0] );
        curr = curr[1];
      }
      os2 << " @v" << abs(m) << ")";
      p = LFSCProofGeneric::Make( os1.str(), p.get(), os2.str() );
      for( int a=0; a<(int)assumes.size(); a++ ){
        p = LFSCAssume::Make( queryM( assumes[a] ), p.get() );
      }
      return LFSCAssume::Make( m, p.get(), false );
#endif
    }
    else if( reason==d_imp_s )
    {
      int m1 = queryM( ec[0] );
      int m2 = queryM( ec[1] );
      switch( pos )
      {
      case 0:

        break;
      case 1:

        break;
      case 2:
      {
        //make a proof of the RHS
        ostringstream os;
        os << "(impl_elim _ _ @v" << abs( m1 ) << " @v" << abs( m ) << ")";
        p = LFSCProofGeneric::MakeStr( os.str().c_str() );
        //clausify the RHS
        p = LFSCClausify::Make( form[1], p.get() );     //cascadeOr?
        p = LFSCAssume::Make( queryM( ec[0] ), p.get() );
        return LFSCAssume::Make( queryM( ec ), p.get() );
      }
        break;
      }
    }
    else if( reason==d_ite_s )
    {
      int m1 = queryM( ec[0] );
      int m2 = queryM( ec[1] );
      switch( pos )
      {
      case 1:
      {
        ostringstream os;
        os << "(ite_elim_2" << (m1<0 ? "n" : "" );
        os << " _ _ _ @v" << abs( m1 ) << " @v" << abs( m ) << ")";
        p = LFSCProofGeneric::MakeStr( os.str().c_str() );
        p = LFSCClausify::Make( form[2], p.get() );
        p = LFSCAssume::Make( queryM( ec[0] ), p.get(), false );
        return LFSCAssume::Make( queryM( ec ), p.get() );
      }
        break;
      case 2:
      {
        ostringstream os;
        os << "(not_ite_elim_2 _ _ _ @v" << (m1<0 ? "n" : "" );
        os << abs( m1 ) << " @v" << abs( m ) << ")";
        p = LFSCProofGeneric::MakeStr( os.str().c_str() );
        Expr e = Expr( NOT, form[2] );
        p = LFSCClausify::Make( e, p.get() );
        p = LFSCAssume::Make( queryM( ec[0] ), p.get(), false );
        return LFSCAssume::Make( queryM( ec ), p.get(), false );
      }
        break;
      case 3:
      {
        ostringstream os;
        os << "(not_ite_elim_1 _ _ _ @v" << abs( m1 ) << " @v" << abs( m ) << ")";
        p = LFSCProofGeneric::MakeStr( os.str().c_str() );
        Expr e = Expr( NOT, form[1] );
        p = LFSCClausify::Make( e, p.get() );
        p = LFSCAssume::Make( queryM( ec[0] ), p.get() );
        return LFSCAssume::Make( queryM( ec ), p.get(), false );
      }
        break;
      case 4:
      {
        ostringstream os;
        os << "(ite_elim_1";// << (m1<0 ? "n" : "" );
        os << "  _ _ _ @v" << abs( m1 ) << " @v" << abs( m ) << ")";
        p = LFSCProofGeneric::MakeStr( os.str().c_str() );
        p = LFSCClausify::Make( form[1], p.get() );
        p = LFSCAssume::Make( queryM( ec[0] ), p.get() );
        return LFSCAssume::Make( queryM( ec ), p.get() );
      }
        break;
      case 5:
      {
        ostringstream os;
        os << "(not_ite_elim_3 _ _ _ @v" << abs( m2 ) << " @v" << abs( m ) << ")";
        p = LFSCProofGeneric::MakeStr( os.str().c_str() );
        Expr e = Expr( NOT, form[2] );
        p = LFSCClausify::Make( e, p.get() );
        p = LFSCAssume::Make( queryM( ec[1] ), p.get() );
        return LFSCAssume::Make( queryM( ec ), p.get(), false );
      }
        break;
      case 6:
      {
        ostringstream os;
        os << "(ite_elim_3";// << (m1<0 ? "n" : "" );
        os << "  _ _ _ @v" << abs( m2 ) << " @v" << abs( m ) << ")";
        p = LFSCProofGeneric::MakeStr( os.str().c_str() );
        p = LFSCClausify::Make( form[2], p.get() );
        p = LFSCAssume::Make( queryM( ec[1] ), p.get(), false );
        return LFSCAssume::Make( queryM( ec ), p.get() );
      }
        break;
      }
    }
    else if( reason==d_iff_s )
    {
      int m1 = queryM( ec[0] );
      int m2 = queryM( ec[1] );
      switch( pos )
      {
      case 0:
      {
        ostringstream os;
        os << "(not_iff_elim_1 _ _ @v" << abs( m1 ) << " @v" << abs( m ) << ")";
        p = LFSCProofGeneric::MakeStr( os.str().c_str() );
        p = LFSCClausify::Make( form[1], p.get() );
        p = LFSCAssume::Make( queryM( ec[0] ), p.get(), false );
        return LFSCAssume::Make( queryM( ec ), p.get(), false );
      }
        break;
      case 1:
      {
        ostringstream os;
        os << "(not_iff_elim_2 _ _ @v" << abs( m1 ) << " @v" << abs( m ) << ")";
        p = LFSCProofGeneric::MakeStr( os.str().c_str() );
        p = LFSCClausify::Make( Expr( NOT, form[1] ), p.get() );
        p = LFSCAssume::Make( queryM( ec[0] ), p.get() );
        return LFSCAssume::Make( queryM( ec ), p.get(), false );
      }
        break;
      case 2:
      {
        ostringstream os;
        os << "(impl_elim _ _ @v" << abs( m1 ) << "(iff_elim_1 _ _ @v" << abs( m ) << "))";
        p = LFSCProofGeneric::MakeStr( os.str().c_str() );
        //clausify the RHS
        p = LFSCClausify::Make( form[1], p.get() );     //cascadeOr?
        p = LFSCAssume::Make( queryM( ec[0] ), p.get() );
        return LFSCAssume::Make( queryM( ec ), p.get() );
      }
        break;
      case 3:
      {
        ostringstream os;
        os << "(impl_elim _ _ @v" << abs( m2 ) << "(iff_elim_2 _ _ @v" << abs( m ) << "))";
        p = LFSCProofGeneric::MakeStr( os.str().c_str() );
        //clausify the RHS
        p = LFSCClausify::Make( form[0], p.get() );     //cascadeOr?
        p = LFSCAssume::Make( queryM( ec[1] ), p.get() );
        return LFSCAssume::Make( m, p.get() );
      }
        break;
      }
    }
    else if( reason==d_or_mid_s )
    {
      ostringstream os1, os2;
      if( form[pos].isNot() )
        os1 << "(not_not_elim _ ";
      os1 << "(or_elim" << ( (pos==form.arity()) ? "_end" : "" );
      os1 << " _ _ " << pos << " ";
      os2 << ")";
      if( form[pos].isNot() )
        os2 << ")";
      p = LFSCPfVar::Make( "@v", abs( m ) );
      p = LFSCProofGeneric::Make( os1.str(), p.get(), os2.str() );
      Expr ea = Expr( NOT, form[pos] );
      p = LFSCClausify::Make( ea, p.get() );
      return LFSCAssume::Make( m, p.get(), false );
    }
    else if( reason==d_and_mid_s )
    {
      //make a proof of the pos-th statement
      p = LFSCPfVar::Make( "@v", abs( m ) );
      p = LFSCProof::Make_and_elim( form, p.get(), pos, form[pos] );
      p = LFSCClausify::Make( form[pos], p.get() );
      return LFSCAssume::Make( m, p.get() );
    }
  }
  ostringstream ose;
  ose << "CNF, " << reason << " unknown position = " << pos << std::endl;
  print_error( ose.str().c_str(), cout );
  return NULL;
}
Exemple #18
0
  Expr add(SetType t, Expr e) {

    if(setTypes.find(t) == setTypes.end() ) {
      // mark as processed
      setTypes.insert(t);

      Type elementType = t.getElementType();
      ostringstream oss_type;
      oss_type << language::SetLanguage(language::output::LANG_SMTLIB_V2)
               << elementType;
      string elementTypeAsString = oss_type.str();
      elementTypeAsString.erase(
        remove_if(elementTypeAsString.begin(), elementTypeAsString.end(), nonsense),
        elementTypeAsString.end());

      // define-sort
      ostringstream oss_name;
      oss_name << language::SetLanguage(language::output::LANG_SMTLIB_V2)
               << "(Set " << elementType << ")";
      string name = oss_name.str();
      Type newt = em->mkArrayType(t.getElementType(), em->booleanType());
      mapTypes[t] = newt;

      // diffent types
      vector<Type> t_t;
      t_t.push_back(t);
      t_t.push_back(t);
      vector<Type> elet_t;
      elet_t.push_back(elementType);
      elet_t.push_back(t);

      if(!enableAxioms)
        sout << "(define-fun emptyset" << elementTypeAsString << "    "
             << " ()"
             << " " << name
             << " ( (as const " << name << ") false ) )" << endl;
      setoperators[ make_pair(t, kind::EMPTYSET) ] =
        em->mkVar( std::string("emptyset") + elementTypeAsString,
                   t);

      if(!enableAxioms)
        sout << "(define-fun singleton" << elementTypeAsString << "     "
             << " ( (x " << elementType << ") )"
             << " " << name << ""
             << " (store emptyset" << elementTypeAsString << " x true) )" << endl;
      setoperators[ make_pair(t, kind::SINGLETON) ] =
        em->mkVar( std::string("singleton") + elementTypeAsString,
                   em->mkFunctionType( elementType, t ) );

      if(!enableAxioms)
        sout << "(define-fun union" << elementTypeAsString << "       "
             << " ( (s1 " << name << ") (s2 " << name << ") )"
             << " " << name << ""
             << " ((_ map or) s1 s2))" << endl;
      setoperators[ make_pair(t, kind::UNION) ] =
        em->mkVar( std::string("union") + elementTypeAsString,
                   em->mkFunctionType( t_t, t ) );

      if(!enableAxioms)
        sout << "(define-fun intersection" << elementTypeAsString << ""
             << " ( (s1 " << name << ") (s2 " << name << ") )"
             << " " << name << ""
             << " ((_ map and) s1 s2))" << endl;
      setoperators[ make_pair(t, kind::INTERSECTION) ] =
        em->mkVar( std::string("intersection") + elementTypeAsString,
                   em->mkFunctionType( t_t, t ) );

      if(!enableAxioms)
        sout << "(define-fun setminus" << elementTypeAsString << "    "
             << " ( (s1 " << name << ") (s2 " << name << ") )"
             << " " << name << ""
             << " (intersection" << elementTypeAsString << " s1 ((_ map not) s2)))" << endl;
      setoperators[ make_pair(t, kind::SETMINUS) ] =
        em->mkVar( std::string("setminus") + elementTypeAsString,
                   em->mkFunctionType( t_t, t ) );

      if(!enableAxioms)
        sout << "(define-fun member" << elementTypeAsString << "          "
             << " ( (x " << elementType << ")" << " (s " << name << "))"
             << " Bool"
             << " (select s x) )" << endl;
      setoperators[ make_pair(t, kind::MEMBER) ] =
        em->mkVar( std::string("member") + elementTypeAsString,
                   em->mkPredicateType( elet_t ) );

      if(!enableAxioms)
        sout << "(define-fun subset" << elementTypeAsString << "    "
             << " ( (s1 " << name << ") (s2 " << name << ") )"
             << " Bool"
             <<" (= emptyset" << elementTypeAsString << " (setminus" << elementTypeAsString << " s1 s2)) )" << endl;
      setoperators[ make_pair(t, kind::SUBSET) ] =
        em->mkVar( std::string("subset") + elementTypeAsString,
                   em->mkPredicateType( t_t ) );

      if(enableAxioms) {
        int N = sizeof(setaxioms) / sizeof(setaxioms[0]);
        for(int i = 0; i < N; ++i) {
          string s = setaxioms[i];
          ostringstream oss;
          oss << language::SetLanguage(language::output::LANG_SMTLIB_V2) << elementType;
          boost::replace_all(s, "HOLDA", elementTypeAsString);
          boost::replace_all(s, "HOLDB", oss.str());
          if( s == "" ) continue;
          sout << s << endl;
        }
      }

    }
    Expr ret;
    if(e.getKind() == kind::EMPTYSET) {
      ret = setoperators[ make_pair(t, e.getKind()) ];
    } else {
      vector<Expr> children = e.getChildren();
      children.insert(children.begin(), setoperators[ make_pair(t, e.getKind()) ]);
      ret = em->mkExpr(kind::APPLY, children);
    }
    // cout << "returning " << ret  << endl;
    return ret;
  }
Exemple #19
0
Lit CNF_Manager::translateExprRec(const Expr& e, CNF_Formula& cnf, const Theorem& thmIn)
{
  if (e.isFalse()) return Lit::getFalse();
  if (e.isTrue()) return Lit::getTrue();
  if (e.isNot()) return !translateExprRec(e[0], cnf, thmIn);

  ExprHashMap<Var>::iterator iMap = d_cnfVars.find(e);

  if (e.isTranslated()) {
    DebugAssert(iMap != d_cnfVars.end(), "Translated expr should be in map");
    return Lit((*iMap).second);
  }
  else e.setTranslated(d_bottomScope);

  Var v(int(d_varInfo.size()));
  bool translateOnly = false;

  if (iMap != d_cnfVars.end()) {
    v = (*iMap).second;
    translateOnly = true;
    d_varInfo[v].fanouts.clear();
  }
  else {
    d_varInfo.resize(v+1);
    d_varInfo.back().expr = e;
    d_cnfVars[e] = v;
  }

  Expr::iterator i, iend;
  bool isAnd = false;
  switch (e.getKind()) {
    case AND:
      isAnd = true;
    case OR: {
      vector<Lit> lits;
      unsigned idx;
      for (i = e.begin(), iend = e.end(); i != iend; ++i) {
        lits.push_back(translateExprRec(*i, cnf, thmIn));
      }

      //      DebugAssert(concreteExpr(e,Lit(v)) == e,"why here");

      for (idx = 0; idx < lits.size(); ++idx) {
        cnf.newClause();
        cnf.addLiteral(Lit(v),isAnd);
        cnf.addLiteral(lits[idx], !isAnd);
	
	//	DebugAssert(concreteExpr(e[idx],lits[idx]) == e[idx], "why here");

	std::string reasonStr = (isAnd ? "and_mid" : "or_mid");
	Expr after = e[idx] ;
	cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, after, reasonStr, idx)); // by yeting
      }

      cnf.newClause();
      cnf.addLiteral(Lit(v),!isAnd);
      for (idx = 0; idx < lits.size(); ++idx) {
        cnf.addLiteral(lits[idx], isAnd);
      }

      std::string reasonStr = (isAnd ? "and_final" : "or_final") ;   
      Expr after = e ;

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, after, reasonStr, 0)); // by yeting
      break;
    }
    case IMPLIES: {
      Lit arg0 = translateExprRec(e[0], cnf, thmIn);
      Lit arg1 = translateExprRec(e[1], cnf, thmIn);

      //      DebugAssert(concreteExpr(e, Lit(v)) == e, "why here");
      //      DebugAssert(concreteExpr(e[0], arg0) == e[0], "why here");
      //      DebugAssert(concreteExpr(e[1], arg1) == e[1], "why here");

      cnf.newClause();
      cnf.addLiteral(Lit(v));
      cnf.addLiteral(arg0);

      cnf.getCurrentClause().setClauseTheorem( d_rules->CNFtranslate(e, e, "imp", 0)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v));
      cnf.addLiteral(arg1,true);

      cnf.getCurrentClause().setClauseTheorem( d_rules->CNFtranslate(e, e, "imp", 1)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v),true);
      cnf.addLiteral(arg0,true);
      cnf.addLiteral(arg1);

      cnf.getCurrentClause().setClauseTheorem( d_rules->CNFtranslate(e, e, "imp", 2)); // by yeting

      break;
    }
    case IFF: {
      Lit arg0 = translateExprRec(e[0], cnf, thmIn);
      Lit arg1 = translateExprRec(e[1], cnf, thmIn);

      //      DebugAssert(concreteExpr(e, Lit(v)) == e, "why here");
      //      DebugAssert(concreteExpr(e[0], arg0) == e[0], "why here");
      //      DebugAssert(concreteExpr(e[1], arg1) == e[1], "why here");

      cnf.newClause();
      cnf.addLiteral(Lit(v));
      cnf.addLiteral(arg0);
      cnf.addLiteral(arg1);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "iff", 0)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v));
      cnf.addLiteral(arg0,true);
      cnf.addLiteral(arg1,true);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "iff", 1)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v),true);
      cnf.addLiteral(arg0,true);
      cnf.addLiteral(arg1);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "iff", 2)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v),true);
      cnf.addLiteral(arg0);
      cnf.addLiteral(arg1,true);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "iff", 3)); // by yeting
      break;
    }
    case XOR: {

      Lit arg0 = translateExprRec(e[0], cnf, thmIn);
      Lit arg1 = translateExprRec(e[1], cnf, thmIn);

      //      DebugAssert(concreteExpr(e, Lit(v)) == e, "why here");
      //      DebugAssert(concreteExpr(e[0], arg0) == e[0], "why here");
      //      DebugAssert(concreteExpr(e[1], arg1) == e[1], "why here");


      cnf.newClause();
      cnf.addLiteral(Lit(v),true);
      cnf.addLiteral(arg0);
      cnf.addLiteral(arg1);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "xor", 0)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v),true);
      cnf.addLiteral(arg0,true);
      cnf.addLiteral(arg1,true);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "xor", 1)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v));
      cnf.addLiteral(arg0,true);
      cnf.addLiteral(arg1);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "xor", 2)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v));
      cnf.addLiteral(arg0);
      cnf.addLiteral(arg1,true);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "xor", 3)); // by yeting
      break;
    }
    case ITE:
    {

      Lit arg0 = translateExprRec(e[0], cnf, thmIn);
      Lit arg1 = translateExprRec(e[1], cnf, thmIn);
      Lit arg2 = translateExprRec(e[2], cnf, thmIn);


      Expr aftere0 = concreteExpr(e[0], arg0);
      Expr aftere1 = concreteExpr(e[1], arg1);
      Expr aftere2 = concreteExpr(e[2], arg2);
      
      vector<Expr> after ;
      after.push_back(aftere0);
      after.push_back(aftere1);
      after.push_back(aftere2);
      
      Theorem e0thm;
      Theorem e1thm;
      Theorem e2thm;

      { e0thm = d_iteMap[e[0]];
	if (e0thm.isNull()) e0thm = d_commonRules->reflexivityRule(e[0]);
	e1thm = d_iteMap[e[1]];
	if (e1thm.isNull()) e1thm = d_commonRules->reflexivityRule(e[1]);
	e2thm = d_iteMap[e[2]];
	if (e2thm.isNull()) e2thm = d_commonRules->reflexivityRule(e[2]);
      }

      vector<Theorem> thms ;
      thms.push_back(e0thm);
      thms.push_back(e1thm);      
      thms.push_back(e2thm);

 

      cnf.newClause();
      cnf.addLiteral(Lit(v),true);
      cnf.addLiteral(arg0);
      cnf.addLiteral(arg2);
      
      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 1)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v));
      cnf.addLiteral(arg0);
      cnf.addLiteral(arg2,true);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 2)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v));
      cnf.addLiteral(arg0,true);
      cnf.addLiteral(arg1,true);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 3)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v),true);
      cnf.addLiteral(arg0,true);
      cnf.addLiteral(arg1);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 4)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v));
      cnf.addLiteral(arg1,true);
      cnf.addLiteral(arg2,true);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 5)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v),true);
      cnf.addLiteral(arg1);
      cnf.addLiteral(arg2);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 6)); // by yeting
      
      break;
    }
    default:
    {
      DebugAssert(!e.isAbsAtomicFormula() || d_varInfo[v].expr == e,
                  "Corrupted Varinfo");
      if (e.isAbsAtomicFormula()) {
        registerAtom(e, thmIn);
        return Lit(v);
      }

      Theorem thm = replaceITErec(e, v, translateOnly);
      const Expr& e2 = thm.getRHS();
      DebugAssert(e2.isAbsAtomicFormula(), "Expected AbsAtomicFormula");
      if (e2.isTranslated()) {
        // Ugly corner case: we happen to create an expression that has been
        // created before.  We remove the current variable and fix up the
        // translation stack.
        if (translateOnly) {
          DebugAssert(v == d_cnfVars[e2], "Expected literal match");
        }
        else {
          d_varInfo.resize(v);
          while (!d_translateQueueVars.empty() &&
                 d_translateQueueVars.back() == v) {
            d_translateQueueVars.pop_back();
          }
          DebugAssert(d_cnfVars.find(e2) != d_cnfVars.end(),
                      "Expected existing literal");
          v = d_cnfVars[e2];
          d_cnfVars[e] = v;
          while (d_translateQueueVars.size() < d_translateQueueThms.size()) {
            d_translateQueueVars.push_back(v);
          }
        }
      }
      else {
        e2.setTranslated(d_bottomScope);
        // Corner case: don't register reflexive equality
        if (!e2.isEq() || e2[0] != e2[1]) registerAtom(e2, thmIn);
        if (!translateOnly) {
          if (d_cnfVars.find(e2) == d_cnfVars.end()) {
            d_varInfo[v].expr = e2;
            d_cnfVars[e2] = v;
          }
          else {
            // Same corner case in an untranslated expr
            d_varInfo.resize(v);
            while (!d_translateQueueVars.empty() &&
                   d_translateQueueVars.back() == v) {
              d_translateQueueVars.pop_back();
            }
            v = d_cnfVars[e2];
            d_cnfVars[e] = v;
            while (d_translateQueueVars.size() < d_translateQueueThms.size()) {
              d_translateQueueVars.push_back(v);
            }
          }
        }
      }
      return Lit(v);
    }
  }

  // Record fanins / fanouts
  Lit l;
  for (i = e.begin(), iend = e.end(); i != iend; ++i) {
    l = getCNFLit(*i);
    DebugAssert(!l.isNull(), "Expected non-null literal");
    if (!translateOnly) d_varInfo[v].fanins.push_back(l);
    if (l.isVar()) d_varInfo[l.getVar()].fanouts.push_back(v);
  }
  return Lit(v);
}
Exemple #20
0
void translate_to_mathematica(const map<Expr, unsigned>& variables, const Expr& assertion) {
  bool first;
  
  unsigned n = assertion.getNumChildren();
  
  if (n == 0) {
    assert(false);
  } else {
    
    std::string op;
    bool binary = false;
    bool theory = false;
    
    
    switch (assertion.getKind()) {
      case kind::NOT: 
        cout << "!";  
        translate_to_mathematica(variables, assertion[0]);
        break;
      case kind::OR:
        first = true;
        cout << "(";
        for (unsigned i = 0; i < n; ++ i) {
          if (!first) {
            cout << " || ";
          }
          first = false;
          translate_to_mathematica(variables, assertion[i]);
        }
        cout << ")";
        break;
      case kind::AND:
        first = true;
        cout << "(";
        for (unsigned i = 0; i < n; ++ i) {
          if (!first) {
            cout << " && ";
          }
          first = false;
          translate_to_mathematica(variables, assertion[i]);
        }
        cout << ")";
        break;      
      case kind::IMPLIES:
        cout << "Implies[";
        translate_to_mathematica(variables, assertion[0]);
        cout << ",";
        translate_to_mathematica(variables, assertion[1]);
        cout << "]";
        break;
      case kind::IFF:
        cout << "Equivalent[";
        translate_to_mathematica(variables, assertion[0]);
        cout << ",";
        translate_to_mathematica(variables, assertion[1]);
        cout << "]";
        break;            
      case kind::EQUAL:
        op = "==";
        theory = true;
	break;
      case kind::LT:
        op = "<";
        theory = true;
        break;
      case kind::LEQ:
        op = "<=";
        theory = true;
        break;
      case kind::GT:
        op = ">";
        theory = true;
        break;
      case kind::GEQ:
        op = ">=";
        theory = true;
        break;
      default:
        assert(false);
        break;
    }

    if (binary) {
      cout << "(";
      translate_to_mathematica(variables, assertion[0]);
      cout << " " << op << " ";
      translate_to_mathematica(variables, assertion[1]);
      cout << ")";
    }      

    if (theory) {
      cout << "(";
      translate_to_mathematica_term(variables, assertion[0]);
      cout << " " << op << " ";
      translate_to_mathematica_term(variables, assertion[1]);
      cout << ")";
    }      
  }  
}
Exemple #21
0
Expr TheoryArith::rewriteToDiff(const Expr& e)
{
  Expr tmp = e[0] - e[1];
  tmp = canonRec(tmp).getRHS();
  switch (tmp.getKind()) {
    case RATIONAL_EXPR: {
      Rational r = tmp.getRational();
      switch (e.getKind()) {
        case LT:
          if (r < 0) return trueExpr();
          else return falseExpr();
        case LE:
          if (r <= 0) return trueExpr();
          else return falseExpr();
        case GT:
          if (r > 0) return trueExpr();
          else return falseExpr();
        case GE:
          if (r >= 0) return trueExpr();
          else return falseExpr();
        case EQ:
          if (r == 0) return trueExpr();
          else return falseExpr();
      }
    }
    case MULT:
      DebugAssert(tmp[0].isRational(), "Unexpected term structure from canon");
      if (tmp[0].getRational() != -1) return e;
      return Expr(e.getOp(), theoryCore()->getTranslator()->zeroVar() - tmp[1], rat(0));
    case PLUS: {
      DebugAssert(tmp[0].isRational(), "Unexpected term structure from canon");
      Rational c = tmp[0].getRational();
      Expr x, y;
      if (tmp.arity() == 2) {
        if (tmp[1].getKind() == MULT) {
          x = theoryCore()->getTranslator()->zeroVar();
          y = tmp[1];
        }
        else {
          x = tmp[1];
          y = rat(-1) * theoryCore()->getTranslator()->zeroVar();
        }
      }
      else if (tmp.arity() == 3) {
        if (tmp[1].getKind() == MULT) {
          x = tmp[2];
          y = tmp[1];
        }
        else if (tmp[2].getKind() == MULT) {
          x = tmp[1];
          y = tmp[2];
        }
        else return e;
      }
      else return e;
      if (x.getKind() == MULT) return e;
      DebugAssert(y[0].isRational(), "Unexpected term structure from canon");
      if (y[0].getRational() != -1) return e;
      return Expr(e.getOp(), x - y[1], getEM()->newRatExpr(-c));
    }
    default:
      return Expr(e.getOp(), tmp - theoryCore()->getTranslator()->zeroVar(), rat(0));
      break;
  }
  return e;
}
Exemple #22
0
void TheoryUF::assertFact(const Theorem& e)
{
  const Expr& expr = e.getExpr();
  switch (expr.getKind()) {
    case NOT:
      break;
    case APPLY:
      if (expr.getOpExpr().computeTransClosure()) {
	enqueueFact(d_rules->relToClosure(e));
      }
      else if (expr.getOpKind() == TRANS_CLOSURE) {
        // const Expr& rel = expr.getFun();
        DebugAssert(expr.isApply(), "Should be apply");
        Expr rel = resolveID(expr.getOpExpr().getName());
        DebugAssert(!rel.isNull(), "Expected known identifier");
        DebugAssert(rel.isSymbol() && rel.getKind()==UFUNC && expr.arity()==2,
                    "Unexpected use of transitive closure: "+expr.toString());

        // Insert into transitive closure table
        ExprMap<TCMapPair*>::iterator i = d_transClosureMap.find(rel);
        TCMapPair* pTable;
        if (i == d_transClosureMap.end()) {
          pTable = new TCMapPair();
          d_transClosureMap[rel] = pTable;
        }
        else {
          pTable = (*i).second;
        }

        ExprMap<CDList<Theorem>*>::iterator i2 = pTable->appearsFirstMap.find(expr[0]);
        CDList<Theorem>* pList;
        if (i2 == pTable->appearsFirstMap.end()) {
          pList = new(true) CDList<Theorem>(theoryCore()->getCM()->getCurrentContext());
          pTable->appearsFirstMap[expr[0]] = pList;
        }
        else {
          pList = (*i2).second;
        }
        pList->push_back(e);

        i2 = pTable->appearsSecondMap.find(expr[1]);
        if (i2 == pTable->appearsSecondMap.end()) {
          pList = new(true) CDList<Theorem>(theoryCore()->getCM()->getCurrentContext());
          pTable->appearsSecondMap[expr[1]] = pList;
        }
        else {
          pList = (*i2).second;
        }
        pList->push_back(e);

        // Compute transitive closure with existing relations
        size_t s,l;
        i2 = pTable->appearsFirstMap.find(expr[1]);
        if (i2 != pTable->appearsFirstMap.end()) {
          pList = (*i2).second;
          s = pList->size();
          for (l = 0; l < s; ++l) {
            enqueueFact(d_rules->relTrans(e,(*pList)[l]));
          }
        }

        i2 = pTable->appearsSecondMap.find(expr[0]);
        if (i2 != pTable->appearsSecondMap.end()) {
          pList = (*i2).second;
          s = pList->size();
          for (l = 0; l < s; ++l) {
            enqueueFact(d_rules->relTrans((*pList)[l],e));
          }
        }
      }
      break;
    default:
      break;
  }
}