/// searchForAssignment - Look for a cached solution for a query. /// /// \param key - The query to look up. /// \param result [out] - The cached result, if the lookup is succesful. This is /// either a satisfying assignment (for a satisfiable query), or 0 (for an /// unsatisfiable query). /// \return - True if a cached result was found. bool CexCachingSolver::searchForAssignment(KeyType &key, Assignment *&result) { Assignment * const *lookup = cache.lookup(key); if (lookup) { result = *lookup; return true; } if (CexCacheTryAll) { // Look for a satisfying assignment for a superset, which is trivially an // assignment for any subset. Assignment **lookup = cache.findSuperset(key, NonNullAssignment()); // Otherwise, look for a subset which is unsatisfiable, see below. if (!lookup) lookup = cache.findSubset(key, NullAssignment()); // If either lookup succeeded, then we have a cached solution. if (lookup) { result = *lookup; return true; } // Otherwise, iterate through the set of current assignments to see if one // of them satisfies the query. for (assignmentsTable_ty::iterator it = assignmentsTable.begin(), ie = assignmentsTable.end(); it != ie; ++it) { Assignment *a = *it; if (a->satisfies(key.begin(), key.end())) { result = a; return true; } } } else { // FIXME: Which order? one is sure to be better. // Look for a satisfying assignment for a superset, which is trivially an // assignment for any subset. Assignment **lookup = cache.findSuperset(key, NonNullAssignment()); // Otherwise, look for a subset which is unsatisfiable -- if the subset is // unsatisfiable then no additional constraints can produce a valid // assignment. While searching subsets, we also explicitly the solutions for // satisfiable subsets to see if they solve the current query and return // them if so. This is cheap and frequently succeeds. if (!lookup) lookup = cache.findSubset(key, NullOrSatisfyingAssignment(key)); // If either lookup succeeded, then we have a cached solution. if (lookup) { result = *lookup; return true; } } return false; }
bool CexCachingSolver::getAssignment(const Query& query, Assignment *&result) { KeyType key; if (lookupAssignment(query, key, result)) return true; std::vector<const Array*> objects; findSymbolicObjects(key.begin(), key.end(), objects); std::vector< std::vector<unsigned char> > values; bool hasSolution; if (!solver->impl->computeInitialValues(query, objects, values, hasSolution)) return false; AssignmentCacheWrapper *bindingWrapper; Assignment *binding; if (hasSolution) { binding = new Assignment(objects, values); // Memoize the result. std::pair<assignmentsTable_ty::iterator, bool> res = assignmentsTable.insert(binding); if (!res.second) { delete binding; binding = *res.first; } if (DebugCexCacheCheckBinding) if (!binding->satisfies(key.begin(), key.end())) { query.dump(); binding->dump(); klee_error("Generated assignment doesn't match query"); } bindingWrapper = new AssignmentCacheWrapper(binding); } else { unsatCore = solver->impl->getUnsatCore(); binding = (Assignment *) 0; bindingWrapper = new AssignmentCacheWrapper(unsatCore); } result = binding; cache.insert(key, bindingWrapper); return true; }
bool CexCachingSolver::getAssignment(const Query& query, Assignment *&result) { KeyType key; if (lookupAssignment(query, key, result)) return true; std::vector<const Array*> objects; findSymbolicObjects(key.begin(), key.end(), objects); std::vector< std::vector<unsigned char> > values; bool hasSolution; if (!solver->impl->computeInitialValues(query, objects, values, hasSolution)) return false; Assignment *binding; if (hasSolution) { binding = new Assignment(objects, values); // Memoize the result. std::pair<assignmentsTable_ty::iterator, bool> res = assignmentsTable.insert(binding); if (!res.second) { delete binding; binding = *res.first; } if (DebugCexCacheCheckBinding) assert(binding->satisfies(key.begin(), key.end())); } else { binding = (Assignment*) 0; } result = binding; cache.insert(key, binding); return true; }