Exemple #1
0
/*
 * Learn a constraint for the exists variable based on the
 * existing forall witness for constraint i:
 * - the witness is defined by the uvars of constraint i
 *   and the values stored in uvalue_aux.
 *
 * This function adds a constraint to the exists_context that will remove the
 * current exists model:
 * - if solver->option is EF_NOGEN_OPTION, the new constraint is
 *   of the form (or (/= var[0] eval[k0]) ... (/= var[k-1] eval[k-1]))
 *   where var[0 ... k-1] are the exist variables of constraint i
 * - if solver->option is EF_GEN_BY_SUBST_OPTION, we build a new
 *   constraint by substitution (option 2)
 *
 * If something goes wrong, then solver->status is updated to EF_STATUS_ERROR.
 * If the new learned assertion makes the exist context trivially unsat
 * then context->status is set to EF_STATUS_UNSAT.
 * Otherwise context->status is kept as is.
 */
static void ef_solver_learn(ef_solver_t *solver, uint32_t i) {
  ef_cnstr_t *cnstr;
  term_t *val;
  term_t new_constraint;
  uint32_t n;
  int32_t code;

  assert(i < ef_prob_num_constraints(solver->prob));
  cnstr = solver->prob->cnstr + i;

  switch (solver->option) {
  case EF_NOGEN_OPTION:
    /*
     * project solver->evalues on the existential
     * variables that occur in constraint i.
     * then build (or (/= evar[0] val[0]) ... (/= evar[n-1] val[n-1]))
     */
    n = ef_constraint_num_evars(cnstr);
    resize_ivector(&solver->evalue_aux, n);
    solver->evalue_aux.size = n;
    val = solver->evalue_aux.data;
    ef_project_exists_model(solver->prob, solver->evalue, cnstr->evars, val, n);
    new_constraint = ef_generalize1(solver->prob, cnstr->evars, val, n);
    break;

  case EF_GEN_BY_SUBST_OPTION:
    val = solver->uvalue_aux.data;
    new_constraint = ef_generalize2(solver->prob, i, val);
    if (new_constraint < 0) {
      // error in substitution
      solver->status = EF_STATUS_SUBST_ERROR;
      solver->error_code = new_constraint;
      return;
    }
    break;

  case EF_GEN_BY_PROJ_OPTION:
  default: // added this to prevent bogus GCC warning
    new_constraint = ef_generalize3(solver, i);
    if (new_constraint < 0) {     
      return;
    }
    break;
  }

  // add the new constraint to the exists context
  code = update_exists_context(solver, new_constraint);
  if (code == TRIVIALLY_UNSAT) {
    solver->status = EF_STATUS_UNSAT;
  } else if (code < 0) {
    solver->status = EF_STATUS_ASSERT_ERROR;
    solver->error_code = code;
  }
}
Exemple #2
0
/*
 * Sampling for the i-th constraint in solver->prob
 * - search for at most max_samples y's that satisfy the assumption of constraint i in prob
 * - for each such y, add a new constraint to the exist context ctx
 * - max_samples = bound on the number of samples to take (must be positive)
 *
 * Constraint i is of the form
 *    (FORALL Y_i: B_i(Y_i) => C(X_i, Y_i))
 * - every sample is a model y_i that satisfies B_i.
 * - for each sample, we learn that any good candidate X_i must satisfy C(X_i, y_i).
 *   So we add the constraint  C(X_i, y_i) to ctx.
 *
 * Update the solver->status to
 * - EF_STATUS_UNSAT if the exits context is trivially unsat
 * - EF_STATUS_..._ERRORif something goes wrong
 * - EF_STATUS_INTERRUPTED if a call to check/recheck context is interrupted
 * keep it unchanged otherwise (should be EF_STATUS_SEARCHING).
 */
static void ef_sample_constraint(ef_solver_t *solver, uint32_t i) {
  context_t *sampling_ctx;
  ef_cnstr_t *cnstr;
  term_t *value;
  uint32_t nvars, samples;
  int32_t ucode, ecode;
  smt_status_t status;
  term_t cnd;

  assert(i < ef_prob_num_constraints(solver->prob) && solver->max_samples > 0);

  cnstr = solver->prob->cnstr + i;

  /*
   * make uvalue_aux large enough
   * its size = number of universal variables in constraint i
   */
  nvars = ef_constraint_num_uvars(cnstr);
  resize_ivector(&solver->uvalue_aux, nvars);
  solver->uvalue_aux.size = nvars;
  value = solver->uvalue_aux.data;

  samples = solver->max_samples;

  /*
   * assert the assumption in the forall context
   */
  sampling_ctx = get_forall_context(solver);
  ucode = assert_formula(sampling_ctx, cnstr->assumption);
  while (ucode == CTX_NO_ERROR) {
    status = satisfy_context(sampling_ctx, solver->parameters, cnstr->uvars, nvars, value, NULL);
    switch (status) {
    case STATUS_SAT:
    case STATUS_UNKNOWN:
      // learned condition on X:
      cnd = ef_substitution(solver->prob, cnstr->uvars, value, nvars, cnstr->guarantee);
      if (cnd < 0) {
	solver->status = EF_STATUS_SUBST_ERROR;
	solver->error_code = cnd;
	goto done;
      }
      ecode = update_exists_context(solver, cnd);
      if (ecode < 0) {
	solver->status = EF_STATUS_ASSERT_ERROR;
	solver->error_code = ecode;
	goto done;
      }
      if (ecode == TRIVIALLY_UNSAT) {
	solver->status = EF_STATUS_UNSAT;
	goto done;
      }
      break;

    case STATUS_UNSAT:
      // no more samples for this constraints
      goto done;

    case STATUS_INTERRUPTED:
      solver->status = EF_STATUS_INTERRUPTED;
      goto done;

    default:
      solver->status = EF_STATUS_CHECK_ERROR;
      solver->error_code = status;
      goto done;
    }

    samples --;
    if (samples == 0) goto done;

    ucode = assert_blocking_clause(sampling_ctx);
  }

  /*
   * if ucode < 0, something went wrong in assert_formula
   * or in assert_blocking_clause
   */
  if (ucode < 0) {
    solver->status = EF_STATUS_ASSERT_ERROR;
    solver->error_code = ucode;
  }

 done:
  clear_forall_context(solver, true);
}