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

Generated on Fri May 20 13:14:00 2005 for CVC Lite by  doxygen 1.3.9.1