void distribute_forall::reduce1_quantifier(quantifier * q) {
    // This transformation is applied after skolemization/quantifier elimination. So, all quantifiers are universal.
    SASSERT(q->is_forall());

    // This transformation is applied after basic pre-processing steps.
    // So, we can assume that
    //    1) All (and f1 ... fn) are already encoded as (not (or (not f1 ... fn)))
    //    2) All or-formulas are flat (or f1 (or f2 f3)) is encoded as (or f1 f2 f3)

    expr * e = get_cached(q->get_expr());
    if (m_manager.is_not(e) && m_manager.is_or(to_app(e)->get_arg(0))) {
        // found target for simplification
        // (forall X (not (or F1 ... Fn)))
        // -->
        // (and (forall X (not F1))
        //      ...
        //      (forall X (not Fn)))
        app * or_e        = to_app(to_app(e)->get_arg(0));
        unsigned num_args = or_e->get_num_args();
        expr_ref_buffer new_args(m_manager);
        for (unsigned i = 0; i < num_args; i++) {
            expr * arg = or_e->get_arg(i);
            expr_ref not_arg(m_manager);
            // m_bsimp.mk_not applies basic simplifications. For example, if arg is of the form (not a), then it will return a.
            m_bsimp.mk_not(arg, not_arg);
            quantifier_ref tmp_q(m_manager);
            tmp_q = m_manager.update_quantifier(q, not_arg);
            expr_ref new_q(m_manager);
            elim_unused_vars(m_manager, tmp_q, new_q);
            new_args.push_back(new_q);
        }
        expr_ref result(m_manager);
        // m_bsimp.mk_and actually constructs a (not (or ...)) formula, 
        // it will also apply basic simplifications.
        m_bsimp.mk_and(new_args.size(), new_args.c_ptr(), result);
        cache_result(q, result);
    }
    else {
        cache_result(q, m_manager.update_quantifier(q, e));
    }
}
Exemple #2
0
void bv_elim_star::reduce1_quantifier(quantifier* q) {
    quantifier_ref r(m_manager);
    proof_ref pr(m_manager);
    m_bv_elim.elim(q, r);
    if (m_manager.fine_grain_proofs()) {
        pr = m_manager.mk_rewrite(q, r.get());
    }
    else {
        pr = 0;
    }
    cache_result(q, r, pr);
}
Exemple #3
0
 subpaving::var process_mul(app * t, unsigned depth, mpz & n, mpz & d) {
     unsigned num_args = t->get_num_args();
     if (num_args <= 1)
         found_non_simplified();
     rational k;
     expr * m;
     if (m_autil.is_numeral(t->get_arg(0), k)) {
         if (num_args != 2)
             found_non_simplified();
         qm().set(n, k.to_mpq().numerator());
         qm().set(d, k.to_mpq().denominator());
         m = t->get_arg(1);
     }
     else {
         qm().set(n, 1);
         qm().set(d, 1);
         m = t;
     }
     expr * const * margs;
     unsigned sz;
     if (m_autil.is_mul(m)) {
         margs = to_app(m)->get_args();
         sz    = to_app(m)->get_num_args();
     }
     else {
         margs = &m;
         sz    = 1;
     }
     scoped_mpz n_arg(qm());
     scoped_mpz d_arg(qm());
     sbuffer<subpaving::power> pws;
     for (unsigned i = 0; i < sz; i++) {
         expr * arg = margs[i];
         unsigned k; 
         as_power(arg, arg, k);
         subpaving::var x_arg = process(arg, depth+1, n_arg, d_arg);
         qm().power(n_arg, k, n_arg);
         qm().power(d_arg, k, d_arg);
         qm().mul(n, n_arg, n);
         qm().mul(d, d_arg, d);
         if (x_arg != subpaving::null_var)
             pws.push_back(subpaving::power(x_arg, k));
     }
     subpaving::var x;
     if (pws.empty())
         x = subpaving::null_var;
     else if (pws.size() == 1 && pws[0].degree() == 1)
         x = pws[0].get_var();
     else
         x = s().mk_monomial(pws.size(), pws.c_ptr());
     cache_result(t, x, n, d);
     return x;
 }
