1 Introduction
This paper is concerned with the static analysis of logic programs, in particular with (set) sharing analysis, whose aim is to identify sets of variables that share a common variable in a substitution. For example, consider the substitution
$\{x/f(u, v), y/g(u, u, u), z/v\}$
. We say that
$x$
and
$y$
share the variable
$u$
, while
$x$
and
$z$
share the variable
$v$
, and no single variable is shared by
$x$
,
$y$
, and
$z$
. Sharing has been extensively studied in many papers, such as those by Hans and Winkler (Reference Hans and Winkler1992); Jacobs and Langen (Reference Jacobs and Langen1992); Muthukumar and Hermenegildo (Reference Muthukumar and Hermenegildo1992); Codish et al. (Reference Codish, Søndergaard and Stuckey1999); Bagnara et al. (Reference Bagnara, Hill and Zaffanella2002); Jurjio-Rivas et al. (Reference Jurjio-Rivas, Morales, López-Gárcia and Hermenegildo2024). It is well known that the precision of sharing analysis may be increased if we also record information about the linearity of terms. We say that a term is linear if it does not contain multiple occurrences of the same variable. For example, the term
$f(x, f(y, z))$
is linear, while
$f(x, f(y, x))$
is not, since
$x$
occurs twice. Integration of linearity and sharing information has been proposed by many authors, such as Codish et al. (Reference Codish, Dams, Yardeni and Furukawa1991); Hans and Winkler (Reference Hans and Winkler1992); Muthukumar and Hermenegildo (Reference Muthukumar and Hermenegildo1992); King (Reference King1994), and recently also in object-oriented languages by Amato et al. (Reference Amato, Meo and Scozzari2022). The works of Codish et al. (Reference Codish, Mulkers, Bruynooghe, de la Banda and Hermenegildo1995) and Bagnara et al. (Reference Bagnara, Zaffanella and Hill2005) contain extensive comparative evaluations of static analyses of logic programs combining many different abstract properties.
In this paper, we focus on the following abstract domains:
-
• Sharing, the basic domain for (set) sharing analysis, including the improvements presented by Amato and Scozzari (Reference Amato and Scozzari2009).
-
• ShLin, a simple domain combining sharing and linearity information (more precisely, it is the reduced product
$\mathrm{SHARING} \times \mathrm{LIN}$
), including the optimal operators presented by Amato and Scozzari (Reference Amato and Scozzari2010, Reference Amato and Scozzari2014, Reference Amato and Scozzari2024). -
•
$\mathrm{S{\scriptstyle H}L{\scriptstyle IN}}^{2}$
, originally introduced by King (Reference King1994) and later refined by Amato and Scozzari (Reference Amato and Scozzari2010, Reference Amato and Scozzari2024).
For each domain, we implemented both the standard (as described in the literature) and the optimal abstract operators. An operator is optimal if it is the most precise correct abstraction of its concrete counterpart. While optimality is well understood theoretically, its practical impact is less clear. Intuitively, increasing precision comes at a computational cost, since it often requires more complex operations. Therefore, one may expect a trade-off between precision and performance when adopting optimal operators. However, in some cases, higher precision may lead to smaller abstract objects, which can reduce the overall cost of the analysis.
All the domains have been implemented in the PLAI static analyzer (Muthukumar and Hermenegildo Reference Muthukumar and Hermenegildo1992), which is part of CiaoPP, the pre-processor (Bueno et al. Reference Bueno, López-García, Morales, Puebla and Hermenegildo2025) of the Ciao Prolog system (Bueno et al. Reference Bueno, Carro, Hermenegildo, López-García and Morales1997). PLAI performs a goal-dependent analysis, where the program is analyzed with respect to a given goal. Goal-dependent analysis requires the implementation of two main operations called forward and backward unificationFootnote
1
(see the papers by Cortesi et al. (Reference Cortesi, Filé and Winsborough1996) and Amato and Scozzari (Reference Amato and Scozzari2009)). Forward unification performs parameter passing by unifying the atom chosen by the selection rule and the call substitution with the head of the chosen clause. The result is an initial substitution for the clause, called entry substitution. Backward unification propagates back to the initial goal the exit substitution (i.e., the result of the analysis of the clause body), thus obtaining the answer substitution
Footnote
2
for the initial goal. Forward and backward unification may be implemented using a common unification operator (
$\mathit{mgu}$
) together with other straightforward operations like projection and renaming of variables. Amato and Scozzari (Reference Amato and Scozzari2009) show that precision of backward unification may be improved by making use of an additional matching (
$\mathit{match}$
) operator.
The aim of this paper is: (1) to analyze the trade-off between standard and optimal operators for
$\mathit{mgu}$
and
$\mathit{match}$
; (2) to explore alternative implementations of backward unification, based either on
$\mathit{mgu}$
alone or on a combination of
$\mathit{mgu}$
and
$\mathit{match}$
; and (3) to experimentally evaluate the
$\mathrm{S{\scriptstyle H}L{\scriptstyle IN}}^{2}$
domain, which has not been implemented before.
The rest of the paper is structured as follows. Section 2 introduces the abstract domains considered in this work. Section 3 describes their implementation within the PLAI analyzer. Section 4 presents the experimental evaluation and discusses the impact of different operators on precision and performance. Finally, Section 5 concludes with directions for future work.
2 Preliminaries: Abstract domains for sharing analysis
In this section, we provide a formal yet intuitive presentation of the abstract domains involved in the experimental evaluation. Given two sets
$C$
and
$A$
of concrete objects and abstract properties, called the concrete and abstract domain, respectively, an abstract interpretation (Cousot and Cousot Reference Cousot and Cousot1992) is given by an approximation relation
$\rhd \subseteq A \times C$
. When
$a \rhd c$
holds, we say that
$a$
is a correct abstraction of
$c$
. We work in a framework where
$A$
is endowed with a partial order relation to compare properties by precision:
$a_1 \lt a_2$
means that
$a_1$
is more precise than
$a_2$
. The precision and approximation relations are related by the following: (1)
$a \rhd c$
and
$a \leq a'$
imply
$a' \rhd c$
and (2) each
$c$
has a least (most precise) correct abstraction in
$A$
. Following the collecting semantics approach (Amato et al. Reference Amato, Meo and Scozzari2020), abstract operators are defined as correct approximations of their concrete counterparts. Given a function
$f: C \rightarrow C$
, we say that
$\tilde {f}: A \rightarrow A$
is a correct abstraction of
$f$
, and we write
$\tilde {f} \rhd f$
, when
$a \rhd c \Rightarrow \tilde {f}(a) \rhd f(c)$
. We say that
$\tilde {f}: A \rightarrow A$
is the optimal abstraction of
$f$
when it is correct and, for each
$f': A \rightarrow A$
,
$ f' \rhd f \Rightarrow \tilde {f} \leq f'$
with the pointwise ordering. In other words, the optimal abstraction of a concrete operator
$f$
is its most precise correct approximation.
2.1 The Sharing abstract domain
The pioneering abstract domain Sharing by Jacobs and Langen (Reference Jacobs and Langen1992) represents sharing information in a concise set representation. Let
$\mathcal{V}$
be an infinite set of variables and
$\mathcal{P}_f(\mathcal{V})$
be the set of its finite subsets. The domain Sharing can be defined as follows:
Intuitively, an abstract object
$[A,U]$
describes the relationships among the variables in
$U$
: if
$S\in A$
, the variables in
$S$
are allowed to share a common variable. For example,
$[\{ \{x,y\},\{z\},\emptyset \},\{w,x,y,z\}]$
represents the substitutions where
$x$
and
$y$
may possibly share, while
$z$
is independent from both
$x$
and
$y$
. Moreover, the variable
$w$
, which does not appear in the first component, is ground. Two examples of such substitutions are
$\{x/y, w/a\}$
and
$\{w/a\}$
while
$\{x/z, w/a\}$
is not, because
$x$
and
$z$
do share. In addition, a special value
$\bot$
is needed to denote the empty set of substitutions.
2.2 The shLin abstract domain
The abstract domain ShLin keeps track of the amount of linearity information in a substitution, coupling an object of Sharing with the set of linear variables. More formally, it is defined as the reduced product of Sharing and a basic linearity domain Lin. Each element of ShLin is a triple where the first component represents the sets of variables which may share, exactly as in Sharing; the second component records the set of variables that must be linear; the third component is, as before, the set of variables of interest. The abstract domain ShLin is defined as follows, where
$\mathit{vars}(S)$
denotes the set of all the variables in
$S$
:
For instance,
$[\{ \{x,y\}, \emptyset \},\{x,z\}, \{x,y,z\} ]$
represents the substitutions where
$x$
may share with
$y$
, while
$x$
and
$z$
are (always) bound to a linear term (actually
$z$
must be ground). Two examples of such substitutions are
$\{x/t(u,a), y/t(u,u), z/a\}$
and
$\{x/y, z/a\}$
, while
$\{x/t(u,u), y/t(u,u), z/a\}$
is not since
$t(u, u)$
is not linear.
2.3 Intuition on linearity and its impact on sharing precision
Linearity information plays a key role in improving the precision of sharing analysis. In fact, when a variable occurs multiple times in a term, unification may introduce additional sharing between variables.
For instance, consider the substitution
$\theta _1=\{x/f(u,v)\}$
over the set
$U=\{x\}$
of variables of interest. This substitution is abstracted in Sharing as
$S=[\{ \{x\}, \emptyset \},U]$
. If we now compute the
$\mathit{mgu}$
between
$S$
and
$\mathcal E=\{x=f(y,z)\}$
, we obtain the abstract object
$\mathit{mgu}(S,\mathcal E)=[\{ \{x,y\},\{x,z\},\{x,y,z\}, \emptyset \},\{x,y,z\}]$
, which contains the sharing group
$\{x,y,z\}$
, due to the fact that the substitution
$\theta _2=\{x/f(u,u)\}$
is also abstracted as
$S$
in Sharing.
Linearity information mitigates this problem. Intuitively, linearity acts as a constraint that rules out combinations of sharing groups that would only arise due to repeated occurrences of variables. In fact, the substitutions
$\theta _1$
and
$\theta _2$
are abstracted in different objects in ShLin, namely
$S_1=[\{ \{x\}, \emptyset \},\{x\},U]$
and
$S_2=[\{ \{x\},\emptyset \},\emptyset ,U]$
. The abstract unification operator in ShLin can now exploit this information and obtain
$\mathit{mgu}(S_1,\mathcal E)=[\{ \{x,y\},\{x,z\},\emptyset \}, \{x,y,z\},\{x,y,z\}]$
while
$\mathit{mgu}(S_2,\mathcal E)=[\{ \{x,y\},\{x,z\},\{x,y,z\},\emptyset \}, \emptyset ,\{x,y,z\}]$
which still contains the sharing group
$\{x,y,z\}$
.
2.4 The shLin2 abstract domain
The idea behind
$\mathrm{S{\scriptstyle H}L{\scriptstyle IN}}^{2}$
is to enhance Sharing by annotating each sharing group with linearity information on each variable. If a variable in a sharing group is (possibly) non-linear, it is denoted using
$\omega$
as an exponent, otherwise the variable is linear. For instance, the object
$xy^\omega z$
(called a 2-sharing group) represents the sharing group
$\{x,y,z\}$
and the information that the common variable shared among
$x$
,
$y$
and
$z$
may occur more than once in
$y$
but only once in
$x$
and
$z$
. For example, this is the case for the variable
$u$
in the substitution
$\{ x/f(u,v,v), y/g(u,u,w), z/u \}$
. The
$\mathrm{S{\scriptstyle H}L{\scriptstyle IN}}^{2}$
abstract domainFootnote
3
can be defined as follows:
Linearity information may vary between 2-sharing groups. For instance,
$[\{xy, y^\omega z, \emptyset \}, \{x, y, z\}]$
represents the substitutions
$\theta$
where the variable
$y$
may share with
$x$
or
$z$
,
$x$
and
$z$
are linear, while
$y$
might be non-linear. However, the variable in common between
$\theta (x)$
and
$\theta (y)$
may only appear once in
$\theta (y)$
. An example of such a substitution is
$\{x/u, y/t(u,v,v), z/v\}$
, while
$\{x/u, y/t(u,u,v), z/v\}$
is not.
2.5 Optimal abstract operators
All the above abstract domains are equipped with the optimal abstract operators for unification, matching and the other required operations. Amato and Scozzari (Reference Amato and Scozzari2009, Reference Amato and Scozzari2024) implement backward unification through matching, exploiting the property that the exit substitution is always more instantiated than the call substitution. Analyses based on matching have been shown to be strictly more precise than analyses that do not use matching. Moreover, Amato and Scozzari (Reference Amato and Scozzari2024) show that when using the optimal operators, the overall analysis is strictly more precise than the analysis performed with the standard operators. Surprisingly, the optimal operators are able to improve not only sharing and linearity information but also groundness.
3 Implementation
We have implemented the abstract domains Sharing, ShLin,
$\mathrm{S{\scriptstyle H}L{\scriptstyle IN}}^{2}$
, together with their operators, within the PLAI analyzer. All our code is publicly available on GitHub under the LGPL-3.0 license at https://github.com/CLAI-UdA/ciaopp.
3.1 Structure of the code
PLAI is written in Prolog and completely modular: each abstract domain is implemented in its own module and communicates with the analyzer engine through a well-defined interface. However, this interface is quite extensive and, to reduce the amount of code required for each abstract domain, we implemented a compatibility layer in the module as_template which translates the standard interface into more elementary operations.
For example, consider the call_to_entry predicate, part of the abstract domain interface, corresponding to what we have called forward unification. It is defined as follows:

