bool sat_path_enumeratort::next(patht &path) { scratch_programt program(symbol_table); program.append(fixed); program.append(fixed); // Let's make sure that we get a path we have not seen before. for(std::list<distinguish_valuest>::iterator it=accelerated_paths.begin(); it!=accelerated_paths.end(); ++it) { exprt new_path=false_exprt(); for(distinguish_valuest::iterator jt=it->begin(); jt!=it->end(); ++jt) { exprt distinguisher=jt->first; bool taken=jt->second; if(taken) { not_exprt negated(distinguisher); distinguisher.swap(negated); } or_exprt disjunct(new_path, distinguisher); new_path.swap(disjunct); } program.assume(new_path); } program.add_instruction(ASSERT)->guard=false_exprt(); try { if(program.check_sat()) { #ifdef DEBUG std::cout << "Found a path" << std::endl; #endif build_path(program, path); record_path(program); return true; } } catch(std::string s) { std::cout << "Error in fitting polynomial SAT check: " << s << std::endl; } catch(const char *s) { std::cout << "Error in fitting polynomial SAT check: " << s << std::endl; } return false; }
void Suggester::kgram(string &w, vector<int>& collect) { vector<vector<int>*> candidates; unsigned sz = w.length(); for (int k = IndexWriter::MIN_N_GRAM; k <= IndexWriter::MAX_N_GRAM; ++k) { for (unsigned n = 0; n < sz - 1; ++n) { string gram = w.substr(n, k); map<string, vector<int> >::iterator it = ir->grams.find(gram); if (it != ir->grams.end()) { candidates.push_back(&(it->second)); } } } if (candidates.empty()) return; vector<pair<int, int> > foo; for (unsigned i = 0; i < candidates.size(); ++i) { vector<pair<int, int> > bar; for (unsigned j = 0; j < candidates[i]->size(); ++j) { bar.push_back(make_pair(1, (*candidates[i])[j])); } disjunct(foo, bar, foo); } for (unsigned i = 0; i < foo.size(); ++i) { pair<int, int> &p = foo[i]; // (sz - 1) means exact match if (p.first >= static_cast<int>(sz) - 4) { collect.push_back(p.second); } } }
TEST(RuleBody, Basic) { RuleBody body; // start with an A auto a = RuleBody::atom(new AstAtom("A")); EXPECT_EQ("A()", toString(a)); a.conjunct(RuleBody::atom(new AstAtom("B"))); EXPECT_EQ("A(),B()", toString(a)); a.disjunct(RuleBody::atom(new AstAtom("C"))); EXPECT_EQ("A(),B();C()", toString(a)); }
bool disjunctive_polynomial_accelerationt::fit_polynomial( exprt &var, polynomialt &polynomial, patht &path) { // These are the variables that var depends on with respect to the body. std::vector<expr_listt> parameters; std::set<std::pair<expr_listt, exprt> > coefficients; expr_listt exprs; scratch_programt program(symbol_table); expr_sett influence; cone_of_influence(var, influence); #ifdef DEBUG std::cout << "Fitting a polynomial for " << expr2c(var, ns) << ", which depends on:" << std::endl; for (expr_sett::iterator it = influence.begin(); it != influence.end(); ++it) { std::cout << expr2c(*it, ns) << std::endl; } #endif for (expr_sett::iterator it = influence.begin(); it != influence.end(); ++it) { if (it->id() == ID_index || it->id() == ID_dereference) { // Hack: don't accelerate anything that depends on an array // yet... return false; } exprs.clear(); exprs.push_back(*it); parameters.push_back(exprs); exprs.push_back(loop_counter); parameters.push_back(exprs); } // N exprs.clear(); exprs.push_back(loop_counter); parameters.push_back(exprs); // N^2 exprs.push_back(loop_counter); parameters.push_back(exprs); // Constant exprs.clear(); parameters.push_back(exprs); for (std::vector<expr_listt>::iterator it = parameters.begin(); it != parameters.end(); ++it) { symbolt coeff = utils.fresh_symbol("polynomial::coeff", signed_poly_type()); coefficients.insert(make_pair(*it, coeff.symbol_expr())); // XXX HACK HACK HACK // I'm just constraining these coefficients to prevent overflows messing things // up later... Should really do this properly somehow. program.assume(binary_relation_exprt(from_integer(-(1 << 10), signed_poly_type()), "<", coeff.symbol_expr())); program.assume(binary_relation_exprt(coeff.symbol_expr(), "<", from_integer(1 << 10, signed_poly_type()))); } // Build a set of values for all the parameters that allow us to fit a // unique polynomial. std::map<exprt, exprt> ivals1; std::map<exprt, exprt> ivals2; std::map<exprt, exprt> ivals3; for (expr_sett::iterator it = influence.begin(); it != influence.end(); ++it) { symbolt ival1 = utils.fresh_symbol("polynomial::init", it->type()); symbolt ival2 = utils.fresh_symbol("polynomial::init", it->type()); symbolt ival3 = utils.fresh_symbol("polynomial::init", it->type()); program.assume(binary_relation_exprt(ival1.symbol_expr(), "<", ival2.symbol_expr())); program.assume(binary_relation_exprt(ival2.symbol_expr(), "<", ival3.symbol_expr())); #if 0 if (it->type() == signedbv_typet()) { program.assume(binary_relation_exprt(ival1.symbol_expr(), ">", from_integer(-100, it->type()))); } program.assume(binary_relation_exprt(ival1.symbol_expr(), "<", from_integer(100, it->type()))); if (it->type() == signedbv_typet()) { program.assume(binary_relation_exprt(ival2.symbol_expr(), ">", from_integer(-100, it->type()))); } program.assume(binary_relation_exprt(ival2.symbol_expr(), "<", from_integer(100, it->type()))); if (it->type() == signedbv_typet()) { program.assume(binary_relation_exprt(ival3.symbol_expr(), ">", from_integer(-100, it->type()))); } program.assume(binary_relation_exprt(ival3.symbol_expr(), "<", from_integer(100, it->type()))); #endif ivals1[*it] = ival1.symbol_expr(); ivals2[*it] = ival2.symbol_expr(); ivals3[*it] = ival3.symbol_expr(); //ivals1[*it] = from_integer(1, it->type()); } std::map<exprt, exprt> values; for (expr_sett::iterator it = influence.begin(); it != influence.end(); ++it) { values[*it] = ivals1[*it]; } // Start building the program. Begin by decl'ing each of the // master distinguishers. for (std::list<exprt>::iterator it = distinguishers.begin(); it != distinguishers.end(); ++it) { program.add_instruction(DECL)->code = code_declt(*it); } // Now assume our polynomial fits at each of our sample points. assert_for_values(program, values, coefficients, 1, fixed, var); for (int n = 0; n <= 1; n++) { for (expr_sett::iterator it = influence.begin(); it != influence.end(); ++it) { values[*it] = ivals2[*it]; assert_for_values(program, values, coefficients, n, fixed, var); values[*it] = ivals3[*it]; assert_for_values(program, values, coefficients, n, fixed, var); values[*it] = ivals1[*it]; } } for (expr_sett::iterator it = influence.begin(); it != influence.end(); ++it) { values[*it] = ivals3[*it]; } assert_for_values(program, values, coefficients, 0, fixed, var); assert_for_values(program, values, coefficients, 1, fixed, var); assert_for_values(program, values, coefficients, 2, fixed, var); // Let's make sure that we get a path we have not seen before. for (std::list<distinguish_valuest>::iterator it = accelerated_paths.begin(); it != accelerated_paths.end(); ++it) { exprt new_path = false_exprt(); for (distinguish_valuest::iterator jt = it->begin(); jt != it->end(); ++jt) { exprt distinguisher = jt->first; bool taken = jt->second; if (taken) { not_exprt negated(distinguisher); distinguisher.swap(negated); } or_exprt disjunct(new_path, distinguisher); new_path.swap(disjunct); } program.assume(new_path); } utils.ensure_no_overflows(program); // Now do an ASSERT(false) to grab a counterexample program.add_instruction(ASSERT)->guard = false_exprt(); // If the path is satisfiable, we've fitted a polynomial. Extract the // relevant coefficients and return the expression. try { if (program.check_sat()) { #ifdef DEBUG std::cout << "Found a polynomial" << std::endl; #endif utils.extract_polynomial(program, coefficients, polynomial); build_path(program, path); record_path(program); return true; } } catch (std::string s) { std::cout << "Error in fitting polynomial SAT check: " << s << std::endl; } catch (const char *s) { std::cout << "Error in fitting polynomial SAT check: " << s << std::endl; } return false; }
static void replaceAssertVertex(NGWrapper &g, NFAVertex t, edge_cache_t &edge_cache, u32 &assert_edge_count) { DEBUG_PRINTF("replacing assert vertex %u\n", g[t].index); const u32 flags = g[t].assert_flags; DEBUG_PRINTF("consider assert vertex %u with flags %u\n", g[t].index, flags); // Wire up all the predecessors to all the successors. for (const auto &inEdge : in_edges_range(t, g)) { NFAVertex u = source(inEdge, g); if (u == t) { continue; // ignore self-loops } const u32 flags_inc_in = conjunct(g[inEdge].assert_flags, flags); if (flags_inc_in == DEAD_EDGE) { DEBUG_PRINTF("fail, in-edge has bad flags %d\n", g[inEdge].assert_flags); continue; } for (const auto &outEdge : out_edges_range(t, g)) { NFAVertex v = target(outEdge, g); DEBUG_PRINTF("consider path [%u,%u,%u]\n", g[u].index, g[t].index, g[v].index); if (v == t) { continue; // ignore self-loops } const u32 flags_final = conjunct(g[outEdge].assert_flags, flags_inc_in); if (flags_final == DEAD_EDGE) { DEBUG_PRINTF("fail, out-edge has bad flags %d\n", g[outEdge].assert_flags); continue; } if ((g[u].assert_flags & POS_FLAG_MULTILINE_START) && v == g.acceptEod) { DEBUG_PRINTF("fail, (?m)^ does not match \\n at eod\n"); continue; } /* Replace path (u,t,v) with direct edge (u,v), unless the edge * already exists, in which case we just need to edit its * properties. * * Use edge_cache to prevent us going O(N). */ auto cache_key = make_pair(u, v); auto ecit = edge_cache.find(cache_key); if (ecit == edge_cache.end()) { DEBUG_PRINTF("adding edge %u %u\n", g[u].index, g[v].index); NFAEdge e = add_edge(u, v, g).first; edge_cache.emplace(cache_key, e); g[e].assert_flags = flags; if (++assert_edge_count > MAX_ASSERT_EDGES) { throw CompileError(g.expressionIndex, "Pattern is too large."); } } else { NFAEdge e = ecit->second; DEBUG_PRINTF("updating edge %u %u [a %u]\n", g[u].index, g[v].index, g[t].index); // Edge already exists. u32 &e_flags = g[e].assert_flags; e_flags = disjunct(e_flags, flags_final); assert(e_flags != DEAD_EDGE); } } } // Clear vertex t to remove all the old edges. /* no need to clear the cache, as we will never look up its edge as it is * unreachable */ clear_vertex(t, g); }