void distribute_forall::reduce1(expr * n) {
    switch (n->get_kind()) {
    case AST_VAR:
        cache_result(n, n);
        break;
    case AST_APP:
        reduce1_app(to_app(n));
        break;
    case AST_QUANTIFIER:
        reduce1_quantifier(to_quantifier(n));
        break;
    default: UNREACHABLE();
    }
}
Exemple #5
0
 subpaving::var process_add(app * t, unsigned depth, mpz & n, mpz & d) {
     unsigned num_args = t->get_num_args();
     mpz_buffer ns(qm()), ds(qm());
     var_buffer xs;
     scoped_mpq c(qm()), c_arg(qm());
     scoped_mpz n_arg(qm()), d_arg(qm());
     for (unsigned i = 0; i < num_args; i++) {
         expr * arg           = t->get_arg(i);
         subpaving::var x_arg = process(arg, depth+1, n_arg, d_arg);
         if (x_arg == subpaving::null_var) {
             qm().set(c_arg, n_arg, d_arg);
             qm().add(c, c_arg, c);
         }
         else {
             xs.push_back(x_arg);
             ns.push_back(n_arg);
             ds.push_back(d_arg);
         }
     }
     qm().set(d,  c.get().denominator());
     unsigned sz = xs.size();
     for (unsigned i = 0; i < sz; i++) {
         qm().lcm(d, ds[i], d);
     }
     scoped_mpz & k = d_arg;
     qm().div(d, c.get().denominator(), k);
     scoped_mpz sum_c(qm());
     qm().mul(c.get().numerator(), k, sum_c);
     for (unsigned i = 0; i < sz; i++) {
         qm().div(d, ds[i], k);
         qm().mul(ns[i], k, ns[i]);
     }
     subpaving::var x;
     if (sz == 0) {
         qm().set(n, sum_c);
         x = subpaving::null_var;
     }
     else {
         x = s().mk_sum(sum_c, sz, ns.c_ptr(), xs.c_ptr());
         qm().set(n, 1);
     }
     cache_result(t, x, n, d);
     return x;
 }
Exemple #6
0
 subpaving::var process_power(app * t, unsigned depth, mpz & n, mpz & d) {
     rational k;
     SASSERT(t->get_num_args() == 2);
     if (!m_autil.is_numeral(t->get_arg(1), k) || !k.is_int() || !k.is_unsigned()) {
         qm().set(n, 1);
         qm().set(d, 1);
         return mk_var_for(t);
     }
     unsigned _k = k.get_unsigned();
     subpaving::var x = process(t->get_arg(0), depth+1, n, d);
     if (x != subpaving::null_var) {
         subpaving::power p(x, _k);
         x = s().mk_monomial(1, &p);
     }
     qm().power(n, _k, n);
     qm().power(d, _k, d);
     cache_result(t, x, n, d);
     return x;
 }
