array_theorem_producer.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file array_theorem_producer.cpp
00004  * \brief Description: TRUSTED implementation of array proof rules.
00005  * 
00006  * Author: Clark Barrett
00007  * 
00008  * Created: Thu May 29 14:02:16 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 
00031 // This code is trusted
00032 #define _CVCL_TRUSTED_
00033 
00034 
00035 #include "array_theorem_producer.h"
00036 #include "theory_array.h"
00037 #include "theory_core.h"
00038 
00039 
00040 using namespace std;
00041 using namespace CVCL;
00042 
00043 
00044 ////////////////////////////////////////////////////////////////////
00045 // TheoryArray: trusted method for creating ArrayTheoremProducer
00046 ////////////////////////////////////////////////////////////////////
00047 
00048 
00049 ArrayProofRules* TheoryArray::createProofRules() {
00050   return new ArrayTheoremProducer(theoryCore()->getTM());
00051 }
00052   
00053 
00054 ////////////////////////////////////////////////////////////////////
00055 // Proof rules
00056 ////////////////////////////////////////////////////////////////////
00057 
00058 
00059 #define CLASS_NAME "CVCL::ArrayTheoremProducer"
00060 
00061 
00062 // ==>
00063 // write(store, index_0, v_0, index_1, v_1, ..., index_n, v_n) = store IFF
00064 //
00065 // read(store, index_n) = v_n &
00066 // index_{n-1} != index_n -> read(store, index_{n-1}) = v_{n-1} &
00067 // (index_{n-2} != index_{n-1} & index_{n-2} != index_n) -> read(store, index_{n-2}) = v_{n-2} &
00068 // ...
00069 // (index_1 != index_2 & ... & index_1 != index_n) -> read(store, index_1) = v_1
00070 // (index_0 != index_1 & index_0 != index_2 & ... & index_0 != index_n) -> read(store, index_0) = v_0
00071 Theorem
00072 ArrayTheoremProducer::rewriteSameStore(const Expr& e, int n)
00073 {
00074   IF_DEBUG(
00075     DebugAssert(e.isEq(), "EQ expected");
00076     Expr e1 = e[0];
00077     int N = 0;
00078     while (isWrite(e1)) { N++; e1 = e1[0]; }
00079     DebugAssert(N == n && n > 0, "Counting error");
00080     DebugAssert(e1 == e[1], "Stores do not match");
00081   )
00082     
00083   Assumptions a;
00084   Proof pf;
00085   Expr write_i, write_j, index_i, index_j, hyp, conc, result;
00086   int i, j;
00087 
00088   write_i = e[0];
00089   for (i = n-1; i >= 0; --i) {
00090     index_i = write_i[1];
00091 
00092     // build: [index_i /= index_n && index_i /= index_(n-1) &&
00093     //         ... && index_i /= index_(i+1)] -> read(store, index_i) = v_i
00094     write_j = e[0];
00095     for (j = n - 1; j > i; --j) {
00096       index_j = write_j[1];
00097       Expr hyp2(!((index_i.getType().isBool())? 
00098                    index_i.iffExpr(index_j) : index_i.eqExpr(index_j)));
00099       if (hyp.isNull()) hyp = hyp2;
00100       else hyp = hyp && hyp2;
00101       write_j = write_j[0];
00102     }
00103     Expr r1(Expr(READ, e[1], index_i));
00104     conc = (r1.getType().isBool())? 
00105       r1.iffExpr(write_i[2]) : r1.eqExpr(write_i[2]);
00106     if (!hyp.isNull()) conc = hyp.impExpr(conc);
00107 
00108     // And into result
00109     if (result.isNull()) result = conc;
00110     else result = result && conc;
00111 
00112     // Prepare for next iteration
00113     write_i = write_i[0];
00114     hyp = Expr();
00115   }
00116   if (withProof()) pf = newPf("rewriteSameStore", e);
00117   return newRWTheorem(e, result, a, pf);
00118 }
00119 
00120 
00121 // ==> write(store, index, value) = write(...) IFF
00122 //       store = write(write(...), index, read(store, index)) &
00123 //       value = read(write(...), index)
00124 Theorem
00125 ArrayTheoremProducer::rewriteWriteWrite(const Expr& e)
00126 {
00127   IF_DEBUG(
00128     DebugAssert(e.isEq(), "EQ expected");
00129     DebugAssert(isWrite(e[0]) && isWrite(e[1]),
00130                 "Expected WRITE = WRITE");
00131   )
00132   Assumptions a;
00133   Proof pf;
00134   const Expr& left = e[0];
00135   const Expr& right = e[1];
00136   const Expr& store = left[0];
00137   const Expr& index = left[1];
00138   const Expr& value = left[2];
00139   Expr e1 = (store.getType().isBool())?
00140     store.iffExpr(Expr(WRITE, right, index, Expr(READ, store, index)))
00141     : store.eqExpr(Expr(WRITE, right, index, Expr(READ, store, index)));
00142   Expr e2 = (value.getType().isBool()) ?
00143     value.iffExpr(Expr(READ, right, index)) :
00144     value.eqExpr(Expr(READ, right, index));
00145   if (withProof()) pf = newPf("rewriteWriteWrite", e);
00146   return newRWTheorem(e, e1.andExpr(e2), a, pf);
00147 }
00148 
00149 
00150 // ==> read(write(store, index1, value), index2) =
00151 //   ite(index1 = index2, value, read(store, index2))
00152 Theorem
00153 ArrayTheoremProducer::rewriteReadWrite(const Expr& e)
00154 {
00155   IF_DEBUG(
00156     DebugAssert(isRead(e), "Read expected");
00157     DebugAssert(isWrite(e[0]), "Expected Read(Write)");
00158   )
00159   Assumptions a;
00160   Proof pf;
00161   const Expr& store = e[0][0];
00162   const Expr& index1 = e[0][1];
00163   const Expr& value = e[0][2];
00164   const Expr& index2 = e[1];
00165   Expr indexCond = (index1.getType().isBool())?
00166     index1.iffExpr(index2) : index1.eqExpr(index2);
00167   if (withProof()) pf = newPf("rewriteReadWrite", e);
00168   return newRWTheorem(e, indexCond.iteExpr(value,
00169                                            Expr(READ, store, index2)), a, pf);
00170 }
00171 
00172 
00173 // value = read(store, index) ==>
00174 //   write(store, index, value) = store
00175 Theorem
00176 ArrayTheoremProducer::rewriteRedundantWrite1(const Theorem& v_eq_r,
00177                                              const Expr& write)
00178 {
00179   DebugAssert(v_eq_r.isRewrite(), "Expected equation");
00180   DebugAssert(isRead(v_eq_r.getRHS()), "Expected Read");
00181   DebugAssert(isWrite(write) && v_eq_r.getRHS()[0] == write[0] &&
00182               v_eq_r.getRHS()[1] == write[1] && v_eq_r.getLHS() == write[2],
00183               "Error in parameters to rewriteRedundantWrite1");
00184   Assumptions a;
00185   Proof pf;
00186   if (withAssumptions()) a = v_eq_r.getAssumptions().copy();
00187   if(withProof()) {
00188     pf = newPf("rewriteRedundantWrite1", write, v_eq_r.getProof());
00189   }
00190   return newRWTheorem(write, write[0], a, pf);
00191 }
00192 
00193 
00194 // ==>
00195 //   write(write(store, index, v1), index, v2) = write(store, index, v2)
00196 Theorem
00197 ArrayTheoremProducer::rewriteRedundantWrite2(const Expr& e)
00198 {
00199   DebugAssert(isWrite(e) && isWrite(e[0]) &&
00200               e[0][1] == e[1],
00201               "Error in parameters to rewriteRedundantWrite2");
00202 
00203   Assumptions a;
00204   Proof pf;
00205   
00206   if(withProof()) {
00207     pf = newPf("rewriteRedundantWrite2", e);
00208   }
00209 
00210   return newRWTheorem(e, Expr(WRITE, e[0][0], e[1], e[2]), a, pf);
00211 }
00212 
00213 
00214 // ==>
00215 //   write(write(store, index1, v1), index2, v2) =
00216 //   write(write(store, index2, v2), index1, ite(index1 = index2, v2, v1))
00217 Theorem
00218 ArrayTheoremProducer::interchangeIndices(const Expr& e)
00219 {
00220   DebugAssert(isWrite(e) && isWrite(e[0]),
00221               "Error in parameters to interchangeIndices");
00222 
00223   Assumptions a;
00224   Proof pf;
00225   
00226   if(withProof()) {
00227     pf = newPf("interchangeIndices", e);
00228   }
00229 
00230   Expr w0 = Expr(WRITE, e[0][0], e[1], e[2]);
00231   Expr indexCond = (e[0][1].getType().isBool())?
00232     e[0][1].iffExpr(e[1]) : e[0][1].eqExpr(e[1]);
00233   Expr w2 = Expr(WRITE, w0, e[0][1], indexCond.iteExpr(e[2], e[0][2]));
00234 
00235   return newRWTheorem(e, w2, a, pf);
00236 }
00237 
00238 Theorem
00239 ArrayTheoremProducer::readArrayLiteral(const Expr& e) {
00240   if(CHECK_PROOFS) {
00241     CHECK_SOUND(e.getKind() == READ,
00242                 "ArrayTheoremProducer::readArrayLiteral("+e.toString()
00243                 +"):\n\n  expression is not a READ");
00244   }
00245 
00246   Expr arrayLit(e[0]);
00247 
00248   if (CHECK_PROOFS) {
00249     CHECK_SOUND(arrayLit.isClosure() && arrayLit.getKind()==ARRAY_LITERAL,
00250                 "ArrayTheoremProducer::readArrayLiteral("+e.toString()+")");
00251   }
00252 
00253   Expr body(arrayLit.getBody());
00254   const vector<Expr>& vars = arrayLit.getVars();
00255 
00256   if(CHECK_PROOFS) {
00257     CHECK_SOUND(vars.size() == 1, 
00258                 "ArrayTheoremProducer::readArrayLiteral("+e.toString()+"):\n"
00259                 +"wrong number of bound variables");
00260   }
00261 
00262   // Use the Expr's efficient substitution
00263   vector<Expr> ind;
00264   ind.push_back(e[1]);
00265   body = body.substExpr(vars, ind);
00266 
00267   Assumptions a;
00268   Proof pf;
00269   if(withProof())
00270     pf = newPf("read_array_literal", e);
00271   return newRWTheorem(e, body, a, pf);
00272 }

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