Skip to content

Commit fb676d5

Browse files
Add a cache for eval in string dependences
This improves the performances since the model for one string can depend on the model for two other strings, which model may have already been computed. The cache must be cleared every time the model changes.
1 parent 095d57b commit fb676d5

File tree

3 files changed

+32
-4
lines changed

3 files changed

+32
-4
lines changed

src/solvers/refinement/string_refinement.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,7 @@ decision_proceduret::resultt string_refinementt::dec_solve()
757757

758758
// Initial try without index set
759759
const auto get = [this](const exprt &expr) { return this->get(expr); };
760+
dependencies.clean_cache();
760761
const decision_proceduret::resultt res=supert::dec_solve();
761762
if(res==resultt::D_SATISFIABLE)
762763
{
@@ -804,6 +805,7 @@ decision_proceduret::resultt string_refinementt::dec_solve()
804805

805806
while((loop_bound_--)>0)
806807
{
808+
dependencies.clean_cache();
807809
const decision_proceduret::resultt res=supert::dec_solve();
808810

809811
if(res==resultt::D_SATISFIABLE)

src/solvers/refinement/string_refinement_util.cpp

+23-4
Original file line numberDiff line numberDiff line change
@@ -537,17 +537,36 @@ optionalt<exprt> string_dependenciest::eval(
537537
const array_string_exprt &s,
538538
const std::function<exprt(const exprt &)> &get_value) const
539539
{
540-
const auto node = node_at(s);
541-
if(node && node->dependencies.size() == 1)
540+
const auto &it = node_index_pool.find(s);
541+
if(it == node_index_pool.end())
542+
return {};
543+
544+
if(eval_string_cache[it->second])
545+
return eval_string_cache[it->second];
546+
547+
const auto node = string_nodes[it->second];
548+
549+
if(node.dependencies.size() == 1)
542550
{
543-
const auto &f = get_builtin_function(node->dependencies[0]);
551+
const auto &f = get_builtin_function(node.dependencies[0]);
544552
const auto result = f.string_result();
545553
if(result && *result == s)
546-
return f.eval(get_value);
554+
{
555+
const auto value_opt = f.eval(get_value);
556+
eval_string_cache[it->second] = value_opt;
557+
return value_opt;
558+
}
547559
}
548560
return {};
549561
}
550562

563+
void string_dependenciest::clean_cache()
564+
{
565+
eval_string_cache.resize(string_nodes.size());
566+
for(auto &e : eval_string_cache)
567+
e.reset();
568+
}
569+
551570
bool add_node(
552571
string_dependenciest &dependencies,
553572
const equal_exprt &equation,

src/solvers/refinement/string_refinement_util.h

+7
Original file line numberDiff line numberDiff line change
@@ -339,10 +339,15 @@ class string_dependenciest
339339

340340
/// Attempt to evaluate the given string from the dependencies and valuation
341341
/// of strings on which it depends
342+
/// Warning: eval uses a cache which must be cleaned everytime the valuations
343+
/// given by get_value can change.
342344
optionalt<exprt> eval(
343345
const array_string_exprt &s,
344346
const std::function<exprt(const exprt &)> &get_value) const;
345347

348+
/// Clean the cache used by `eval`
349+
void clean_cache();
350+
346351
void output_dot(std::ostream &stream) const;
347352

348353
private:
@@ -352,6 +357,8 @@ class string_dependenciest
352357
/// Set of nodes representing strings
353358
std::vector<string_nodet> string_nodes;
354359

360+
mutable std::vector<optionalt<exprt>> eval_string_cache;
361+
355362
/// Nodes describing dependencies of a string: values of the map correspond
356363
/// to indexes in the vector `string_nodes`.
357364
std::unordered_map<array_string_exprt, std::size_t, irep_hash>

0 commit comments

Comments
 (0)