where
-
• Sg is the goal we are going to analyze;
-
• Sv is the set of variables occurring in Sg;
-
• ClauseKey is an identifier for the clause we are using to analyze Sg;
-
• Head is the head of the clause;
-
• Hv is the set of variables occurring in Head;
-
• Fv are the variables in the clause that do not occur in Head;
-
• Proj is the call substitution projected onto the variables in Sv;
-
• Entry is the resulting entry substitution;
-
• ExtraInfo may contain additional information that is passed later to the backward unification phase.
Our implementation of this predicate is the following:

It combines the predicates augment, mgu and project, implemented in each of our domains, with unifiable_with_occurs_check which is a built-in predicate in Ciao.
The compatibility layer also avoids duplicating code that is syntactically identical across different domains. For example, the special value $bottom, which denotes an empty abstract substitution (corresponding to
$\bot$
in Section 2.1), is handled largely within this layer. The same applies to most of the code for analyzing Prolog built-ins. Apart from the compatibility layer, there are two other modules that contain code shared by all our domains: as_aux contains generic utility code, while as_bags contains an implementation of finite multisets.
Finally, the three domains are implemented in the modules as_sharing, as_shlin and as_shlin2. Although CiaoPP already provides several implementations of Sharing, we have devised a new one to serve as a baseline for the other domains in our collection. The behavior of the analysis (such as choosing between matching or unification for backward unification, or between optimal and standard operators) can be configured through specific CiaoPP flags.
The built-in PLAI domains for sharing analysis are implemented natively in Prolog, using sets (ordered lists) and a shallow encoding of logic variables. We adopt the same approach in our implementations. All code is fully annotated with type and mode information using the annotation mechanism provided by the Ciao system. For example, this is the complete specification of the predicate computing the lubs of abstract substitutions:

The specification states that compute_lub is always called with a non-empty list of abstract substitutions as its first argument, and an independent variable as a second argument, which is bound to an abstract substitution on exit. The predicate is also declared to be deterministic and not to fail (when called under these preconditions). These annotations may be checked at run-time and have proved very useful during development, both for catching bugs in our code and for ensuring a correct understanding of how the CiaoPP interface is expected to work. In addition, most modules include a comprehensive test suite.
3.2 From the algorithm to the implementation
Moving from the algorithmic descriptions given in our papers to their actual implementation has not always been straightforward, and has required careful consideration.
First of all, while PLAI has the predicate call_to_entry which corresponds directly to forward unification, it splits backward unification into two distinct steps. First, the exit substitution is projected onto the variables of the chosen atom by the predicate exit_to_prime, it is then extended to all the variables of the original goal by the predicate extend, incorporating the information on the other variables coming from the call substitution. This process is depicted in Figure 1, which we briefly describe here. The procedure
$\texttt {{call to entry}}$
computes the
$\mathit{mgu}$
between
$\theta ^{in}$
and
$\mathcal E$
, the equation connecting the selected atom
$q(t(Y), Y)$
and the clause head
$q(t(A), B)$
, yielding
$\bar \theta = \mathit{mgu}(\theta ^{in}, \mathcal E) = \{X/f(\_0),Y/f(\_0),Z/\_1,A/f(\_0),B/f(\_0)\}$
. This is then projected onto the variables of the clause to obtain the entry substitution
$\theta$
. After analyzing the body,
$\theta$
is further instantiated, yielding the exit substitution
$\theta '$
.
Now exit_to_prime computes the
$\mathit{mgu}$
between
$\theta '$
and
$\bar \theta$
, and projects the result onto the variables of the selected goal, obtaining
$\theta ''$
, called the prime. Note that in this step we are sure that variables in
$\theta '$
are not further instantiated, hence unification may be replaced by matching. Using matching instead of unification (which is irrelevant in the concrete) improves precision in the abstract. Finally, extend propagates the effect of the prime to the entire initial goal, by unifying it with the call substitution. Again, since variables in the prime are not going to be further instantiated, unification may be replaced by matching.
Two observations are worth noting. First, the extend step is conceptually redundant: the final projection in exit_to_prime could be performed directly over all variables of the initial goal, thus producing the answer substitution in a single step. However, this would require modifying the PLAI engine, which we do not intend to do. Second, our
$\mathit{mgu}$
and
$\mathit{match}$
operations are designed so that
$\mathit{mgu}$
takes an abstract substitution and a concrete set of equations, whereas
$\mathit{match}$
takes two abstract substitutions. This makes the implementation of extend using only
$\mathit{mgu}$
a bit cumbersome, since it should operate on two abstract substitutions.
Flow of the analysis in PLAI.

