예제 #1
0
/*
 * Delete the whole thing
 */
void delete_ef_solver(ef_solver_t *solver) {
  if (solver->exists_context != NULL) {
    delete_context(solver->exists_context);
    safe_free(solver->exists_context);
    solver->exists_context = NULL;
  }
  if (solver->forall_context != NULL) {
    delete_context(solver->forall_context);
    safe_free(solver->forall_context);
    solver->forall_context = NULL;
  }
  if (solver->exists_model != NULL) {
    yices_free_model(solver->exists_model);
    solver->exists_model = NULL;
  }

  safe_free(solver->evalue);
  safe_free(solver->uvalue);
  solver->evalue = NULL;
  solver->uvalue = NULL;

  if (solver->full_model != NULL) {
    yices_free_model(solver->full_model);
    solver->full_model = NULL;
  }
  yices_delete_term_vector(&solver->implicant);

  delete_ivector(&solver->evalue_aux);
  delete_ivector(&solver->uvalue_aux);
  delete_ivector(&solver->all_vars);
  delete_ivector(&solver->all_values);
}
예제 #2
0
/*
 * Check satisfiability and get a model
 * - ctx = the context
 * - parameters = heuristic settings (if parameters is NULL, the defaults are used)
 * - var = array of n uninterpreted terms
 * - n = size of array evar and value
 * Output parameters;
 * - value = array of n terms (to receive the value of each var)
 * - model = to export the model (if model is NULL, nothing is exported)
 *
 * The return code is as in check_context:
 * 1) if code = STATUS_SAT then the context is satisfiable
 *    and a model is stored in value[0 ... n-1]
 *    - value[i] = a constant term mapped to evar[i] in the model
 * 2) code = STATUS_UNSAT: not satisfiable
 *
 * 3) other codes report an error of some kind or STATUS_INTTERRUPT
 */
static smt_status_t satisfy_context(context_t *ctx, const param_t *parameters, term_t *var, uint32_t n, term_t *value, model_t **model) {
  smt_status_t stat;
  model_t *mdl;
  int32_t code;

  assert(context_status(ctx) == STATUS_IDLE);

  stat = check_context(ctx, parameters);
  switch (stat) {
  case STATUS_SAT:
  case STATUS_UNKNOWN:
    mdl = yices_get_model(ctx, true);
    code = yices_term_array_value(mdl, n, var, value);
    if (model != NULL) {
      *model = mdl;
    } else {
      yices_free_model(mdl);
    }

    if (code < 0) {
      // can't convert the model to constant terms
      stat = STATUS_ERROR;
    }
    break;

  default:
    // can't build a model
    break;
  }

  return stat;
}
예제 #3
0
/*
 * Check satisfiability of the exists_context
 * - first free the exists_model if non-NULL
 * - if SAT build a model (in solver->evalue) and store the exists_model
 */
static smt_status_t ef_solver_check_exists(ef_solver_t *solver) {
  term_t *evar;
  uint32_t n;

  if (solver->exists_model != NULL) {
    yices_free_model(solver->exists_model);
    solver->exists_model = NULL;
  }

  evar = solver->prob->all_evars;
  n = iv_len(evar);
  return satisfy_context(solver->exists_context, solver->parameters, evar, n, solver->evalue, &solver->exists_model);
}
예제 #4
0
/*
 * Compute an implicant for constraint i
 * - we must have an assignment for the exists variable in solver->evalue
 *   and an assignment for the universal variables of constraints i in
 *   solver->uvalue_aux.
 * - this builds and store the full model for constraint i in solver->full_model
 *   then construct and store the implicant in solver->implicant
 *
 * Error codes: set solver->status to EF_STATUS_ERROR
 * - this may happen if yices_model_from_map or yices_implicant_for_fomuulas fail
 */
