theory_simulate.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  *\file theory_simulate.cpp
00004  *\brief Implementation of class TheorySimulate.
00005  *
00006  * Author: Sergey Berezin
00007  *
00008  * Created: Tue Oct  7 10:28:14 2003
00009  *
00010  * <hr>
00011  * Copyright (C) 2003 by the Board of Trustees of Leland Stanford
00012  * Junior University and by New York University. 
00013  *
00014  * License to use, copy, modify, sell and/or distribute this software
00015  * and its documentation for any purpose is hereby granted without
00016  * royalty, subject to the terms and conditions defined in the \ref
00017  * LICENSE file provided with this distribution.  In particular:
00018  *
00019  * - The above copyright notice and this permission notice must appear
00020  * in all copies of the software and related documentation.
00021  *
00022  * - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES,
00023  * EXPRESSED OR IMPLIED.  USE IT AT YOUR OWN RISK.
00024  * 
00025  * <hr>
00026  * 
00027  */
00028 /*****************************************************************************/
00029 
00030 #include "theory_simulate.h"
00031 #include "simulate_proof_rules.h"
00032 #include "typecheck_exception.h"
00033 #include "parser_exception.h"
00034 #include "smtlib_exception.h"
00035 // For the type REAL
00036 #include "theory_arith.h"
00037 
00038 
00039 using namespace std;
00040 using namespace CVCL;
00041 
00042 
00043 TheorySimulate::TheorySimulate(TheoryCore* core)
00044   : Theory(core, "Simulate") {
00045   // Initialize the proof rules
00046   d_rules = createProofRules();
00047   // Register the kinds
00048   vector<int> kinds;
00049   kinds.push_back(SIMULATE);
00050   // Register the theory with the core
00051   registerTheory(this, kinds, false /* no solver */);
00052 }
00053 
00054 
00055 TheorySimulate::~TheorySimulate() {
00056   delete d_rules;
00057 }
00058 
00059 
00060 Theorem
00061 TheorySimulate::rewrite(const Expr& e) {
00062   switch (e.getKind()) {
00063   case SIMULATE:
00064     return d_rules->expandSimulate(e);
00065     break;
00066   default:
00067     return reflexivityRule(e);
00068   }
00069 }
00070 
00071 
00072 void
00073 TheorySimulate::computeType(const Expr& e) {
00074   switch (e.getKind()) {
00075   case SIMULATE: { // SIMULATE(f, s0, i_1, ..., i_k, N)
00076     const int arity = e.arity();
00077     if (!e[arity - 1].isRational() || 
00078         !e[arity - 1].getRational().isInteger()) {
00079       throw TypecheckException
00080         ("Number of cycles in SIMULATE (last arg) "
00081          "must be an integer constant:\n\n  " + e[arity -1].toString()
00082          +"\n\nIn the following expression:\n\n  "
00083          +e.toString());
00084     }
00085 
00086     const Expr& fn(e[0]);
00087     Type fnType(getBaseType(fn));
00088     // The arity of function is k+1, which is e.arity()-2.
00089     // The arity of the type also includes the result type.
00090     if(fnType.arity() != e.arity()-1)
00091       throw TypecheckException
00092         ("Wrong number of arguments in SIMULATE:\n\n"
00093          +e.toString()
00094          +"\n\nExpected "+int2string(fnType.arity()+1)
00095          +" arguments, but received "+int2string(e.arity())+".");
00096     // Build the function type that SIMULATE expects
00097     vector<Type> argTp;
00098     // The (initial) state type
00099     Type resType(getBaseType(e[1]));
00100     argTp.push_back(resType);
00101     for(int i=2, iend=e.arity()-1; i<iend; ++i) {
00102       Type iTp(e[i].getType());
00103       Type iTpBase(getBaseType(e[i]));
00104       if(!iTp.isFunction() || iTp.arity() != 2 || !isReal(iTpBase[0]))
00105         throw TypecheckException
00106           ("Type mismatch in SIMULATE:\n\n  "
00107            +e.toString()
00108            +"\n\nThe input #"+int2string(i-1)
00109            +" is expected to be of type:\n\n  REAL -> <something>"
00110            "\n\nBut the actual type is:\n\n  "
00111            +iTp.toString());
00112       argTp.push_back(iTpBase[1]);
00113     }
00114     Type expectedFnType(Type::funType(argTp, resType));
00115     if(fnType != expectedFnType)
00116       throw TypecheckException
00117         ("Type mismatch in SIMULATE:\n\n  "
00118          +e.toString()
00119          +"\n\nThe transition function is expected to be of type:\n\n  "
00120          +expectedFnType.toString()
00121          +"\n\nBut the actual type is:\n\n  "
00122          +fnType.toString());
00123 
00124     e.setType(resType);
00125     break;
00126   }
00127   default:
00128     DebugAssert(false,"TheorySimulate::computeType: Unexpected expression: "
00129                 +e.toString());
00130   }
00131 }
00132 
00133 ///////////////////////////////////////////////////////////////////////////////
00134 //parseExprOp:
00135 //Recursive call of parseExpr defined in theory_ libaries based on kind of expr 
00136 //being built
00137 ///////////////////////////////////////////////////////////////////////////////
00138 Expr
00139 TheorySimulate::parseExprOp(const Expr& e) {
00140   TRACE("parser", "TheorySimulate::parseExprOp(", e, ")");
00141   // If the expression is not a list, it must have been already
00142   // parsed, so just return it as is.
00143   if(RAW_LIST != e.getKind()) return e;
00144 
00145   DebugAssert(e.arity() > 0,
00146               "TheorySimulate::parseExprOp:\n e = "+e.toString());
00147   /* The first element of the list (e[0] is an ID of the operator. 
00148      ID string values are the dirst element of the expression */ 
00149   const Expr& c1 = e[0][0];
00150   int kind = getEM()->getKind(c1.getString());
00151   switch(kind) {
00152   case SIMULATE: { // Application of SIMULATE to args
00153     vector<Expr> k;
00154     Expr::iterator i = e.begin(), iend=e.end();
00155     // Skip first element of the vector of kids in 'e'.
00156     // The first element is the operator.
00157     ++i; 
00158     // Parse the kids of e and push them into the vector 'k'
00159     for(; i!=iend; ++i) 
00160       k.push_back(parseExpr(*i));
00161     return Expr(SIMULATE, k, e.getEM());
00162     break;
00163   }
00164   default:
00165     DebugAssert(false, "TheorySimulate::parseExprOp: Unexpected operator: "
00166                 +e.toString());
00167   }
00168   return e;
00169 }
00170 
00171 Expr
00172 TheorySimulate::computeTCC(const Expr& e) {
00173   switch (e.getKind()) {
00174   case SIMULATE: {
00175     // TCC(SIMULATE(f, s, i1, ..., ik, N)):
00176 
00177     // First, we require that the type of the first argument of f is
00178     // exactly the same as the type of f's result (otherwise we need
00179     // to check subtyping relation, which might be undecidable), and
00180     // whether f is defined on s.
00181     //
00182     // Then, we check that the result type of i_j exactly matches the
00183     // type of the j+1-th argument of f (again, for efficiency and
00184     // decidability reasons), and that each i_j is defined on every
00185     // integer from 0..N-1.
00186     vector<Expr> tccs;
00187     Type fnType(e[0].getType());
00188     DebugAssert(fnType.arity() == e.arity()-1,
00189                 "TheorySimulate::computeTCC: SIMULATE() doesn't typecheck: "
00190                 +e.toString());
00191     Type resType(fnType[fnType.arity()-1]);
00192     // Check that the state type matches the 1st arg and the result type in f
00193     if(fnType[0] != resType)
00194       return getEM()->falseExpr();
00195     // Compute TCC for f on the initial state
00196     tccs.push_back(getTypePred(fnType[0], e[1]));
00197 
00198     const Rational& N = e[e.arity()-1].getRational();
00199     // Now, iterate through the inputs
00200     for(int i=2, iend=e.arity()-1; i<iend; ++i) {
00201       Type iTp(e[i].getType());
00202       DebugAssert(iTp.isFunction() && iTp.arity()==2,
00203                   "TheorySimulate::computeTCC: SIMULATE() doesn't typecheck: "
00204                   +e.toString());
00205       // Match the return type of i-th input with f's argument
00206       if(iTp[1] != fnType[i-1])
00207         return getEM()->falseExpr();
00208       // Compute the TCC for i(0) ... i(N-1)
00209       for(Rational j=0; j<N; j = j+1)
00210         tccs.push_back(getTypePred(iTp[0], getEM()->newRatExpr(j)));
00211     }
00212     return rewriteAnd(andExpr(tccs)).getRHS();
00213   }
00214   default: 
00215     DebugAssert(false, "TheorySimulate::computeTCC("+e.toString()
00216                 +")\n\nUnknown expression.");
00217     return getEM()->trueExpr();
00218   }
00219 }
00220 
00221 
00222 ExprStream&
00223 TheorySimulate::print(ExprStream& os, const Expr& e) {
00224   switch(os.lang()) {
00225   case PRESENTATION_LANG:
00226     switch(e.getKind()) {
00227     case SIMULATE:{
00228       os << "SIMULATE" << "(" << push;
00229       bool first(true);
00230       for (int i = 0; i < e.arity(); i++) {
00231         if (first) first = false;
00232         else os << push << "," << pop << space;
00233         os << e[i];
00234       }
00235       os << push << ")";
00236       break;
00237     }
00238     default:
00239       // Print the top node in the default LISP format, continue with
00240       // pretty-printing for children.
00241       e.printAST(os);
00242       
00243       break;
00244     }
00245     break;
00246   case SMTLIB_LANG:
00247     d_theoryUsed = true;
00248     throw SmtlibException("TheorySimulate::print: SMTLIB not supported");
00249     switch(e.getKind()) {
00250     case SIMULATE:{
00251       os << "(" << push << "SIMULATE" << space;
00252       for (int i = 0; i < e.arity(); i++) {
00253         os << space << e[i];
00254       }
00255       os << push << ")";
00256       break;
00257     }
00258     default:
00259       // Print the top node in the default LISP format, continue with
00260       // pretty-printing for children.
00261       e.printAST(os);
00262       
00263       break;
00264     }
00265     break;
00266   case LISP_LANG:
00267     switch(e.getKind()) {
00268     case SIMULATE:{
00269       os << "(" << push << "SIMULATE" << space;
00270       for (int i = 0; i < e.arity(); i++) {
00271         os << space << e[i];
00272       }
00273       os << push << ")";
00274       break;
00275     }
00276     default:
00277       // Print the top node in the default LISP format, continue with
00278       // pretty-printing for children.
00279       e.printAST(os);
00280       
00281       break;
00282     }
00283     break;
00284   default:  // Not a known language
00285     e.printAST(os);
00286     break;
00287   }
00288   return os;
00289 }

Generated on Thu Apr 13 16:57:35 2006 for CVC Lite by  doxygen 1.4.4