Skip to content

Commit 6519b6e

Browse files
Refactor compute_inverse_function
We replace this function by a `solve` function which manipulate a linear_functiont. This makes the interface and the code clearer.
1 parent 604f23c commit 6519b6e

File tree

2 files changed

+24
-42
lines changed

2 files changed

+24
-42
lines changed

src/solvers/strings/string_constraint_instantiation.cpp

Lines changed: 18 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -136,48 +136,24 @@ exprt linear_functiont::to_expr(bool negated) const
136136
return sum.is_nil() ? from_integer(0, type) : sum;
137137
}
138138

139-
/// \param qvar: a symbol representing a universally quantified variable
140-
/// \param val: an expression
141-
/// \param f: an expression containing `+` and `-`
142-
/// operations in which `qvar` should appear exactly once.
143-
/// \return an expression corresponding of $f^{-1}(val)$ where $f$ is seen as
144-
/// a function of $qvar$, i.e. the value that is necessary for `qvar` for `f`
145-
/// to be equal to `val`. For instance, if `f` corresponds to the expression
146-
/// $q + x$, `compute_inverse_function(q,v,f)` returns an expression
147-
/// for $v - x$.
148-
static exprt
149-
compute_inverse_function(const exprt &qvar, const exprt &val, const exprt &f)
139+
exprt linear_functiont::solve(
140+
linear_functiont f,
141+
const exprt &var,
142+
const exprt &val)
150143
{
151-
exprt positive, negative;
152-
// number of times the element should be added (can be negative)
153-
// qvar has to be equal to val - f(0) if it appears positively in f
154-
// (i.e. if f(qvar)=f(0) + qvar) and f(0) - val if it appears negatively
155-
// in f. So we start by computing val - f(0).
156-
linear_functiont linear_function{minus_exprt(val, f)};
157-
158-
// true if qvar appears negatively in f (positively in linear_function):
159-
bool neg = false;
160-
161-
auto it = linear_function.coefficients.find(qvar);
162-
INVARIANT(
163-
it != linear_function.coefficients.end(),
164-
string_refinement_invariantt("a function must have an occurrence of qvar"));
165-
if(it->second == 1 || it->second == -1)
166-
{
167-
neg = (it->second == 1);
168-
}
169-
else
170-
{
171-
INVARIANT(
172-
it->second == 0,
173-
string_refinement_invariantt(
174-
"a proper function must have exactly one "
175-
"occurrence after reduction, or it cancelled out, and it does not"
176-
" have one"));
177-
}
178-
179-
linear_function.coefficients.erase(it);
180-
return linear_function.to_expr(neg);
144+
auto it = f.coefficients.find(var);
145+
PRECONDITION(it != f.coefficients.end());
146+
PRECONDITION(it->second == 1 || it->second == -1);
147+
const bool positive = it->second == 1;
148+
149+
// Transform `f` into `f(var <- 0)`
150+
f.coefficients.erase(it);
151+
// Transform `f(var <- 0)` into `f(var <- 0) - val`
152+
f.add(linear_functiont{unary_minus_exprt{val}});
153+
154+
// If the coefficient of var is 1 then solution `val - f(var <- 0),
155+
// otherwise `f(var <- 0) - val`
156+
return f.to_expr(positive);
181157
}
182158

183159
/// Instantiates a string constraint by substituting the quantifiers.
@@ -204,7 +180,7 @@ exprt instantiate(
204180
for(const auto &index : find_indexes(axiom.body, str, axiom.univ_var))
205181
{
206182
const exprt univ_var_value =
207-
compute_inverse_function(axiom.univ_var, val, index);
183+
linear_functiont::solve(linear_functiont{index}, axiom.univ_var, val);
208184
implies_exprt instance(
209185
and_exprt(
210186
binary_relation_exprt(axiom.univ_var, ID_ge, axiom.lower_bound),

src/solvers/strings/string_constraint_instantiation.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ struct linear_functiont
5454
/// \param negated: optional Boolean asking to negate the function
5555
/// \return an expression corresponding to the linear function
5656
exprt to_expr(bool negated = false) const;
57+
58+
/// Return an expression `y` such that `f(var <- y) = val`.
59+
/// The coefficient of \p var in the linear function must be 1 or -1.
60+
/// For instance, if `f` corresponds to the expression `q + x`, `solve(q,v,f)`
61+
/// returns the expression `v - x`.
62+
static exprt solve(linear_functiont f, const exprt &var, const exprt &val);
5763
};
5864

5965
#endif // CPROVER_SOLVERS_REFINEMENT_STRING_CONSTRAINT_INSTANTIATION_H

0 commit comments

Comments
 (0)