More importantly, the definitions of
$\mathit{mgu}$
and
$\mathit{match}$
given in our papers are expressed in a declarative style. It is relatively easy to implement these operators following the definitions using a generate-and-test approach, and we have adopted this strategy in several cases. However, there are some cases in which this approach is too slow, making it necessary to devise more carefully optimized implementations.
As an illustrative example, consider the definition of the matching operator for ShLin shown in Figure 2. Rather than discussing the details of the definition (for which we refer to Amato and Scozzari (Reference Amato and Scozzari2010)), we use it here to highlight some of the issues that arise in its implementation. The crucial step in the definition is the computation of
$S''_0$
. This involves selecting a sharing group
$B \in S_1$
and a subset of sharing groups
$X \subseteq S''_2$
, and then checking whether the conditions
$B \cap U_2 = \left (\bigcup X\right ) \cap U_1$
and
$L_1 \cap nl(X)=\emptyset$
are satisfied.
A straightforward implementation would follow a generate-and-test strategy that mirrors the formal definition. However, this approach requires enumerating a large number of candidate subsets
$X$
, whose number is exponential in the size of
$S''_2$
, which is itself potentially exponential in the number of program variables. To obtain a practically usable implementation, it is therefore necessary to reduce the search space.
First, once we fix
$B \in S_1$
, a necessary condition for satisfying
$B \cap U_2 = \left (\bigcup X\right ) \cap U_1$
is that every
$C \in X$
satisfies
$C \cap U_1 \subseteq B \cap U_2$
. Hence, we can restrict the search to subsets
$X \subseteq \{ C \in S''_2 \mid C \cap U_1 \subseteq B \cap U_2 \}$
. Additionally, instead of generating
$X$
, checking constraints and then producing the pair
$\left \langle B \cup \bigcup X, L_2 \setminus nl(X) \setminus \bigcup (X \cap \bar S) \right \rangle$
, we have devised a procedure that incrementally builds the resulting pairs, without explicitly generating the candidates
$X$
at all. In this way, although the theoretical complexity of the procedure does not decrease, the implementation is generally much faster.
The definition of the match operator in ShLin, for
$[S_1,L_1,U_1]$
and
$[S_2,L_2,U_2] \in \mathrm{S{\scriptstyle H}L{\scriptstyle IN}}$
.

