1 Introduction

Proving quantitative properties of programs often leads to verification conditions that involve cardinalities of sets and relations over program states. For example, determining the memory requirements for memoization reduces to bounding the cardinality of the set of argument values passed to a function, and bounding information leaks of a program reduces to bounding the cardinality of the set of observations an attacker can make.

A number of recent advances for discharging verification conditions with cardinalities consider extensions of logical theories with cardinality constraints, such as set algebra and its generalizations [25, 31, 32], linear arithmetic [15, 40], constraints over strings [27], as well as general SMT based settings [17]. At their core, these approaches operate by checking whether a cardinality bound holds for a given formula that describes a set of values. However, they cannot synthesize formulas that satisfy given cardinality constraints. As a consequence, the problem of automatically inferring cardinality-based inductive arguments that imply a specified assertion remains an open challenge.

In this paper, we present an approach for synthesizing linear arithmetic formulas that satisfy given cardinality constraints. Our approach relies on the theory of counting integer points in polytopes, however, instead of computing the cardinality of a given polytope (the typical use case of this theory) our approach synthesizes a polytope for a given cardinality constraint. Our synthesizer internally organizes the search space in terms of symbolic polytopes. Such polytopes are represented using symbolic vertices and hyperplanes, together with certain well-formedness constraints. We derive an expression for the number of points in the polytope in terms of this symbolic representation, which leads to a set of constraints that at the same time represent the shape and the cardinality of the polytope. For this, we restrict our attention to the class of unimodular polytopes. Unimodularity can be concisely described using constraints and provides an effective means for reducing the search space while being sufficiently expressive. We then resort to efficient SMT solvers specifically tuned to deal with the resulting kind of non-linear constraints, e.g., Z3 [16]. We cast our approach in terms of an algorithm \(\#\textsc {Itp}_\textsc {LIA} \) for cardinality constrained interpolation, that is, \(\#\textsc {Itp}_\textsc {LIA} \) generates formulas that satisfy cardinality constraints along with implication constraints.

We put cardinality-constrained interpolation to work within an automatic verification method \(\#\textsc {Horn} \) for inferring cardinality-based inductive program properties, based on abstraction and its counterexample-guided refinement. Specifically, #Horn is a solver for recursive Horn clauses with cardinality constraints. We rely on Horn clauses as basis because they serve as a language for describing verification conditions for a wide range of programs, including those with procedures and multiple threads [8, 19, 34]. Adding recursion enables representing verification conditions that rely on inductive reasoning, such as loop invariants or procedure summaries. By offering support for cardinalities directly in the language in which we express verification conditions, our solver can effectively leverage the interplay between the qualitative and quantitative (cardinality) aspects of the constraints to be solved.

We implemented \(\#\textsc {Itp}_\textsc {LIA} \) and #Horn and applied them to analyze a collection of examples that show

  • how a variety of cardinality-based properties (namely, bounds on information leaks, memory usage, and execution time) and different program classes (namely, while programs and programs with procedures) can be expressed and analyzed in a uniform manner.

  • that our approach can establish resource bounds on examples from the recent literature at competitive performance and precision, and that it can handle examples whose precise analysis is out of scope of existing approaches.

  • that our approach can be used for synthesizing a padding-based countermeasure against timing side channels, for a given bound on tolerable leakage.

In summary, our paper contributes and puts to work a synthesis method for polytopes that satisfy cardinality constraints, based on symbolic integer point counting algorithms.

2 Example

We consider a procedure mcm for Matrix chain multiplication [14] that recursively computes the cost of multiplying matrices \(M_0, \dots , M_{n}\) with optimal bracketing. mcm (i, j) returns the number of operations required for multiplying the subsequence \(M_i,\dots ,M_j\), and c(k) returns the number of operations required for multiplying matrices \(M_k\) and \(M_{k+1}\).

figure a

Even though the number of recursive function calls is exponential in n, mcm can be turned into an efficient algorithm by applying memoization. The amount of memory required to store results of recursive calls is bounded by \(\frac{(n+1) \cdot (n+2)}{2}\), as mcm is only called with ordered pairs of arguments.

Proving such a bound requires reasoning about recursive procedure calls as well as tracking dependencies between variables i and j, i.e., estimating the range of each variable in isolation and combining the estimates is not precise enough.

When using #Horn, we first set up recursive Horn constraints on an assertion \( args (i,j,n)\) that contains all triples (ijn) such that calling main(n) leads to a recursive call \(\mathtt{mcm } (i,j)\), following [19]. Then, #Horn solves these constraints using a procedure based on counterexample-guided abstraction refinement. As an intermediate step, #Horn deals with an interpolation query that requires finding a polytope \(\varphi _{ args }\) over ij and n such that

$$\begin{aligned} \begin{array}{@{}ll@{}} n \ge 2 \wedge (i=0 \wedge j=n \vee i=1 \wedge j=1) \rightarrow \varphi _{ args } \qquad &{} \quad (1) \\ n \ge 0 \rightarrow | \{ (i,j) \mid \varphi _{ args } \} | \le \frac{(n+1) \cdot (n+2)}{2} \; . &{} \quad (2) \end{array} \end{aligned}$$

Constraint (1) requires that \(\varphi _{ args }\) contains triples obtained by symbolically executing mcm, a typical interpolation query, while (2) ensures that \(\varphi _{ args }\) satisfies the bound by referring to the cardinality of \(\varphi _{ args }\) through an application of cardinality operator \(| \cdot |\).

Given (1) and (2), \(\#\textsc {Itp}_\textsc {LIA} \) computes the solution \(\varphi _{ args } = (0 \le i \le 1 \mathrel {\wedge } i \le j \le n \mathrel {\wedge } n \ge 2)\). The cardinality of \(\{ (i,j) \mid \varphi _{ args } \}\) is \(2 n+1\), hence \(\varphi _{ args }\) satisfies the above bound. #Horn uses this solution to refine the abstraction function. In particular, it starts using the predicate \(i \le j\), which is crucial for tracking that mcm is only called on ordered pairs.

3 Counting Integer Points in Polytopes

In this section, we first revisit the theory of counting integer points in polytopes. We then discuss the derivation of expressions for the number of integer points in unimodular polytopes with symbolic vertices and hyperplanes.

Preliminaries. Let \(g_1, \dots , g_d \in \mathbb {R}^d\) be vectors in d-dimensional space. A cone with generators \(g_1, \dots , g_d\) is the set of all positive linear combinations of its generators. A cone is unimodular if the absolute value of the determinant of the matrix \((g_1 \;\dots \; g_d)\) is equal to one. The vertex cone of a polytope P at vertex v is the smallest cone that originates from v and that includes P; we denote its generators by \(g _{v1},\dots ,g _{vd}\). Finally, a polytope P is unimodular if all its vertex cones are unimodular.Footnote 1

Generating functions. The integer points contained in a set \(S\subseteq \mathbb {R}^d\) in can be represented in terms of a generating function \( f (S,x)\) which is a sum of monomials, one per integer point in S, defined as follows

$$\begin{aligned} f (S,x)= \sum _{m \in S \cap \mathbb {Z}^d} x^m, \end{aligned}$$
(1)

where for \(m = (m_1, \dots , m_d)\) we define \(x^m = x_1^{m_1} \cdot \ldots \cdot x_d^{m_d}\). This generating function is a Laurent series, i.e. its terms may have negative degree. Note that, for finite S, the value of \( f (S,x)\) at \(x=(1,\dots ,1)\), corresponds to the number of integer points in S.

Rational function representation. Generating functions are a powerful tool for counting integer points in polytopes. This is due to two key results: First, Brion’s theorem [9] allows to decompose the generating function of a polytope into the sum of the generating functions of its vertex cones. Second, the generating function of unimodular vertex cones can be represented through an equivalent yet short rational function. This rational function representation relies on a generalization of the equivalence \(\frac{1}{1-x} =(1+x+x^2+x^3+\dots )\), which provides a concise representation of the set \(\{0,1,2,3,\dots \}\).

This yields the following rational function representation for a unimodular polytope P with vertices \(\mathcal {V}\):

$$\begin{aligned} r (P,x) = \sum _{v \in \mathcal {V}} \frac{x^v}{(1-x^{g _{v1}}) \cdots (1-x^{g _{vd}})} \end{aligned}$$
(2)

Here, each summand represents the generating function of the vertex cone at v with generators \(g _{v1},\dots ,g _{vd}\). Rational function representations for arbitrary polytopes can be obtained through Barvinok’s algorithm [3] that decomposes arbitrary vertex cones into unimodular cones.

Generating function evaluation. Since \(x=(1,\dots ,1)\) is a singularity of \( r (P,x)\), computing the number of points in the polytope by direct evaluation leads to a division by zero. This can be avoided by performing a Laurent series expansion of \( r (P,x)\) around \(x=(1,\dots ,1)\), however, the expansion requires a reduction of \( r (P,x)\) from a multivariate polynomial over \((x_1, \dots , x_d)\) to a univariate polynomial over y, see [15]. The reduction is done by finding a vector \(\mu = (\mu _1, \dots , \mu _d)\) with

$$\begin{aligned} \mu \cdot g \ne 0, \end{aligned}$$
(3)

for all generators g of the polytope, and by replacing \(x_i\) with \(y^{\mu _i}\), for each \(i \in 1\dots d\). Equation (3) ensures that no factor in the denominator of Eq. (2) becomes 0, and hence avoids introduction of singularities. Let \( sub ( r (P,x),y)\) denote the result of the above substitution. Then, the constant term of the Laurent expansion of \( sub ( r (P,x),y)\) around \(y=1\) yields the desired count. Computing Laurent series expansions is a standard procedure and implemented, e.g., in Wolfram Alpha [41].

figure b

Example 1

Consider the unimodular polytope \(P= (x_1 \ge 0 \mathrel {\wedge } x_2 \ge 0 \mathrel {\wedge } x_1+x_2 \le 2)\) of dimension \(d=2\). P has vertices \(v_1 = (0\;0)\), \(v_2 = (0\;2)\), and \(v_3 = (2\;0)\) and contains 6 integer points, as shown by the circles below.

The generators of the vertex cones are given by

$$\begin{aligned} \begin{array}{@{}l@{\qquad }l@{}} g _{v_11} = (0\;1) &{} g _{v_12} = (1\; 0) \\ g _{v_21} = (0\; -1) &{} g _{v_22} = (1\;-1) \\ g _{v_31} = (-1\; 0) &{} g _{v_32} = (-1 \; 1) . \end{array} \end{aligned}$$

Equation (2) yields the following rational generating function \( r (P,x)\).

$$\begin{aligned} \frac{x_1^0 x_2^0}{(1\!-\!x_1^0x_2^1) (1\!-\!x_1^1 x_2^0)} + \frac{x_1^0x_2^2}{ (1\!-\! x_1^0 x_2^{-1}) (1\!-\!x_1^1 x_2^{-1})} + \frac{x_1^2 x_2^0}{ (1\!-\!x_1^{-1} x_2^0) (1\!-\!x_1^{-1} x_2^{1})} \end{aligned}$$

Applying the substitution with \(\mu =(-1\; 1)\) yields the expression \( sub ( r (P,x),y)\).

$$\begin{aligned} \frac{1}{(1-y) (1-y^{-1})} \mathrel {+} \frac{y^2}{ (1-y^{-1}) (1-y^{-2})} \mathrel {+} \frac{y^{-2}}{ (1-y) (1-y^2)} \end{aligned}$$

Computing the series expansion using the Wolfram Alpha command \( series \; sub( r(P,x),y) \; at \; y=1\) produces \(\cdots 5(y-1)^3 + 5(y-1)^2 + 6\), with the constant coefficient 6 yielding the expected count.\(\quad \blacksquare \)

Symbolic cardinality expression. The rational function representation of the generating function of a unimodular polytope shown in Eq. 2 refers to the polytope’s vertices and to the generators of its vertex cones. However, these generators and vertices do not have to be instantiated to concrete values in order for the evaluation of the generating function to be possible [40]. That is, the evaluation of the generating function can be carried out symbolically yielding a formula that expresses the cardinality of a polytope as a function of its generators, vertices, and a vector \(\mu \).

In our algorithm, we will use \(\textsc {SymConeCard}(v, G, \mu )\) to refer to the result of the symbolic evaluation of the generating function for the cone of a symbolic vertex v with generators G. By summing up \(\textsc {SymConeCard}(v, G, \mu )\) for all vertex cones we obtain a symbolic expression of the number of integer points in a symbolic polytope.Footnote 2

Example 2

The cardinality of a two-dimensional polytope with symbolic vertices \(v_1, v_2, v_3\) and generators \(g _{v_i1}\) and \(g _{v_i2}\), with \(i \in 1..3\), is given by \(\sum _{i=1}^3\textsc {SymConeCard}(v_i, \{ g _{v_i1}, g _{v_i2} \}, \mu )\), where

$$\begin{aligned} \begin{array}{@{}l@{}} \textsc {SymConeCard}(v_i, \{ g _{v_i1}, g _{v_i2} \}, \mu ) \\ = \begin{array}{@{}l@{}} (\mu _1^2 + 3 \mu _1 ( \mu _2 - 2 \mu _v -1) + \mu _2^2 \mathrel {-} 3 \mu _2 ( 2 \mu _v + 1) \mathrel {+} 6 \mu _v^2 + 6 \mu _v + 1) (12 \mu _1 \mu _2)^{-1} \\ \text {with } \begin{array}{@{}l@{}} \mu _1 = \mu \cdot g _{v_i1}, \; \mu _2 = \mu \cdot g _{v_i2} \text { and } \mu _v = \mu \cdot v_i. \end{array} \end{array} \end{array} \end{aligned}$$

\(\quad \blacksquare \)

Note that in order for \(\textsc {SymConeCard}(v, G, \mu )\) to yield a valid count, the vertices and generators must satisfy a number of conditions, e.g., the symbolic cones need to be unimodular and the employed vector \(\mu \) needs to satisfy Eq. (3). We next present our interpolation procedure \(\#\textsc {Itp}_\textsc {LIA} \) that creates constraints for ensuring these conditions.

4 Interpolation with Cardinality Constraints

In this section, we first define interpolation with cardinality constraints. Then we present the interpolation procedure \(\#\textsc {Itp}_\textsc {LIA} \) that generates constraints on the cardinality of an interpolant and solves them using an SMT solver.

Cardinality Interpolation. Let k be a variable and let w be a tuple of variables. Let \(\varphi \) and \(\psi \) be constraints in a given first-order theory. Then, a cardinality constraint is an expression of the form

$$\begin{aligned} \begin{array}{@{}ll@{}} | \{ w \mid \varphi \} |=k \wedge \psi \end{array} \end{aligned}$$

where \(| \cdot |\) denotes the set cardinality operator. We call the free variables of \(\varphi \) that do not occur in w parameters. A cardinality constraint is parametric if it has at least one parameter and non-parametric otherwise. The expression \(\psi \) is used to constrain the cardinality.

Fig. 1.
figure 1

Function \(\#\textsc {Itp}_\textsc {LIA} \) computes cardinality constrained interpolants for template \(\textsc {Tmpl}\).

Example 3

Consider the theory of linear integer arithmetic. The cardinality constraint \(| \{ x \mid 0 \le x \le 10 \} | = k \mathrel {\wedge } k \le 20\) is non-parametric, whereas the constraint \(| \{ x \mid 0 \le x \le n \} | =k \mathrel {\wedge } k \le n+1\) is parametric in n. Both constraints are valid, since \(| \{ x \mid 0 \le x \le 10 \} | = 11\) and \(| \{ x \mid 0 \le x \le n \} | = n+1\). \(\quad \blacksquare \)

Assume constraints \(\varphi ^{-}\) and \(\varphi ^{+}\) such that \(\varphi ^{-}\) implies \(\varphi ^{+}\). A cardinality-constrained interpolant for \(\varphi ^{-}\), \(\varphi ^{+}\), and cardinality constraint \(| \{ w \mid \varphi \} |=k \mathrel {\wedge } \psi \) is a constraint \(\varphi \) such that 1) \(\varphi ^{-}\) implies \(\varphi \), 2) \(\varphi \) implies \(\varphi ^{+}\), and 3)  \(| \{ w \mid \varphi \} |=k \mathrel {\wedge } \psi \) is valid. For a parametric cardinality constraint, we say that the interpolation problem is parametric, and call it non-parametric otherwise.

Example 4

Let \(\varphi ^{-}=(x=0 \mathrel {\wedge } n\ge 0)\) and \(\varphi ^{+}=true\). Then \(\varphi =(0 \le x \le n)\) is an interpolant that satisfies the cardinality constraint \(| \{ x \mid \varphi \} | =k \mathrel {\wedge } k \le n+1\). For \(\varphi ^{-}=false\), \(\varphi ^{+}=x \ge 0\) and cardinality constraint \(| \{ x \mid \varphi \} | =k \mathrel {\wedge } 1 \le k \le 10\) the constraint \(\varphi =(0 \le x \le 5)\) is a cardinality-constrained interpolant. \(\quad \blacksquare \)

Note that our definition of interpolation differs from the standard, cardinality-free definition given e.g. in [29] in that we do not require the free variables in \(\varphi \) to be common to both \(\varphi ^{-}\) and \(\varphi ^{+}\). We exclude this requirement because it appears to be overly restrictive for the setting with cardinalities, as the cardinality constraint imposes a lower/upper bound in addition to \(\varphi ^{-}\) and \(\varphi ^{+}\). In particular, the common variables condition rules out both interpolants in Example 4, as the set of common variables is empty in both cases.

In this paper, we focus on cardinality constraints with \(\varphi \) in linear arithmetic and \(\psi \) in (non-linear) arithmetic, which is an important combination for applications in software verification.

Interpolation Algorithm. We present an algorithm \(\#\textsc {Itp}_\textsc {LIA} \) for interpolation with cardinality constraints. For simplicity of exposition, we first consider the non-parametric case and discuss the parametric case in Sect. 5.

\(\#\textsc {Itp}_\textsc {LIA} \) finds an interpolant \(\varphi \) in a space of polytope candidates that is defined through a template. This template is given by a function \(\textsc {Tmpl}\) that maps a symbolic vertex \(v\in \mathcal {V}\) to a set of symbolic hyperplanes that are determined to intersect in v, where each hyperplane \(H \in \textsc {Tmpl}(v)\) is of the form \(c_H \cdot w = \gamma _H\).

The algorithm \(\#\textsc {Itp}_\textsc {LIA} \) is described in Fig. 1. It collects a constraint \(\textsc {Cons} \) over the symbolic vertices and symbolic hyperplanes of \(\varphi \), which ensures that any solution yields a unimodular polytope that satisfies conditions (1) – (3) of the definition of cardinality interpolation. In particular, \(\#\textsc {Itp}_\textsc {LIA} \) ensures that the cardinality of \(\varphi \) satisfies \(\psi \) by constructing a symbolic expression \(\textsc {SymCard}\) on the cardinality of \(\varphi \) in line 13, and requiring that this expression satisfies the cardinality constraint \(\psi \) in line 15. Line 12 produces well-formedness constraints \(\textsc {Vert}(v, \mathcal {H}, \mathcal {H}_\mathcal {V}) \) and \(\textsc {Genr} (v, \mathcal {H}, G)\) that ensure a geometrically well-formed instantiation of the template \(\textsc {Tmpl}\). The final conjunct in line 12 poses constraints on the generators of the vertex cones in \(\varphi \) that ensure their unimodularity, as explained in Sect. 3. Finally, line 14 produces constraints that ensure the validity of the implications \(\varphi ^{-}\mathrel {\rightarrow } \varphi \) and \(\varphi \mathrel {\rightarrow } \varphi ^{+}\). The resulting constraint \(\textsc {Cons} \) is passed to an SMT solver that either returns a valuation of symbolic vertices and hyperplanes and hence determines \(\varphi \), or fails.

Constraint generation. We will now describe the constraint generation of \(\#\textsc {Itp}_\textsc {LIA} \) in more detail. For each symbolic vertex v we make sure that it lies on the hyperplanes determined by \(\textsc {Tmpl}(v)\) and in the appropriate half-space with respect to the remaning hyperplanes. This is achieved by the following constraint.

$$\begin{aligned} \textsc {Vert}(v,\mathcal {H}, \mathcal {H}_\mathcal {V}) = \bigwedge _{ H \in \mathcal {H}} c_{H} \cdot v = \gamma _H \ \mathrel {\wedge } \ \bigwedge _{ H \in \mathcal {H}_\mathcal {V}\setminus \mathcal {H}} c_{H} \cdot v < \gamma _H \end{aligned}$$

By making the inequalities strict, we ensure that the polytope does not collapse into a single point, since in this case Brion’s theorem does not hold.

\(\textsc {SymConeCard}\) and \(\textsc {Unim}\) refer to the generators of vertex cones determined by \(\textsc {Tmpl}\). Hence we produce a constraint that defines these generators in terms of symbolic hyperplanes. Let \(g _{vH}\) denote the generator of the cone at vertex v that lies in the half-space described by hyperplane H. Then we constrain the generators of the cone at v as follows.

$$\begin{aligned} \textsc {Genr} (v, \mathcal {H}, G, \mu ) = {\bigwedge }_{ H \in \mathcal {H}}&(c_H \cdot g _{vH} \le 0 \mathrel {\wedge }\mu \cdot g _{vH} \ne 0 \\&\mathrel {\wedge } {\bigwedge }_{H' \in \mathcal {H}\setminus \{ H \} } c_{H'} \cdot g _{vH} = 0) \end{aligned}$$

Here we require each generator \(g _{vH}\) to lie on the facet formed by the intersection of all hyperplanes \(H' \in \mathcal {H}\setminus \{ H \}\), and to point in the appropriate half-space wrt. H. Additionally the generator is constrained according to Eq. 3. With the generators defined, we can ensure the unimodularity of vertex cones of the polytope by \(\textsc {Unim}(v, G) = ( abs ( det ( g _{vH_1}, \ldots , g _{vH_d})) = 1)\),

where \(G = \{ g _{vH_1}, \ldots , g _{vH_d} \}\). We then use \(\textsc {SymConeCard}(v, G, \mu )\) to denote the counting expression of the symbolic cone of vertex v for our generators. We construct the counting expressions for the entire symbolic polytope \(\varphi \) by taking the sum over counting expressions for its vertex cones.

Finally, we generate constraints \(\textsc {Impl} \) for the implication conditions \(\varphi ^{-}\rightarrow \varphi \) and \(\varphi \rightarrow \varphi ^{+}\) by applying Farkas’ lemma [35], which is a standard tool for such tasks [13, 33]. This lemma states that every linear consequence of a satisfiable set of linear inequalities can be obtained as a non-negative linear combination of these inequalities. Formally, if \(Aw \le b\) is satisfiable and \(Aw\le b\) implies \(cw \le \gamma \) then there exists \(\lambda \ge 0\) such that \(\lambda A = c\) and \(\lambda b \le \gamma \). When dealing with integers, Farkas’ lemma is sound but not complete, see the discussion on completeness at the end of this section. Our implementation of \(\textsc {Impl} \) handles non-conjunctive implication constraints by a standard method based on DNF conversion and Farkas’ lemma.

figure c

Example 5

Consider \(\varphi ^{-}= (1 \le x \mathrel {\wedge } x-y \le 1 \mathrel {\wedge }\, x-y \ge -1 \mathrel {\wedge }\, y \le z \mathrel {\wedge } z \le 10)\), \(\varphi ^{+}= true \), \(w = (x, y)\), and \(\psi = (k \le 120)\). The solution \(\varphi \) is a polytope formed by three vertices \(\mathcal {V}= \{ v_1, v_2, v_3 \}\). It is bounded by the supporting hyperplanes \(\mathcal {H}_\mathcal {V}= \{ H _{1} , H _{2} , H _{3} \}\) with normal vectors \(c_{H_1}, c_{H_2}\) and \(c_{H_3}\), respectively. In our example, we use \(\textsc {Tmpl}\) such that \( v_1 \mapsto \{ H _{1} \), \( H _{3} \}, \; v_2 \mapsto \{ H _{1} , H _{2} \}\), and \(v_3 \mapsto \{ H _{2} , H _{3} \}\), restricting \(\varphi \) to a triangular shape.

We obtain the following constraints:

$$\begin{aligned} \begin{array}{@{}l@{\;=\;}l@{}} \textsc {Vert}(v_1, \{ H_1, H_3 \}, \mathcal {H}_\mathcal {V}) &{} (c_{H_1} \cdot v_1 = \gamma _{H_1} \mathrel {\wedge } c_{H_3} \cdot v_1 = \gamma _{H_3} \mathrel {\wedge } c_{H_2} \cdot v_1 < \gamma _{H_2}) \\ \textsc {Vert}(v_2, \{ H_1, H_2 \}, \mathcal {H}_\mathcal {V}) &{} (c_{H_1} \cdot v_2 = \gamma _{H_1} \mathrel {\wedge } c_{H_2} \cdot v_2 = \gamma _{H_2} \mathrel {\wedge } c_{H_3} \cdot v_2 < \gamma _{H_3}) \\ \textsc {Vert}(v_3, \{ H_2, H_3 \}, \mathcal {H}_\mathcal {V}) &{} (c_{H_2} \cdot v_3 = \gamma _{H_2} \mathrel {\wedge } c_{H_3} \cdot v_3 = \gamma _{H_3} \mathrel {\wedge } c_{H_1} \cdot v_3 < \gamma _{H_1}) \\ \end{array} \end{aligned}$$

We get the following constraints on generators:

$$\begin{aligned} \begin{array}{@{}l@{}l@{}} \textsc {Genr} (v_1, \{ H_1, H_3 \}, \{ g _{v_1H_1}, g _{v_1H_3} \}, \mu ) \;=\; \\ \qquad (\begin{array}{@{}l@{}} c_{H_1} \cdot g _{v_1H_1} \le 0 \wedge c_{H_3} \cdot g _{v_1H_1} = 0 \mathrel {\wedge } c_{H_3} \cdot g _{v_1H_3} \le 0 \wedge c_{H_1} \cdot g _{v_1H_3} = 0)\\ \end{array}\\ \textsc {Genr} (v_2, \{ H_1, H_2 \}, \{ g _{v_2H_1}, g _{v_2H_2} \}, \mu ) \;=\; \\ \qquad (\begin{array}{@{}l@{}} c_{H_1} \cdot g _{v_2H_1} \le 0 \wedge c_{H_2} \cdot g _{v_2H_1} = 0 \mathrel {\wedge } c_{H_2} \cdot g _{v_2H_2} \le 0 \wedge c_{H_1} \cdot g _{v_2H_2} = 0) \\ \end{array}\\ \textsc {Genr} (v_3, \{ H_2, H_3 \}, \{ g _{v_3H_2}, g _{v_3H_3} \}, \mu ) \;=\; \\ \qquad (\begin{array}{@{}l@{}} c_{H_2} \cdot g _{v_3H_2} \le 0 \wedge c_{H_3} \cdot g _{v_3H_2} =0 \mathrel {\wedge } c_{H_3} \cdot g _{v_3H_3} \le 0 \wedge c_{H_2} \cdot g _{v_3H_3} = 0) \end{array} \end{array} \end{aligned}$$

and unimodularity restrictions:

$$\begin{aligned} \begin{array}{@{}c@{}} abs ( det (g _{v_1H_1},g _{v_1H_3})) \mathrel {=} abs ( det (g _{v_2H_1},g _{v_2H_2})) \mathrel {= } abs ( det (g _{v_3H_2},g _{v_3H_3})) = 1 \end{array} \end{aligned}$$

The implication constraints in matrix notation are

$$\begin{aligned} \begin{array}{@{}l@{}} \overbrace{ \begin{pmatrix} -1 &{} 0 \\ 1 &{} -1 \\ -1 &{} 1 \\ 0 &{} 1 \end{pmatrix} }^{A} \begin{pmatrix} x \\ y \end{pmatrix} \mathrel {\le } \overbrace{ \begin{pmatrix} -1 \\ 1 \\ 1 \\ 10 \end{pmatrix} }^{b} \quad \mathrel {\rightarrow } \quad \overbrace{ \begin{pmatrix} c_{11} &{} c_{12} \\ c_{21} &{} c_{22} \\ c_{31} &{} c_{32} \\ \end{pmatrix} }^{C} \begin{pmatrix} x \\ y \end{pmatrix} \mathrel {\le } \overbrace{ \begin{pmatrix} \gamma _1 \\ \gamma _2 \\ \gamma _3 \end{pmatrix} }^{\gamma } \end{array} \end{aligned}$$

where, for each \(i \in \{ 1,2,3 \}\), we obtain the following constraints for \( H _{i} \) by an application of Farkas’ lemma: \( \exists \lambda ^i : \lambda ^i \ge 0 \wedge \lambda ^i A = C_i \wedge \lambda ^i b \mathrel {\le } \gamma _1\). We pass the constraints to an SMT solver and obtain the solution \(\varphi = (1 \le x \; \wedge \; y \le 10 \; \wedge \; y \ge x -3)\) with \(| \{ (x,y) \mid \varphi \} |=91\). \(\quad \blacksquare \)

Theorem 1

(Soundness). If \(\#\textsc {Itp}_\textsc {LIA} (w, \varphi ^{-}, \varphi ^{+}, \psi , \textsc {Tmpl})\) returns a solution \(\varphi \), then \(\varphi \) is a cardinality-constrained interpolant for \(\varphi ^{-}\) and \(\varphi ^{+}\) and cardinality constraint \(| \{ w \mid \varphi \} |=k \mathrel {\wedge } \psi \).

Proof

We show that \(\varphi \) satisfies conditions (1) to (3). Conditions (1) and (2) follow from the use of Farkas’ lemma. Since the conditions posed by \(\textsc {Vert}(v,\mathcal {H}, \mathcal {H}_\mathcal {V}) \) ensure that each vertex is active (part of the polytope) and that vertices are distinct, Brion’s theorem is applicable and hence the generating function of \(\varphi \) can be expressed as the sum of the generating functions of its vertex cones. Each of \(\varphi \)’s vertex cones is unimodular by constraints \(\textsc {Unim}(v, G) \) and its generating function is hence given by the expression in Eq. 2. Summing over the evaluated rational generating functions of the vertex cones is equivalent to evaluating the sum of the rational generating functions by the fact that Laurent expansion distribute over sums. As a consequence, the expression \(\textsc {SymCard}\) corresponds to the cardinality of \(\varphi \) and, by the constraint in Line 15 in Fig. 1, satisfies the cardinality constraint \(\psi \). \(\quad \square \)

Completeness. For a given template, our method returns a solution whenever a solution expressed by the template exists, yet subject to the following two sources of incompleteness. First, solving non-linear integer arithmetic constraints is an undecidable problem and hence the call to \(\textsc {SMTSolve} \) may (soundly) fail. Second, Farkas’ lemma is incomplete over the integers. Note that these sources of incompleteness did not strike on benchmarks from the literature, see Sect. 7.

5 Interpolation with Parametric Cardinalities

We now briefly discuss the parametric interpolation problem by contrasting it with the non-parametric case. Computing the number of integer points in a polytope in terms of a parameter uses the techniques described in Sect. 3. The key challenge we face when extending cardinality-constrained interpolation to the parametric case is a quantifier alternation. While in the non-parametric case the constraints \(\textsc {Cons} \) are quantified as \( \exists \mathcal {H}_\mathcal {V}\; \exists \mathcal {V}: \textsc {Cons} \), introducing parameters changes the quantifier structure to \(\exists \mathcal {H}_\mathcal {V}\; \forall p\; \exists \mathcal {V}: \textsc {Cons} \), where p is a tuple of parameters in the cardinality constraint. The alternation stems from the fact that the parameter valuation detemines the intesection points, that is, the vertices, for parametric polytopes. This alternation has two implication on the computation of interpolants: First, for different values of p the number of vertices of a polytope can vary due to changes in the relative position of the bounding hyperplanes. As a consequence, templates with fixed number of vertices are only valid for a specific parameter range, which is called a chamber [40]. We deal with this aspect by considering a predicate \( cmb \) that restricts the parameter range to the appropriate chamber and that satisfies the implication constraints. We then conjoin \( cmb \) to the inferred polytope.Footnote 3

Second, solving the cardinality constraint requires quantifier elimination for non-linear arithmetic. For this task we devise a constraint-based method ensuring positivity of a polynomial on a given range by referring to its roots.

6 Verification of Programs with Cardinality Constraints

In this section, we sketch our algorithm \(\#\textsc {Horn} \) for solving sets of Horn clauses with cardinality constraints. We choose Horn clauses as a basis for representing our verification conditions as they provide a uniform way to encode a variety of verification tasks [57, 19]. The interpolation procedure \(\#\textsc {Itp}_\textsc {LIA} \) presented in Sect. 4 is a key ingredient for, but not restricted to, \(\#\textsc {Horn} \).

Horn Clauses with Cardinality Constraints. A Horn clause is a formula of the form \(\varphi _0 \wedge q_1 \wedge \dots \wedge q_k \rightarrow H\) where \(\varphi _0\) is a linear arithmetic constraint, and \(q_1, \dots , q_k\) are uninterpreted predicates that we refer to as queries. We call the left-hand side of the implication body and the right-hand side head of the clause. H can either be a constraint \(\varphi \), a query q, or a cardinality constraint of the form \(| \{ w \mid q \} | \le \eta \), where \(\eta \) is a polynomial. By restricting cardinality constraints over queries to this shape, we ensure monotonicity, which is key for the soundness of over-approximation. For a clause \(\varphi _0 \wedge q_1 \wedge \dots \wedge q_k \rightarrow q\), we say that q depends on queries \(q_1, \dots , q_k\). We call a set of clauses recursive if the dependency relation contains a cycle, and non-recursive otherwise. For the semantics, we consider a solution function \(\varSigma \) that maps each query symbol q occurring in a given set of clauses into a constraint. The satisfaction relation \(\varSigma \models cl \) holds for a clause \( cl = (\varphi _0 \wedge q_1 \wedge \dots \wedge q_k \rightarrow H)\) iff the body of \( cl \) entails the head, after replacing each q by \(\varSigma (q)\). The lifting from clauses to sets of clauses is canonical.

Algorithm Description. \(\#\textsc {Horn} \) takes as input a set \(C\) of recursive Horn clauses with cardinality constraints and produces as output either a solution to the clauses or a counterexample. Due the undecidability caused by recursion, \(\#\textsc {Horn} \) may not terminate. The solver executes the following main steps: abstract inference, property checking, and refinement.

Abstract inference. We iteratively build a solution for the set of inference clauses \(\mathcal {I}= \{ cl \in C\mid cl = (\ldots \rightarrow q) \}\) by performing logical inference until a fixpoint is reached. This step uses abstraction to ensure that the inference terminates, where the abstraction is determined by a set of predicates \( Preds \). This step is standard [19], as clauses \(\mathcal {I}\) do not contain cardinality constraints.

Property checking. We check whether the constructed solution satisfies all property clauses in \(\mathcal {P}= C\setminus \mathcal {I}\). The novelty in \(\#\textsc {Horn} \) is the check for satisfaction of cardinality constraints \(| \{ w \mid \varphi \} | \le \eta \), where \(\varphi \) is a linear arithmetic constraint. Here we rely on a parametric extension of Barvinok’s algorithm [40], which on input \(\varphi \) returns a set of tuples \(\mathscr {B}(\varphi ,w)=\{( cmb _1, c_1),\; \dots \}\) such that whenever the constraint \( cmb _i\) holds, the cardinality of \(| \{ w \mid \varphi \} |\) is given by the expression \(c_i\), which may either be a polynomial \(c_i\), or \(\omega \) for the unbounded case. We hence reduce checking satisfaction of the cardinality constraint \(| \{ w \mid \varphi \} | \le \eta \) to checking the following constraint.

$$\begin{aligned} \begin{array}{@{}ll@{}} {\bigwedge }_{( cmb , c) \in \mathscr {B}(\varphi ,w)} \left( cmb \rightarrow c\le \eta \right) \end{array} \end{aligned}$$

If the check succeeds, the algorithm returns the solution. Otherwise, the algorithm proceeds to a refinement phase to analyze the derivation that led to the violation of the property clause.

Refinement. We construct a counterexample, i.e., a set \( CEX \) of recursion-free Horn clauses with cardinality constraints that represents the derivation that led to the violation of the property clause. This counterexample may either be genuine or spurious due to abstraction. To determine which it is, we rely on a solver for non-recursive clauses with cardinality constraints that either produces a solution for the clauses or reports that no such solution exists. If no solution exists, the algorithm returns the counterexample that represents a genuine error derivation. Otherwise it uses \(\#\textsc {Itp}_\textsc {LIA} \) to eliminate the cardinality constraint from the clauses thus producing a set of cardinality-free Horn clauses. We solve these clauses using existing methods [22] and obtain a set of predicates that we use to refine the abstraction.

7 Experiments

We implemented our method in SICStus Prolog, and use its built-in constraint solver for the simplification and projection of linear constraints, HSF [19] for solving recursion- and cardinality-free Horn clauses, and Z3 [16] for non-linear/boolean constraint solving. We use barvinok [38] for checking whether a solution candidate satisfies a cardinality constraint. We use a 1.3 Ghz Intel Core i5 computer with 4 GB of RAM.

Table 1. Application of #Horn on three classes of examples.

Benchmarks from the literature. We use #Horn to analyze a set of examples taken from the recent literature on resource bound computation (in particular: time and heap space), with results given in Table 1a. We find that #Horn is able to prove all bounds in the literature while being slightly faster on average.

The time consumption of loops is bounded by synthesising a polytope containing all tuples of loop counter valuations. For example, for two loops with counters i and j bounded by parameters n and m, we synthesize a polytope of the form: \(a \le i \le n+b \wedge c \le j \le m+d\), where abcd are inferred by our method. For heap consumption, we use the cost model of [24]. We encode \( max \) using disjunctions.

Dealing with relational dependencies. We use #Horn to analyze programs mcm for matrix chain multiplication of Sect. 2 and an array manipulating program band matrix for which code is provided in [37], with results in Table 1b. These examples require the tracking of relational dependencies between variables. The example mcm is particularly challenging as it requires reasoning about recursive function calls. We are not aware of any other method that can handle programs with both features. We use a template specifying that the sought polytope consists of three and four symbolic vertices, respectively. Choosing a template that is not expressive enough might only allow to prove coarser bounds, however, one can automate the problem of finding an appropriate template by iterating over templates with an increasing number of symbolic vertices.

figure e

Synthesis of countermeasures. By relying on recursive Horn clauses as input language, #Horn is readily applicable to a number of verification questions that go beyond reachability. We illustrate this using the example of procedure index(ae), which returns the first position of an element e in an array a. Note that the execution time of index (modeled by the variable t) reveals the position of e. We apply #Horn for synthesizing a padding countermeasure against this timing side channel. Namely, we seek to instantiate the initialization of the variable j such that it provides enough padding for a given bound on leakage. This is achieved by bounding the cardinality of the set of possible final values of t. We add an additional clause that constrains the cardinality of values for t upon termination, as the logarithm of this number corresponds to the amount of leaked information in bits, see e.g. [36]. Table 1c provides the timings and synthesized initialization of j for different bounds on leakage.

8 Related Work

Counting integer points in polytopes. The theory of counting integer points in polytopes has found wide-spread applications in program analysis. All applications we are aware of (including [2, 17, 28, 40]) compute cardinalities for given polytopes, whereas our interpolation method computes polytopes for given cardinality constraints.

Verdoolaege et al. [40] also derive symbolic expressions for the number of integer points in parametric polytopes. In their approach, the parameter governs only the offset of the bounding hyperplanes (and hence the position of the vertices of the polytope) but not their tilt (and hence not the generators of the vertex cones). The advantage of fixing the vertex cones is that Barvinok’s decomposition can be applied to handle arbitrary polytope shapes. In contrast, our interpolation procedure \(\#\textsc {Itp}_\textsc {LIA} \) (see Sect. 4) leaves the vertices and the generators of the vertex cones symbolic, up to constraints that ensure their unimodularity. The benefit of this approach is the additional degree of freedom for the synthesis procedure. #Horn leverages both approaches: the one from [40] for checking cardinality constraints, and \(\#\textsc {Itp}_\textsc {LIA} \) for refining the abstraction.

Recently, [17] presented a logic and decision procedure for satisfiability in the presence of cardinality constraints for the case of linear arithmetic. In contrast, we focus on synthesizing formulas that satisfy cardinality constraints, rather than checking their satisfiability.

Resource bounds. In [26] a static analysis estimates the worst case execution time of non-parametric loops using the box domain. To ensure precision, the widening operator intersects the current abstraction with polytopes derived from conditional statements. In contrast, our approach generates abstraction consisting of parametric unimodular polytopes (which include boxes as a special case). In [21], the authors compute parametric resource and time bounds by instrumenting the program with (multiple-) counters, using static analysis to compute a bound for the counters, and combining the results to yield a bound for the entire program. In contrast, we fit polytopes over each iteration domain of the program, thus avoiding the need to infer counter placement and enabling higher precision by tracking dependencies between variables. In [39] a pattern-matching based method extracts polytopes representing the iteration domain of for-loops from C source. In contrast our method operates on unstructured programs represented as Horn clauses. In [23, 24], a type system for the amortized analysis for higher-order, polymorphic programs is developed. Their focus lies on recursive data-types while we mostly deal with recursion/loops over the integers. In [10], this line of work is extended to the verification of C programs. In [1, 30] closed-form bounds on resource usage are established by solving recurrence relations.

Quantitative verification. Existing verification methods for other theories rely on cardinality extensions of SAT [18], or Boolean algebra of (uninterpreted) sets [25], multisets [31], and fractional collections [32]. These approaches focus on either computing the model size or checking satisfiability of a formula containing cardinality constraints. Cardinalities of uninterpreted sets are also used in [20] for establishing termination and memory usage bounds based on fixed abstractions. Finally, CEGAR approaches for weighted transition systems have been studied in  [11, 12]. These approaches considers abstractions for mean-payoff objectives such as limit-average or discounted sum.

9 Conclusion

We applied the theory of counting integer points in polytopes to devise an algorithm for a cardinality-constrained extension of Craig interpolation. This algorithm proceeds by posing constraints on a symbolic polytope that specify both its shape and cardinality and then solves the constraints via an SMT solver. We embedded our interpolation procedure into a solver for recursive Horn clauses with cardinality constraints and experimentally demonstrated its potential.