static void ef_build_implicant(ef_solver_t *solver, uint32_t i) {
  model_t *mdl;
  ef_cnstr_t *cnstr;
  term_vector_t *v;
  term_t a[2];
  uint32_t n;
  int32_t code;

  assert(i < ef_prob_num_constraints(solver->prob));

  // free the current full model if any
  if (solver->full_model != NULL) {
    yices_free_model(solver->full_model);
    solver->full_model = NULL;
  }

  // build the full_map and the correspongin model.
  ef_build_full_map(solver, i);
  n = solver->all_vars.size;
  assert(n == solver->all_values.size);
  mdl = yices_model_from_map(n, solver->all_vars.data, solver->all_values.data);
  if (mdl == NULL) {
    // error in the model construction
    solver->status = EF_STATUS_ERROR; // TODO: add another code
    solver->error_code = yices_error_code();
    return;
  }
  solver->full_model = mdl;

  cnstr = solver->prob->cnstr + i;
  a[0] = cnstr->assumption;
  a[1] = opposite_term(cnstr->guarantee);
  v = &solver->implicant;
  v->size = 0;
  code = yices_implicant_for_formulas(mdl, 2, a, v);
  if (code < 0) {
    solver->status = EF_STATUS_ERROR;
    solver->error_code = yices_error_code();
  }

#if 1
  printf("Implicant\n");
  yices_pp_term_array(stdout, v->size, v->data, 120, UINT32_MAX, 0, 0);
  printf("(%"PRIu32" literals)\n", v->size);
#endif

}
예제 #5
0
int example2_main(void) {
  type_t real;
  term_t t, a;
  int32_t code;
  context_t *ctx;
  model_t *mdl;

  /*
   * Global initialization: this must called first.
   */
  yices_init();

  /*
   * Create an uninterpreted term of type real and call it "x"
   */
  real = yices_real_type();
  t = yices_new_uninterpreted_term(real);
  code = yices_set_term_name(t, "x");

  /*
   * If code is negative, something went wrong
   */
  if (code < 0) {
    printf("Error in yices_set_term\n");
    yices_print_error(stdout);
    fflush(stdout);
    goto done;
  }


  /*
   * Create the atom (x > 0)
   */
  a = yices_arith_gt0_atom(t);

  /*
   * Print the atom:
   */
  printf("Atom: ");
  yices_pp_term(stdout, a, 120, 2, 6);

  /*
   * Check that (x > 0) is satisfiable and get a model
   * - create a context
   * - assert atom 'a' in this context
   * - check that the context is satisfiable
   */
  ctx = yices_new_context(NULL);  // NULL means use the default configuration
  code = yices_assert_formula(ctx, a);
  if (code < 0) {
    printf("Assert failed: ");
    yices_print_error(stdout);
    fflush(stdout);
    goto done;
  }

  switch (yices_check_context(ctx, NULL)) { // NULL means default heuristics
  case STATUS_SAT:
    // build the model and print it
    printf("Satisfiable\n");
    mdl = yices_get_model(ctx, true);
    code = yices_pp_model(stdout, mdl, 120, 100, 0);
    if (code < 0) {
      printf("Print model failed: ");
      yices_print_error(stdout);
      fflush(stdout);
      goto done;
    }
    // cleanup: delete the model
    yices_free_model(mdl);
    break;

  case STATUS_UNSAT:
    printf("Unsatisfiable\n");
    break;

  case STATUS_UNKNOWN:
    printf("Status is unknown\n");
    break;

  case STATUS_IDLE:
  case STATUS_SEARCHING:
  case STATUS_INTERRUPTED:
  case STATUS_ERROR:
    // these codes should not be returned
    printf("Bug: unexpected status returned\n");
    break;
  }

  /*
   * Delete the context: this is optional since yices_exit
   * would do it anyway.
   */
  yices_free_context(ctx);

 done:
  /*
   * Global cleanup: free all memory used by Yices
   */
  yices_exit();

  return 0;
}
예제 #6
0
/*
 * Sample exists models
 * - stop when we find one that's not refuted by the forall constraints
 * - or when we reach the iteration bound
 *
 * Result:
 * - solver->status = EF_STATUS_ERROR if something goes wrong
 * - solver->status = EF_STATUS_INTERRUPTED if one of the calls to
 *   check_context is interrupted
 * - solver->status = EF_STATUS_UNSAT if all efmodels have been tried and none
 *   of them worked
 * - solver->status = EF_STATUS_UNKNOWN if the iteration limit is reached
 * - solver->status = EF_STATUS_SAT if a good model is found
 *
 * In the later case,
 * - the model is stored in solver->exists_model
 * - also it's available as a mapping form solver->prob->evars to solver->evalues
 *
 * Also solver->iters stores the number of iterations used.
 */