4 Experimental evaluation
In order to benchmark both the precision and the efficiency of our domains, we used the SWI-Prolog benchmark suite.Footnote 4 It consists of 35 Prolog programs, collected by the SWI-Prolog organization but running on many Prolog systems. Two programs were removed from the suite: det.pl, which does not run in Ciao, and queens_clpfd.pl, which relies on CLP(FD) features that are not supported in our setting. As a result, we analyzed a total of 33 programs. They are listed in Table 1 together with some basic size metrics.
Benchmark programs and corresponding size metrics. The column max vars is the maximum number of variables in a clause

Each program was analyzed in 15 different configurations. These include the built-in Sharing domain provided by PLAI (share_amgu), the built-in
$\mathrm{SHARING} \times \mathrm{FREE} \times \mathrm{LIN}$
(shfrlin_amgu), as well as our implementations of Sharing, ShLin and
$\mathrm{S{\scriptstyle H}L{\scriptstyle IN}}^{2}$
with different options. In the following, we report only a representative subset of these configurations. The configuration referred to as base uses the standard (as described in the literature)
$\mathit{mgu}$
for both forward and backward unification. In particular, the standard operators used for ShLin are the ones by Hans and Winkler (Reference Hans and Winkler1992), including the independence checks that Howe and King (Reference Howe and King2003) and Hill et al. (Reference Hill, Zaffanella and Bagnara2004) showed to be removable. The configuration match employs the standard
$\mathit{mgu}$
for forward unification but the (optimal) matching operator for backward unification. Finally, the configuration optimal uses optimal operators for both
$\mathit{mgu}$
and
$\mathit{match}$
.
The built-in domains share_amgu and shfrlin_amgu rely on specialized implementations that likely do not correspond to any of the configurations considered in this work. To the best of our knowledge, these implementations have not been fully described in the literature, at least in their current form. Note that shfrlin_amgu also tracks freeness information. This additional component may both improve precision and introduce extra computational overhead, which should be taken into account when comparing performance.
All benchmarks were executed on a machine equipped with an Intel i5-13600K CPU with 32 GB of RAM, running Ubuntu Linux 25.10 and Ciao 1.25.0-m1. We measured both execution time and precision, according to the following procedure:
-
• CiaoPP was instructed to analyze the main predicate of each program;
-
• other predicates were analyzed only as a consequence of this initial call;
-
• a timeout of 2 minutes was imposed for each analysis;
-
• the virtual address space of the analyzer was limited to 24 GB of RAM.
Critical programs, causing either a timeout or an out-of-memory condition (both
).

