/* * Collect all terms that satisfy predicate f * - add them to vector v * - if f(aux, t) returns true, add t to vector v * - if all is false, only the terms in model->map are considered * - if all is true, the terms in model->map and model->alias are considered * - f must not have side effects * * - v is not reset. All terms collected are added to v */ void model_collect_terms(model_t *model, bool all, void *aux, model_filter_t f, ivector_t *v) { int_hmap_t *hmap; int_hmap_pair_t *r; hmap = &model->map; r = int_hmap_first_record(hmap); while (r != NULL) { if (f(aux, r->key)) { ivector_push(v, r->key); } r = int_hmap_next_record(hmap, r); } hmap = model->alias_map; if (all && hmap != NULL) { r = int_hmap_first_record(hmap); while (r != NULL) { if (f(aux, r->key)) { ivector_push(v, r->key); } r = int_hmap_next_record(hmap, r); } } }
clause_ref_t clause_db_new_clause(clause_db_t* db, const mcsat_literal_t* literals, uint32_t size, mcsat_clause_tag_t tag) { mcsat_tagged_clause_t* clause_memory; uint32_t clause_size; clause_ref_t clause_ref; assert(tag.type == CLAUSE_LEMMA || tag.var != variable_null); // Allocate the clause (size + 1) for null-termination clause_size = clause_size_in_bytes(size); clause_memory = allocate(&clause_size, &db->memory, &db->size, &db->capacity); // Construct the clause and tag it clause_construct(&clause_memory->clause, literals, size); clause_memory->tag = tag; // Compute the clause reference clause_ref = clause_get_ref(db, clause_memory); // Remember the clause assert(clause_db_is_clause(db, clause_ref, true)); ivector_push(&db->clauses, clause_ref); // Return the reference return clause_ref; }
/* * Undo assert_var/keep record poly * - stop on the top-most 'INCREASE_DLEVEL' */ static void op_stack_backtrack(test_bench_t *bench) { op_stack_t *stack; ivector_t saved_polys; uint32_t i; int32_t id; stack = &bench->stack; init_ivector(&saved_polys, 10); i = stack->top; for (;;) { assert(i > 0); i --; switch (stack->data[i].tag) { case RECORD_POLY: id = stack->data[i].arg.rec_id; ivector_push(&saved_polys, id); break; case ASSERT_EQ: // undo case PROPAGATE: // undo break; case INCREASE_DLEVEL: goto done; case PUSH: default: assert(false); break; } } done: stack->top = i; if (bench->conflict) { // check whether the conflict equality has been removed assert(bench->conflict_eq >= 0); if (i <= bench->conflict_eq) { bench->conflict_eq = -1; bench->conflict = false; bench->mngr_conflict = false; printf("---> Conflict resolved\n"); fflush(stdout); } } // redo the record poly operations i = saved_polys.size; while (i > 0) { i --; id = saved_polys.data[i]; push_record_poly(stack, id); } delete_ivector(&saved_polys); }
/* * Add all indices in the domain of map to vector v * - the default index (null_particle) is not added if it's present in map */ void collect_map_indices(map_t *map, ivector_t *v) { uint32_t i, n; n = map->nelems; for (i=0; i<n; i++) { ivector_push(v, map->data[i].index); } }
/* * Add term t to the store: * - t is added as last element of store->terms[i] where i = index for type of t */ static void type_store_add_term(type_store_t *store, term_t t) { uint32_t i; type_t tau; assert(good_term(__yices_globals.terms, t)); tau = term_type(__yices_globals.terms, t); i = type_store_get_type(store, tau); ivector_push(store->terms + i, t); }
/* * Collect all children of i in vector v * - i must be the start of a valie expression * - v must be initialized and empty (if not empty, the children * are added to v). */ void collect_subexpr(etk_queue_t *queue, int32_t i, ivector_t *v) { int32_t k, n; assert(start_token(queue, i)); if (queue->tk[i].key == ETK_OPEN) { n = queue->tk[i].val; k = i+1; while (k < n) { assert(good_token(queue, k)); ivector_push(v, k); k = token_sibling(queue, k); } assert(k == n); } }
/* * Extract the common part of p and q: * - p and q must both be normalized * - the set of variables x_1, ..., x_k such that * x_i occurs with the same coefficient in p and q is added to vector v. * - these variables are in increasing order */ void monarray_pair_common_part(monomial_t *p, monomial_t *q, ivector_t *v) { int32_t x, y; x = p->var; y = q->var; while (x < max_idx && y < max_idx) { if (x < y) { p ++; x = p->var; } else if (y < x) { q ++; y = q->var; } else { if (q_eq(&p->coeff, &q->coeff)) { ivector_push(v, x); } p ++; x = p->var; q ++; y = q->var; } } }
/* * Flatten all terms in flat->queue to conjuncts * - all terms in the queue must also be in the cache * - f_ite: if true, flatten (ite c a b) * - f_iff: if true, flatten (iff a b) */ static void flattener_build_conjuncts(flattener_t *flat, bool f_ite, bool f_iff) { term_table_t *terms; int_queue_t *queue; composite_term_t *d; term_t t, u, v; uint32_t i, n; queue = &flat->queue; terms = flat->terms; while (! int_queue_is_empty(queue)) { t = int_queue_pop(queue); switch (term_kind(terms, t)) { case ITE_TERM: case ITE_SPECIAL: d = ite_term_desc(terms, t); assert(d->arity == 3); if (f_ite && is_boolean_term(terms, d->arg[1])) { assert(is_boolean_term(terms, d->arg[2])); /* * If t is (ite C A B) * u := (C => A) * v := (not C => B) * Otherwise, t is (not (ite C A B)) * u := (C => not A) * v := (not C => not B) */ u = d->arg[1]; // A v = d->arg[2]; // B if (is_neg_term(t)) { u = opposite_term(u); v = opposite_term(v); } u = mk_implies(flat->manager, d->arg[0], u); // (C => u) v = mk_implies(flat->manager, opposite_term(d->arg[0]), v); // (not C) => v flattener_push_term(flat, u); flattener_push_term(flat, v); continue; } break; case EQ_TERM: d = eq_term_desc(terms, t); assert(d->arity == 2); if (f_iff && is_boolean_term(terms, d->arg[0])) { assert(is_boolean_term(terms, d->arg[1])); /* * t is either (iff A B) or (not (iff A B)): */ u = d->arg[0]; // A v = d->arg[1]; // B if (is_neg_term(t)) { u = opposite_term(u); } // flatten to (u => v) and (v => u) t = mk_implies(flat->manager, u, v); // (u => v) u = mk_implies(flat->manager, v, u); // (v => u); flattener_push_term(flat, t); flattener_push_term(flat, u); continue; } break; case OR_TERM: if (is_neg_term(t)) { /* * t is (not (or a[0] ... a[n-1])) * it flattens to (and (not a[0]) ... (not a[n-1])) */ d = or_term_desc(terms, t); n = d->arity; for (i=0; i<n; i++) { flattener_push_term(flat, opposite_term(d->arg[i])); } continue; } break; default: break; } ivector_push(&flat->resu, t); } // clean up the cache assert(int_queue_is_empty(queue)); int_hset_reset(&flat->cache); }
/* * Process disjuncts and universal quantifiers * - input = all terms in the queue * - f_ite: if true, flatten (ite c a b) * - f_iff: if true, flatten (iff a b) */ static void flattener_forall_disjuncts(flattener_t *flat, bool f_ite, bool f_iff) { term_table_t *terms; int_queue_t *queue; composite_term_t *d; term_t t, u, v; uint32_t i, n; queue = &flat->queue; terms = flat->terms; while (! int_queue_is_empty(queue)) { t = int_queue_pop(queue); switch (term_kind(terms, t)) { case ITE_TERM: case ITE_SPECIAL: d = ite_term_desc(terms, t); assert(d->arity == 3); if (f_ite && is_boolean_term(terms, d->arg[1])) { assert(is_boolean_term(terms, d->arg[2])); /* * If t is (ite C A B) * u := (C AND A) * v := (not C AND B) * Otherwise, t is (not (ite C A B)) * u := (C AND not A) * v := (not C AND not B) */ u = d->arg[1]; // A v = d->arg[2]; // B if (is_neg_term(t)) { u = opposite_term(u); // NOT A v = opposite_term(v); // NOT B } u = mk_binary_and(flat->manager, d->arg[0], u); // (C AND u) v = mk_binary_and(flat->manager, opposite_term(d->arg[0]), v); // (not C) AND v flattener_push_term(flat, u); flattener_push_term(flat, v); continue; } break; case EQ_TERM: d = eq_term_desc(terms, t); assert(d->arity == 2); if (f_iff && is_boolean_term(terms, d->arg[0])) { assert(is_boolean_term(terms, d->arg[1])); /* * t is either (iff A B) or (not (iff A B)): */ u = d->arg[0]; // A v = d->arg[1]; // B if (is_neg_term(t)) { u = opposite_term(u); } // flatten to (u AND v) or ((not u) AND (not v)) t = mk_binary_and(flat->manager, u, v); // (u AND v) u = mk_binary_and(flat->manager, opposite_term(u), opposite_term(v)); // (not u AND not v); flattener_push_term(flat, t); flattener_push_term(flat, u); continue; } break; case OR_TERM: if (is_pos_term(t)) { /* * t is (or a[0] ... a[n-1]) */ d = or_term_desc(terms, t); n = d->arity; for (i=0; i<n; i++) { flattener_push_term(flat, d->arg[i]); } continue; } break; case FORALL_TERM: if (is_pos_term(t)) { d = forall_term_desc(terms, t); n = d->arity; assert(n >= 2); /* * t is (FORALL x_0 ... x_k : body) * body is the last argument in the term descriptor */ flattener_push_term(flat, d->arg[n-1]); continue; } break; default: break; } ivector_push(&flat->resu, t); } // clean up the cache assert(int_queue_is_empty(queue)); int_hset_reset(&flat->cache); }
static int build_instance(char *filename, smt_core_t *core) { int l, n, c_idx, literal, nvars, nclauses; char *s; FILE *f; ivector_t buffer; f = fopen(filename, "r"); if (f == NULL) { perror(filename); return OPEN_ERROR; } s = fgets(line, MAX_LINE, f); l = 1; /* line number */ if (s == NULL) { fprintf(stderr, "%s: empty file\n", filename); fclose(f); return FORMAT_ERROR; } /* skip empty and comment lines */ while (*s == 'c' || *s == '\n') { s = fgets(line, MAX_LINE, f); l ++; if (s == NULL) { fprintf(stderr, "Format error: file %s, line %d\n", filename, l); fclose(f); return FORMAT_ERROR; } } /* read problem size */ n = sscanf(s, "p cnf %d %d", &nvars, &nclauses); if (n != 2 || nvars < 0 || nclauses < 0) { fprintf(stderr, "Format error: file %s, line %d\n", filename, l); fclose(f); return FORMAT_ERROR; } /* initialize core for nvars */ init_sat_solver(core, nvars); /* initialize the clause buffer */ init_ivector(&buffer, 10); /* now read the clauses and translate them */ c_idx = 0; while (c_idx < nclauses) { for (;;) { literal = read_literal(f, nvars); if (literal < 0) break; ivector_push(&buffer, literal); } if (literal != END_OF_CLAUSE) { fprintf(stderr, "Format error: file %s\n", filename); fclose(f); return FORMAT_ERROR; } add_clause(core, buffer.size, buffer.data); c_idx ++; ivector_reset(&buffer); } delete_ivector(&buffer); fclose(f); return 0; }
/* * Check whether f is a range constraint * - if so return a term t and fill in vector v with the formula's constants * - otherwise, return NULL_TERM * * Side effect: use queue and cache. * v may be modified even if the function returns NULL_TERM. */ static term_t formula_is_range_constraint(sym_breaker_t *breaker, term_t f, ivector_t *v) { int_queue_t *queue; int_hset_t *cache; term_table_t *terms; intern_tbl_t *intern; term_t r, t; term_t x, a, y, b; uint32_t neqs; queue = &breaker->queue; cache = &breaker->cache; terms = breaker->terms; intern = &breaker->ctx->intern; assert(int_queue_is_empty(queue) && int_hset_is_empty(cache)); push_term(queue, cache, f); neqs = 0; t = NULL_TERM; y = NULL_TERM; // prevent GCC warning b = NULL_TERM; // prevent GCC warning /* * Invariants: * - neqs = number of equality atoms seen so far * - if neq == 1, then the first equality is stored as (y == b) where b is a constant * - if neq >= 2, then all equalities seen so far were of the form (x == constant) */ do { // r := root of the first term in the queue r = intern_tbl_get_root(intern, int_queue_pop(queue)); switch (match_term(breaker->ctx, r, &a, &x)) { case MATCH_FALSE: // skip false terms break; case MATCH_OR: push_children(queue, cache, or_term_desc(terms, r)); break; case MATCH_EQ: assert(term_is_constant(terms, a)); if (neqs == 0) { y = x; b = a; } else if (neqs == 1) { /* * First equality: (y == b). Second equality: (x == a) */ if (y == x) { // y is the common term, a and b are constant ivector_push(v, b); ivector_push(v, a); } else if (y == a && term_is_uconst(terms, x)) { // y is the common term, b and x are constant ivector_push(v, b); ivector_push(v, a); } else if (x == b && term_is_uconst(terms, y)) { // b is the common term, y and a are constant ivector_push(v, y); ivector_push(v, a); y = b; } else if (a == b && term_is_uconst(terms, y) && term_is_uconst(terms, x)) { // b is the common term, y and x are constant ivector_push(v, y); ivector_push(v, x); y = b; } else { // abort goto done; } } else { /* * All equalities so far have the form (y == constant) * - the current equality is (x == a) */ if (y == x) { ivector_push(v, a); // match } else if (y == a && term_is_constant(terms, x)) { ivector_push(v, x); // swap a and x } else { // no match goto done; } } neqs ++; break; case MATCH_IFF: /* * the returned term x is equivalent to t */ push_term(queue, cache, x); break; default: // abort goto done; } } while (! int_queue_is_empty(queue)); assert(y != NULL_TERM && t == NULL_TERM); if (neqs >= 2) { assert(v->size == neqs); t = y; } done: int_queue_reset(queue); int_hset_reset(cache); return t; }