static void ef_solver_search(ef_solver_t *solver) {
  smt_status_t stat;
  uint32_t i, max;

  max = solver->max_iters;
  i = 0;

  assert(max > 0);

#if 0
  printf("\nEF search: %"PRIu32" constraints, %"PRIu32" exists vars, %"PRIu32" forall vars\n",
	 ef_prob_num_constraints(solver->prob),
	 ef_prob_num_evars(solver->prob),
	 ef_prob_num_uvars(solver->prob));

  //  printf("\nConditions on the exists variables:\n");
  //  yices_pp_term_array(stdout, ef_prob_num_conditions(solver->prob), solver->prob->conditions, 120, UINT32_MAX, 0, 0);
#endif

  ef_solver_start(solver);
  while (solver->status == EF_STATUS_SEARCHING && i < max) {

#if 0
    printf("\n--- Iteration %"PRIu32" (scan_idx = %"PRIu32") ---\n", i, solver->scan_idx);
#endif

    stat = ef_solver_check_exists(solver);
    switch (stat) {
    case STATUS_SAT:
    case STATUS_UNKNOWN:
      // we have a candidate exists model
      // check it and learn what we can

#if 0
      // FOR DEBUGGING
      printf("Candidate exists model:\n");
      print_ef_solution(stdout, solver);
      printf("\n");
#endif

      ef_solver_check_exists_model(solver);
      break;

    case STATUS_UNSAT:
      solver->status = EF_STATUS_UNSAT;
      break;

    case STATUS_INTERRUPTED:
      solver->status = EF_STATUS_INTERRUPTED;
      break;

    default:
      solver->status = EF_STATUS_CHECK_ERROR;
      solver->error_code = stat;
      break;
    }

    i ++;
  }

  /*
   * Cleanup and set status if i == max
   */
  if (solver->status != EF_STATUS_SAT && solver->exists_model != NULL) {
    yices_free_model(solver->exists_model);
    solver->exists_model = NULL;
    if (solver->status == EF_STATUS_SEARCHING) {
      assert(i == max);
      solver->status = EF_STATUS_UNKNOWN;
    }
  }

  solver->iters = i;
}
예제 #7
0
/*
 * Option 3: generalize by computing an implicant then
 * applying projection.
 */
static term_t ef_generalize3(ef_solver_t *solver, uint32_t i) {
  model_t *mdl;
  ef_cnstr_t *cnstr;
  ivector_t *v, *w;
  term_t a[2];
  uint32_t n;
  int32_t code;
  proj_flag_t pflag;
  term_t result;

  assert(i < ef_prob_num_constraints(solver->prob));

  // free the current full model if any
  if (solver->full_model != NULL) {
    yices_free_model(solver->full_model);
    solver->full_model = NULL;
  }

  // build the full_map and the corresponding model.
  ef_build_full_map(solver, i);
  n = solver->all_vars.size;
  assert(n == solver->all_values.size);
  mdl = yices_model_from_map(n, solver->all_vars.data, solver->all_values.data);
  if (mdl == NULL) {
    // error in the model construction
    solver->status = EF_STATUS_MDL_ERROR;
    solver->error_code = yices_error_code();
    return NULL_TERM;
  }
  solver->full_model = mdl;


  // Constraint
  cnstr = solver->prob->cnstr + i;
  a[0] = cnstr->assumption;                 // B(y)
  a[1] = opposite_term(cnstr->guarantee);   // not C(x, y)


#if EF_VERBOSE
  printf("Constraint:\n");
  yices_pp_term_array(stdout, 2, a, 120, UINT32_MAX, 0, 0);
  printf("(%"PRIu32" literals)\n", 2);
#endif

  // Compute the implicant
  v = &solver->implicant;
  ivector_reset(v);
  code = get_implicant(mdl, solver->prob->manager, LIT_COLLECTOR_ALL_OPTIONS, 2, a, v);
  if (code < 0) {
    solver->status = EF_STATUS_IMPLICANT_ERROR;
    solver->error_code = code;
    return NULL_TERM;
  }

#if EF_VERBOSE
  printf("Implicant:\n");
  yices_pp_term_array(stdout, v->size, v->data, 120, UINT32_MAX, 0, 0);
  printf("(%"PRIu32" literals)\n", v->size);
#endif

  // Projection
  w = &solver->projection;
  ivector_reset(w);
  n = ef_constraint_num_uvars(cnstr);

#if EF_VERBOSE
  printf("(%"PRIu32" universals)\n", n);
  yices_pp_term_array(stdout, n, cnstr->uvars, 120, UINT32_MAX, 0, 0);
#endif

  
  pflag = project_literals(mdl, solver->prob->manager, v->size, v->data, n, cnstr->uvars, w);

  if (pflag != PROJ_NO_ERROR) {
    solver->status = EF_STATUS_PROJECTION_ERROR;
    solver->error_code = pflag;
    return NULL_TERM;
  }

#if EF_VERBOSE
  printf("Projection:\n");
  yices_pp_term_array(stdout, w->size, w->data, 120, UINT32_MAX, 0, 0);
  printf("(%"PRIu32" literals)\n", w->size);
#endif

  switch (w->size) {
  case 0:
    result = true_term;
    break;

  case 1:
    result = w->data[0];
    break;

  default:
    result = mk_and(solver->prob->manager, w->size, w->data);
    break;
  }

  return opposite_term(result);
}