The 24 GB memory limit was introduced to reliably detect out-of-memory conditions. In preliminary experiments, we relied on the operating system’s OOM killer; however, this approach proved inconsistent, as it occasionally terminated not only the analyzer but also the script orchestrating the benchmark execution.
Following this procedure, we were able to fully analyze all benchmarks, with the exception of six critical programs, which failed under at least one configuration. These programs are summarized in Figure 3. There are two cases, namely reducer with ShLin and flatten with
$\mathrm{S{\scriptstyle H}L{\scriptstyle IN}}^{2}$
, where increasing precision of abstract operators leads to non-termination, and two cases, namely chat_parser with ShLin, reducer with
$\mathrm{S{\scriptstyle H}L{\scriptstyle IN}}^{2}$
and unify with both Sharing and ShLin, where increasing precision allows the analysis to complete within the timeout.
As expected, the program metric most strongly correlated with analysis failures is the maximum number of variables in a clause (max vars), as it directly affects the size of abstract objects. In fact, the six programs in Figure 3 are all among the top nine programs with the highest values of the max vars metric. This observation is confirmed by computing the Pearson correlation coefficient between the indicator function of the timeout/out-of-memory condition and each metric. The highest correlation is consistently obtained with max vars across all abstract domains. For instance, for ShLin with optimal operators, the correlation is 0.72 with max vars, while it remains below 0.30 for all other metrics.
Analysis time for non-critical programs.

Figure 4 reports the execution time for all non-critical programs, while Table 2 provides the complete set of results. For each domain we show a boxplot comparing different configurations, followed by a final boxplot comparing the three domains under optimal operators. As expected, more complex domains lead to higher execution times. However, the increase is negligible when comparing ShLin with Sharing, while it is much more visible for
$\mathrm{S{\scriptstyle H}L{\scriptstyle IN}}^{2}$
. This behavior is expected, since the size of abstract objects for the latter is much larger. Analyzing the boxplots for each domain confirms what we already observed for the critical programs: while more complex operators may increase analysis time, this effect does not occur systematically, the increase is generally negligible and sometimes the opposite happens.
Analysis time for all programs with the different abstract domains and configurations. OOM denotes an out-of-memory condition, while TO denotes a timeout

If we exclude timeout and out-of-memory cases, the correlation between analysis time and the considered metrics becomes less clear. In particular, max vars generally shows a low correlation, while predicates tends to exhibit higher values. However, these trends vary significantly across the different abstract domains.
Precision with respect to the sharing property.