void distribute_forall::reduce1_app(app * a) {
    SASSERT(a);
    unsigned num_args = a->get_num_args();
    unsigned j        = num_args;
    bool reduced      = false;
    m_new_args.reserve(num_args);
    app * na = a;

    while(j > 0) {
        --j;
        SASSERT(is_cached(a->get_arg(j)));
        expr * c = get_cached(a->get_arg(j));
        SASSERT(c!=0);
        if (c != a->get_arg(j)) 
            reduced = true;
        m_new_args[j] = c;
    }    

    if (reduced) {
        na = m_manager.mk_app(a->get_decl(), num_args, m_new_args.c_ptr());
    }
    
    cache_result(a, na);
}
Exemple #8
0
static const char* remap_file(const char* syscall_name, const char* pathname,
                              char* buffer, usage_t usage) {
  char* pos;
  int debug = EKAM_DEBUG;

  /* Ad-hoc debugging can be accomplished by setting debug = 1 when a particular file pattern
   * is matched. */

  if (debug) {
    fprintf(stderr, "remap for %s (%s): %s\n",
            syscall_name, (usage == READ ? "read" : "write"), pathname);
  }

  init_streams();

  if (strlen(pathname) >= PATH_MAX) {
    /* Too long. */
    if (debug) fprintf(stderr, "  name too long\n");
    errno = ENAMETOOLONG;
    return NULL;
  }

  if (get_cached_result(pathname, buffer, usage)) {
    if (debug) fprintf(stderr, "  cached: %s\n", buffer);
    return buffer;
  }

  flockfile(ekam_call_stream);

  if (strncmp(pathname, TAG_PROVIDER_PREFIX, strlen(TAG_PROVIDER_PREFIX)) == 0) {
    /* A tag reference.  Construct the tag name in |buffer|. */
    strcpy(buffer, pathname + strlen(TAG_PROVIDER_PREFIX));

    if (usage == READ) {
      /* Change first slash to a colon to form a tag.  E.g. "header/foo.h" becomes
       * "header:foo.h". */
      pos = strchr(buffer, '/');
      if (pos == NULL) {
        /* This appears to be a tag type without a name, so it should look like a directory.
         * We can use the current directory.  TODO:  Return some fake empty directory instead. */
        funlockfile(ekam_call_stream);
        strcpy(buffer, ".");
        if (debug) fprintf(stderr, "  is directory\n");
        return buffer;
      }
      *pos = ':';
      canonicalizePath(pos + 1);

      if (strcmp(buffer, "canonical:.") == 0) {
        /* HACK:  Don't try to remap top directory. */
        funlockfile(ekam_call_stream);
        if (debug) fprintf(stderr, "  current directory\n");
        return "src";
      }
    }

    /* Ask ekam to remap the file name. */
    fputs(usage == READ ? "findProvider " : "newProvider ", ekam_call_stream);
    fputs(buffer, ekam_call_stream);
    fputs("\n", ekam_call_stream);
  } else if (strcmp(pathname, TMP) == 0 ||
             strcmp(pathname, VAR_TMP) == 0 ||
             strncmp(pathname, TMP_PREFIX, strlen(TMP_PREFIX)) == 0 ||
             strncmp(pathname, VAR_TMP_PREFIX, strlen(VAR_TMP_PREFIX)) == 0) {
    /* Temp file.  Ignore. */
    funlockfile(ekam_call_stream);
    if (debug) fprintf(stderr, "  temp file: %s\n", pathname);
    return pathname;
  } else {
    if (strncmp(pathname, current_dir, strlen(current_dir)) == 0) {
      /* The app is trying to open files in the current directory by absolute path.  Treat it
       * exactly as if it had used a relative path. */
      pathname = pathname + strlen(current_dir);
    } else if (pathname[0] == '/') {
      /* Absolute path.  Note the access but don't remap. */
      if (usage == WRITE) {
        /* Cannot write to absolute paths. */
        funlockfile(ekam_call_stream);
        errno = EACCES;
        if (debug) fprintf(stderr, "  absolute path, can't write\n");
        return NULL;
      }

      fputs("noteInput ", ekam_call_stream);
      fputs(pathname, ekam_call_stream);
      fputs("\n", ekam_call_stream);
      fflush(ekam_call_stream);
      if (ferror_unlocked(ekam_call_stream)) {
        funlockfile(ekam_call_stream);
        fprintf(stderr, "error: Ekam call stream broken.\n");
        abort();
      }
      cache_result(pathname, pathname, usage);
      funlockfile(ekam_call_stream);
      if (debug) fprintf(stderr, "  absolute path: %s\n", pathname);
      return pathname;
    }

    /* Path in current directory. */
    strcpy(buffer, pathname);
    canonicalizePath(buffer);
    if (strcmp(buffer, ".") == 0) {
      /* HACK:  Don't try to remap current directory. */
      funlockfile(ekam_call_stream);
      if (debug) fprintf(stderr, "  current directory\n");
      return "src";
    } else {
      /* Ask ekam to remap the file name. */
      fputs(usage == READ ? "findInput " : "newOutput ", ekam_call_stream);
      fputs(buffer, ekam_call_stream);
      fputs("\n", ekam_call_stream);
    }
  }

  fflush(ekam_call_stream);
  if (ferror_unlocked(ekam_call_stream)) {
    funlockfile(ekam_call_stream);
    fprintf(stderr, "error: Ekam call stream broken.\n");
    abort();
  }

  /* Carefully lock the return stream then unlock the call stream, so that we know that
   * responses will be received in the correct order. */
  flockfile(ekam_return_stream);
  funlockfile(ekam_call_stream);

  /* Read response from Ekam. */
  if (fgets(buffer, PATH_MAX, ekam_return_stream) == NULL) {
    funlockfile(ekam_return_stream);
    fprintf(stderr, "error: Ekam return stream broken.\n");
    abort();
  }

  /* Done reading. */
  funlockfile(ekam_return_stream);

  /* Remove the trailing newline. */
  pos = strchr(buffer, '\n');
  if (pos == NULL) {
    fprintf(stderr, "error: Path returned from Ekam was too long.\n");
    abort();
  }
  *pos = '\0';

  if (*buffer == '\0') {
    /* Not found. */
    errno = ENOENT;
    if (debug) fprintf(stderr, "  ekam says no such file\n");
    return NULL;
  }

  cache_result(pathname, buffer, usage);

  if (debug) fprintf(stderr, "  remapped to: %s\n", buffer);
  return buffer;
}