Figure 5 reports the precision of the three domains with respect to the sharing property. For each program and configuration, we counted the number of sharing groups in the annotations generated by CiaoPP. For program points where CiaoPP reports multiple analysis results, corresponding to different preconditions, we only counted the sharing groups appearing in the alternative with the smallest number of sharing groups. Although this is a coarse measure of precision, it provides a useful indication of overall trends. It shows that the use of matching and optimal operators leads to a clear increase in precision for the ShLin domain, while the improvement is more limited for Sharing and
$\mathrm{S{\scriptstyle H}L{\scriptstyle IN}}^{2}$
. Moreover, more expressive domains yield more precise results.
Precision with respect to the linearity property.

Figure 6 reports the precision with respect to the linearity property, measured by counting the number of linear variables, and computing the maximum in case of multiple annotations. The results are similar to those obtained for the sharing property. We do not report boxplots for groundness, since almost all configurations yield identical results.
Precision results for all analyzed programs and configurations. + indicates the use of optimal mgu, while (+) indicates identical results for standard and optimal mgu (which are therefore collapsed in a single column); M denotes the use of matching instead of mgu; ++ denotes the use of both optimal mgu and optimal matching. OOM denotes an out-of-memory condition, while TO denotes a timeout

Table 3. Long description
A table comparing precision results for various programs and configurations, focusing on the linearity property. The table has 40 rows and 14 columns. Column headers are as follows: property, program, shlin2 (+), shlin2 opt mgu, shlin2 noopt mgu, shlin opt, shlin noopt, shlin, sharing opt mgu, sharing noopt mgu, sharing (+), sharing (+) share, sharing mgu share, and sharing shfrlin. Row labels include various programs such as boyer, browse, chat_parser, crypt, derive, divide10, eval, fast_mu, fib, flatten, log10, meta_qsort, moded_path, mu, nand, nreverse, ops8, perfect, pingpong, poly_10, prover, qsort, queens_8, query, reducer, sendmore, serialise, sieve, simple_analyzer, tak, times10, unify, and zebra. Each row presents the precision results for the corresponding program under different configurations. Notable trends include varying precision results across different programs and configurations, with some programs experiencing out-of-memory (OOM) conditions or timeouts (TO).
The complete set of detailed results is provided in Table 3, which shows that
$\mathrm{S{\scriptstyle H}L{\scriptstyle IN}}^{2}$
with matching and optimal operators yields the most precise results among all the considered domains, with the only exception of the programs chat_parser and flatten, for which the analysis does not terminate. Since we measure sharing precision as the number of sharing groups, this also provides an indication of the size of abstract objects. As expected, in several cases, optimal operators lead to smaller abstract objects. This effect concerns the sharing component only, which is the dominant one, as the number of sharing groups may grow exponentially with the number of variables.
Finally, our implementation of the Sharing domain, when used with the most precise configuration, consistently outperforms the built-in Sharing implementation in CiaoPP; in some cases, it succeeds in terminating analyses for which the built-in implementation does not terminate.
5 Conclusions
The results of our experimental evaluation can be summarized as follows.
-
Optimality. The main outcome is that the use of optimal abstract operators does not compromise the feasibility of the analysis. Even if their definitions are more convoluted, optimal abstract operators can be implemented efficiently in practice. In many cases, they even lead to faster analyses. This behavior is likely a peculiarity of may abstract domains: the additional precision provided by optimal operators often results in smaller abstract objects. As a consequence, the effort required to compute the optimal operators is compensated by the reduced size of the resulting abstract objects. On the other hand, the benefits of optimal operators are not uniform and tend to be significant only in selected cases.
-
Matching. The use of matching consistently outperforms unification. It improves both precision and performance, and in several cases enables analyses that would otherwise time out when relying solely on unification. As a result, matching proves to be a particularly effective choice in practice.
As future work, we plan to extend the experimental evaluation by considering additional benchmark programs and improving the implementation of some abstract operators, in particular the optimal mgu for
$\mathrm{S{\scriptstyle H}L{\scriptstyle IN}}$
and the matching operator for
$\mathrm{S{\scriptstyle H}L{\scriptstyle IN}}^{2}$
, which still follow an unoptimized generate-and-test approach. We also plan to investigate the implementation in CiaoPP of numerical analyses, such as the parallelotope-based analysis by Amato et al. (Reference Amato, Rubino and Scozzari2017), and more advanced fixpoint solvers, such as the ones implemented in ScalaFix (Amato and Scozzari Reference Amato, Scozzari, Chechik, Katoen and Leucker2023).
Competing interests
The authors declare none.


[S1,L1,U1]
[S2,L2,U2]∈SHLIN





