• Aucun résultat trouvé

Enhanced Caching for #SAT Solving

N/A
N/A
Protected

Academic year: 2021

Partager "Enhanced Caching for #SAT Solving"

Copied!
17
0
0

Texte intégral

(1)

HAL Id: hal-02963599

https://hal.archives-ouvertes.fr/hal-02963599

Preprint submitted on 10 Oct 2020

HAL is a multi-disciplinary open access archive for the deposit and dissemination of sci- entific research documents, whether they are pub- lished or not. The documents may come from teaching and research institutions in France or abroad, or from public or private research centers.

L’archive ouverte pluridisciplinaire HAL, est destinée au dépôt et à la diffusion de documents scientifiques de niveau recherche, publiés ou non, émanant des établissements d’enseignement et de recherche français ou étrangers, des laboratoires publics ou privés.

Enhanced Caching for #SAT Solving

Jean-Marie Lagniez, Pierre Marquis

To cite this version:

Jean-Marie Lagniez, Pierre Marquis. Enhanced Caching for #SAT Solving. 2020. �hal-02963599�

(2)

Jean-Marie Lagniez 1 and Pierre Marquis 1,2

1

CRIL-CNRS, Universit´ e d’Artois, F-62300 Lens, France

2

Institut Universitaire de France lagniez@cril.fr marquis@cril.fr

Abstract. We present and evaluate an improved caching scheme and an improved cache cleaning strategy that can be exploited for model counting of propositional formulae in conjunctive normal form (CNF).

The caching scheme consists in storing for each entry (a CNF formula forming a connected component given a current variable assignment, together with its model count) the corresponding set of variables and the corresponding set of clauses, except those clauses of the CNF formula that are satisfied or not shortened when conditioned by the assignment.

The cache cleaning strategy is based not only on the ages of the entries, but also on the proportion of entries of the same size that led to positive hits. We also report the results of an empirical evaluation showing the benefits that are provided by these caching scheme and cache cleaning strategy when implemented in a #SAT solver.

Keywords: Model counting, #SAT, caching.

1 Introduction

Caching turns out to be a key ingredient of propositional model counters and compilers targeting the Decision-DNNF language for knowledge compilation. In a context of model counting or top-down Decision-DNNF knowledge compilation, caching consists in storing a model count (or a Decision-DNNF representation) for each component ϕ found in the current CNF formula, so as to refrain from re-computing it if the component is encountered again during the search. Indeed, in such a case, it is enough to retrieve the associated model count / Decision- DNNF representation from the cache (and to link to the latter so as to produce a Decision-DNNF representation with shared subcircuits in the knowledge compila- tion case).

A caching scheme simply is a mapping making precise how each CNF formula

ϕ considered during search is represented. The quality of a caching scheme can

be measured as its ability to determine efficiently whether a given CNF formula

ϕ has an equivalent representation already in the cache (the time efficiency),

without missing it if this is the case, while ensuring that the cache remains of

a reasonable size (the space efficiency). The two aspects (time and space) are

clearly linked and have a direct impact on the (time and space) complexity of

the model counter/compiler into which the caching scheme is exploited.

(3)

Since the size of the cache can become huge (especially in knowledge com- pilation scenarios, i.e., when Decision-DNNF representations are stored), it is of the utmost importance from the practical side to limit the memory consumption through the use of a cache cleaning strategy so as to avoid out-of-memory errors.

Cache cleaning strategies aim to find out entries that should be removed from the cache because they are of large size and/or are seldom activated (trade-offs are looked for).

Because caching leads to enhance the performance of model counters and compilers, a cache manager is implemented in many state-of-the-art #sat solvers, including Cachet 3 [6] and sharpSAT 4 [7], and top-down compilers, including C2D 5 [1, 2], Dsharp 6 [5], and D4 7 [3].

In this paper, we present and evaluate a caching scheme that appears empir- ically as a good trade-off compared to the previous caching schemes pointed out so far in the literature. In this scheme, the clauses of the current CNF formula ϕ are represented explicitly as in the standard scheme used by Cachet [6], thus avoiding to recognize some entries that are missed by the hybrid scheme consid- ered in sharpSAT [7]. Furthermore, the size of the cache is minimized by storing for each entry the corresponding set of variables and a restricted set of residual clauses. In this restricted set, not only the satisfied clauses of Σ are omitted, but also the binary clauses of Σ considered at start (as in sharpSAT) and, more generally, every input clause which has not been shortened by the current vari- able assignment. We prove the correction of the caching scheme. We also present a new cache cleaning strategy that refines the one used in sharpSAT, and takes account for the ages of the entries, with dynamic resets to reflect their activities, and but also for the proportion of entries of the same size that led to positive hits (so as to try and keep in the cache the most promising entries). Finally, the results of an empirical evaluation are reported, showing the caching scheme and the cleaning strategy presented in the paper as valuable for the model counting task when achieved by the compilation-based counter D4 [3].

The rest of the paper is organized as follows. In Section 2, one starts with some formal preliminaries. In Section 3, our caching scheme is presented and proved correct. In Section 4, our cache cleaning strategy is described. In Section 5, some empirical results are provided. Finally, Section 6 concludes the paper.

2 Formal Preliminaries

We consider a propositional language L PS defined in the usual way from a finite set PS = {x 1 , . . . , x n } of propositional symbols and the standard connectives.

One assumes a preset, strict and total ordering < over PS: x 1 < x 2 < . . . <

x n−1 < x n .

3

www.cs.rochester.edu/∼kautz/Cachet/index.htm

4

sites.google.com/site/marcthurley/sharpsat

5

reasoning.cs.ucla.edu/c2d/

6

www.haz.ca/research/dsharp/

7

www.cril.fr/kc/

(4)

Formulae from L PS are interpreted in a classical way. A formula is consistent when it has a model, i.e., a variable assignment that makes it true. Two formulae are equivalent when they have the same models. ≡ denotes logical equivalence.

For every formula Σ in L PS , Var(Σ) is the set of propositional variables occurring in Σ. kΣk denotes the number of models over Var(Σ). |Σ| denotes the size of Σ.

A literal ` is either a propositional variable or a negated one. For every literal

`, var(`) denotes the variable x of ` (var(x) = x and var (¬x) = x). ` denotes the complementary literal of ` (i.e., for every variable x, x = ¬x and ¬x = x).

A clause is a finite disjunction of literals, and a term is a finite conjunction of literals. A CNF formula Σ is a finite conjunction of clauses. Every CNF is viewed as a set of clauses, and every clause is viewed as a set of literals. A clause is valid (tautologous) when it contains complementary literals. A subclause of a clause δ corresponds to a subset of the literals occurring in δ.

The set of canonical clauses of a formula ϕ consists of all the clauses δ implied by ϕ which are such that every variable of PS appears once in each δ; it is in normal form when the clauses are listed in increasing order w.r.t.

the lexicographic ordering induced by the literal ordering x 1 < ¬x 1 < x 2 <

¬x 2 < . . . < x n−1 < ¬x n−1 < x n < ¬x n when the variable ordering is such that x 1 < x 2 < . . . < x n−1 < x n . For instance, if PS = {x 1 , x 2 , x 3 }, and ϕ = (x 1 ∨ x 2 ) ∧ (¬x 2 ∨ x 3 ), the set of canonical clauses of ϕ in normal form is the ordered set {x 1 ∨ x 2 ∨ x 3 , x 1 ∨ x 2 ∨ ¬x 3 , x 1 ∨ ¬x 2 ∨ x 3 , ¬x 1 ∨ ¬x 2 ∨ x 3 }. The canonical clauses of ϕ correspond in a bijective way (up to a negation) to the counter-models of ϕ, i.e., the variable assignments that make it false. Clearly enough, two equivalent formulae of L PS have the same set of canonical clauses in normal form.

A term is consistent when it does not contain complementary literals. The conditioning of a CNF formula ϕ by a consistent term γ is the CNF formula ϕ | γ obtained by removing from ϕ every clause containing a literal of γ and removing from the remaining clauses every occurrence of every ` when ` is a literal of γ.

For instance, if ϕ = (x 1 ∨x 2 )∧(¬x 2 ∨x 3 ) and γ = ¬x 1 , then ϕ | γ = x 2 ∧(¬x 2 ∨x 3 ).

BCP denotes a Boolean Constraint Propagator [8, 4], which is a key component of many solvers. BCP(ϕ) returns {∅} if there exists a unit refutation from the clauses of the CNF formula ϕ, and it returns the set of literals (unit clauses) which are derived from ϕ using unit propagation in the remaining case. For instance, if ϕ = (x 1 ∨ x 2 ) ∧ (¬x 2 ∨ x 3 ), then BCP(ϕ ∧ ¬x 1 ) = {¬x 1 , x 2 , x 3 }.

For efficiency reasons, the propagation is not “physically” performed on the CNF (instead the set of literals derived using unit propagation is maintained). On the previous example, ϕ ∧ ¬x 1 is simplified into the empty set of clauses once BCP has been applied on it.

The primal graph of a CNF formula ϕ is the (undirected) graph (V, E) where

the vertices in V correspond to the variables of ϕ and an edge of E (i.e., a couple

of vertices) connecting two variables exists whenever one can find a clause of ϕ

where both variables occur. Every connected component of this graph (i.e., a

maximal subset of vertices which are pairwise connected by a path) corresponds

(5)

to a subset of clauses of ϕ, referred to as a connected component of the for- mula ϕ. For instance, the primal graph of (x 1 ∨ x 2 ) ∧ (¬x 2 ∨ x 3 ) is the graph ({x 1 , x 2 , x 3 }, {{x 1 , x 2 }, {x 2 , x 3 }). Since this graph has a single connected com- ponent {x 1 , x 2 , x 3 }, the formula has a single connected component (the set of all its clauses).

3 An Improved Caching Scheme

In the following, we assume without loss of generality that the input CNF formula Σ does not contain any valid clauses and any unit clauses (a polynomial-time preprocessing consisting of detecting and removing valid clauses, then applying BCP on the resulting set of clauses can be used to ensure that this condition is always satisfied).

As evoked in the introduction, model counters and top-down Decision-DNNF compilers consist of search procedures that decompose recursively the input for- mula Σ by assigning variables in it and identifying independent components.

Each time a variable is assigned in the current CNF formula ϕ considered dur- ing search, BCP is run so as to possibly simplify further the current formula ϕ through the assignment of additional variables. Thus, the current variable as- signment is completed and ϕ is simplified. Whenever the clauses of ϕ can be partitioned into (at least) two disjoint components ϕ 1 and ϕ 2 , the two CNF for- mulae ϕ 1 and ϕ 2 can be processed independently (ϕ ≡ ϕ 1 ∧ ϕ 2 is such that kϕk = kϕ 1 k × kϕ 2 k and a Decision-DNNF representation of ϕ can be obtained by conjoining a Decision-DNNF representation of ϕ 1 and a Decision-DNNF represen- tation of ϕ 2 using a decomposable ∧-node).

Every CNF formula ϕ encountered during search corresponds to a subset of the clauses of Σ, some of them being shortened through its conditioning by the current variable assignment γ once augmented by BCP. Thus, all the clauses of Σ satisfied by γ are not in the subset of clauses representing ϕ, as well as those con- taining at least one variable not in the set of variables of the current component.

In the remaining clauses of Σ, literals that are complementary to literals occur- ring in γ can be removed (the corresponding clauses of Σ are shortened), leading to the clauses of ϕ. Thus, when the input is a CNF formula Σ, the CNF formulae ϕ that are encountered during search (which are the candidates to be added into the cache when they are not already in) are elements of S(Σ) = {δ 0 ⊆ δ | δ ∈ Σ}.

What’s in a caching scheme? Formally, a caching scheme c is a mapping

associating with any ϕ ∈ S(Σ) for some CNF formula Σ a representation r c (ϕ) of

ϕ (this representation can be any data structure). A cache for Σ given a caching

scheme c is a mapping associating with representations r c (ϕ) of CNF formulae

ϕ ∈ S(Σ) their number of models kϕk (or Decision-DNNF representations of those

ϕ). As expected, the size of a cache given a caching scheme c is the sum for each

entry of the size of the representation r c (ϕ) stored in it plus the size of the corre-

sponding model count (kϕk (in binary notation) or the size of the Decision-DNNF

representation of ϕ associated with r c (ϕ)). Any ϕ 1 ∈ S(Σ) is considered to be

(6)

stored in the cache whenever one can find in the cache an entry r c2 ) such that r c1 ) = r c2 ) holds. A correct caching scheme c is a caching scheme such that for any CNF formula Σ, ϕ 1 , ϕ 2 ∈ S(Σ), if r c1 ) = r c2 ) then ϕ 1 ≡ ϕ 2 . Stated otherwise, when the representations of ϕ 1 and ϕ 2 coincide, then the two CNF formulae ϕ 1 and ϕ 2 are equivalent. Because the equality of two representations ϕ 1 and ϕ 2 given a caching scheme c is syntactic, it can be achieved efficiently, i.e., in time linear in the size of r c (ϕ 1 ) plus the size of r c (ϕ 2 ). When the caching scheme is correct, this equality relation can be viewed as a lower approximation of the equivalence relation between CNF formulae. Obviously enough, considering logical equivalence between CNF formulae would lead to the best possible lookup operation (if a CNF formula equivalent to a given ϕ has already been added to the cache, then it will be found for sure), but this is no feasible in practice (one has to keep in mind that the lookup operation is to be achieved for each ϕ en- countered during search, so for exponentially many formulae in the general case;

given that full equivalence testing is a coNP-complete problem, solving exponen- tially many instances of a coNP-complete problem would be too demanding).

For the same reason, one typically requires the representation mapping r c to be computable in polynomial time (observe that, without this assumption, full equivalence testing could be simulated by representing every CNF formula ϕ by its set of canonical clauses written in normal form, which is exponentially larger than |ϕ| in the general case).

Because of the syntactic nature of the approximate equivalence test, the per- formance of a caching scheme depends only on two key factors: the cumulated sizes of the entries and the quality of the approximation of equivalence that is achieved. Indeed, the cumulated sizes of the entries give the size of the cache, which is the most memory-demanding ingredient of a model counter / top-down Decision-DNNF compiler. The sizes of the entries also have a direct impact on the efficiency of the model counter / top-down Decision-DNNF compiler in term of computation time (just because the times required to write entries into the cache or for the lookup operation depends directly on the sizes of the entries).

The quality of the approximation of equivalence that is achieved also has a great influence on the performance of a caching scheme. A first caching scheme asso- ciated with codes that are smaller than the codes of a second caching scheme cannot be considered as better when the equivalence relation over the represen- tations associated with the first scheme is finer than the equivalence relation over the representations associated with the second scheme. Indeed, the time overhead that results from using the second scheme (with larger codes) can be balanced by the fact that it may avoid counting the models (or compiling) several times the same CNF formulae (which are not recognized as keys of the cache when the first scheme is used). If this was not the case, in the limit, not implementing any cache – the n “no cache” scheme – would be the best strategy).

Some previous caching schemes. Let us now present some caching schemes

introduced so far. We assume that unit clauses (even those obtained using BCP)

are not represented in the cache (there is no need of doing so).

(7)

In the standard caching scheme s 8 ), every CNF formula ϕ encountered during search is represented as a string gathering the identifiers (integers) of the literals of the clauses in it, separating the clauses by zeroes. The identifier of a positive literal x i is its index i in the enumeration x 1 < x 2 < . . . < x n−1 < x n , and the identifier of a negative literal ¬x i is −i.

In the hybrid caching scheme h considered in sharpSAT, the clauses of the input CNF formula Σ are indexed in an arbitrary way (the index of the first clause of Σ is 1, the index of the second clause of Σ is 2, etc.). Every CNF formula ϕ encountered during search is represented as a pair consisting of the set of indexes of the variables occurring in ϕ (again, the identifier of x i is i) in ascending order, and the set of indexes of the clauses of Σ that are “still alive” (non satisfied) and containing at least two unassigned literals), in ascending order. A variant of h, called o, consists in omitting in the set of indexes of the clauses every index of a binary clause. Indeed, as shown in [7], this set is redundant since it can be reconstructed knowing the indexes of the literals occurring in it. This leads to smaller sizes of the codes, hence to a more efficient cache management.

Let us illustrate those three caching schemes on a simple example. Let Σ = (x 1 ∨ x 2 ∨ x 4 ) ∧ (x 2 ∨ x 3 ∨ x 4 ) ∧ (x 3 ∨ x 4 ∨ x 5 ) ∧ (x 1 ∨ ¬x 6 ) be a CNF formula. Let γ = x 2 , and let ϕ be the unique component of Σ | γ simplified using BCP. We have ϕ = (x 3 ∨ x 4 ∨ x 5 ) ∧ (x 1 ∨ ¬x 6 ). This formula ϕ is represented by the string r s (ϕ) = 3, 4, 5, 0, 1, −6, 0 using the standard caching scheme. It is represented by r h (ϕ) = ({1, 3, 4, 5, 6}, {3, 4}) using the hybrid caching scheme. It is represented by r o (ϕ) = ({1, 3, 4, 5, 6}, {3}) using the variant of the hybrid caching scheme where indexes of binary clauses are omitted.

For the sake of code conciseness, indexes are typically compressed, i.e., rep- resented using as few bits as possible (and not using a fixed format for integers).

The o scheme with such a code compression is referred to as the p scheme in [7]

(”p” stands for ”packing”).

Clearly enough, representing clauses by their indexes in Σ (as with the h scheme, the o scheme or the p scheme) is more efficient in term of encoding sizes than representing them explicitly (as with the s scheme). However, explicitly representing the clauses leads to a finer equivalence relation between the clause sets. Thus, stepping back to the previous example, and considering two terms γ 1 = ¬x 1 ∧x 3 and γ 2 = x 1 ∧¬x 3 ∧x 5 , one can observe that Σ | γ 1 is equivalent to Σ | γ 2 (the resulting CNF consists of the single clause x 2 ∨ x 4 ). Σ | γ 1 and Σ | γ 2

share the same r s representation: 2, 4, 0. Contrastingly, we have r h (Σ | γ 1 ) = ({x 2 , x 4 }, {1}) while r h (Σ | γ 2 ) = ({x 2 , x 4 }, {2}). Thus, Σ | γ 1 is not viewed as equivalent to Σ | γ 2 when the scheme h is used (the same problem happens with o and p).

Our caching scheme i and its family. Let us now introduce the caching scheme denoted by i (”i” insists on the fact that, compared to the standard

8

According to [7], it is the one used in Cachet ([6] do not make it precise).

(8)

scheme, some clauses of the input formula Σ are handled implicitly, i.e., they are not represented as parts of the entries of the cache for Σ). It is the caching scheme implemented (by default) in D4, but to the best of our knowledge, it has not been described so far in any paper (especially, it is not presented in [3]). Since i appears empirically as quite a good scheme in comparison to previous caching schemes (see Section 5), we believe that it makes sense to specify it so as to be in position to take advantage of it in other model counters and Decision-DNNF compilers.

Let us present i in a smooth way by starting with a basic caching scheme b, which is such that for any CNF formula Σ and any ϕ ∈ S(Σ), r b (ϕ) = (V, C) where V is the set of indexes of variables of Var(ϕ) ordered in ascending way and C is the set of residual clauses of ϕ given Σ (the clauses which are not satisfied by the assignment corresponding to ϕ). With b, C is sorted by increasing clause size first, and within each cluster of clause representations having the same size, the indexes of the literals of each clause are listed in increasing order w.r.t. the lexicographic ordering induced by the literal ordering x 1 < ¬x 1 < x 2 < ¬x 2 <

. . . < x n−1 < ¬x n−1 < x n < ¬x n when the variable ordering is such that x 1 < x 2 < . . . < x n−1 < x n . Multi-occurrent clauses are removed (only one occurrence per clause is kept).

When the basic caching scheme b is used, the residual clauses are represented in an explicit way, as in the s scheme and not using indexes (unlike the schemes h, o, p presented above), but they are ordered in such a way that two sets of residual clauses that differ only as to the ordering of the clauses and/or as to the ordering of literals within clauses will have the same representation C (this ordering is maintained dynamically). The indexes used for representing clauses in C also use as few bits as possible, as in the p scheme.

A variant of b, noted 2, is obtained by avoiding to store the binary clauses as with o. What makes i different of b also is the notion of residual clause under consideration. With the i caching scheme, not only the binary clauses of Σ are not stored, but every clause of ϕ that is not shortened by the corresponding variable assignment is not represented as well. Finally, with the variant i 0 of i, one considers the same set of residual clauses as in i, but represents those clauses using indexes as in the h scheme.

Considering the previous example again, let ϕ be the unique component of Σ | ¬x 2 . We have ϕ = (x 1 ∨ x 4 ) ∧ (x 3 ∨ x 4 ) ∧ (x 3 ∨ x 4 ∨ x 5 ) ∧ (x 1 ∨ ¬x 6 ). This formula ϕ is represented by:

– r b (ϕ) = ({1, 3, 4, 5, 6}, {{1, 4}, {1, −6}, {3, 4}, {3, 4, 5}}), – r 2 (ϕ) = ({1, 3, 4, 5, 6}, {{1, 4}, {3, 4}, {3, 4, 5}}),

– r i (ϕ) = ({1, 3, 4, 5, 6}, {{1, 4}, {3, 4}}).

– r i

0

(ϕ) = ({1, 3, 4, 5, 6}, {1, 2}).

Thus, no representation of any of the two clauses x 3 ∨ x 4 ∨ x 5 and x 1 ∨ ¬x 6 is stored when i or i 0 is considered.

Interestingly, refraining from storing the clauses of Σ that have not been

shortened does not question the correctness of the approach, whatever clauses

are represented explicitly (by the literals in them) or implicitly (by their indexes):

(9)

Proposition 1. The caching schemes i and i 0 are correct.

Proof.

– Caching scheme i. In order to show that i is correct, it is enough to prove that for any CNF Σ and any ϕ ∈ S(Σ), ϕ is fully determined by r i (ϕ) = (V, C) given Σ. The proof is constructive: it consists in considering every clause δ of Σ and to decide using r i (ϕ) whether δ (or in some case, a subclause of it) belongs to ϕ. The first case is when Var (δ) ∩ V = ∅. In this case, δ does not belong to the component ϕ. In the remaining case, there are two possibilities:

(1) either Var(δ) ⊆ V or (2) Var(δ) \ V = ∅. In case (1), we conclude that δ belongs to ϕ (even if it is not represented explicitly in C). In case (2), there are still two possibilities: if there exists no clause δ 0 represented in C such that Var(δ 0 ) ⊆ V and δ 0 is a subclause of δ, then δ does not belong to the component ϕ (it is satisfied by the current variable assignment), else δ 0 belongs to ϕ (δ or another clause of Σ has been shortened to give rise to δ 0 ).

– Caching scheme i 0 . In order to show that i 0 is correct, one can use the same approach as for i. The only difference concerns case (2). In this case, if the index of δ belongs to the C part of r i

0

(ϕ), then the subclause of δ containing only its literals over variables in the V part belongs to ϕ, else δ does not belong to ϕ (it is satisfied by the current variable assignment).

4 An Improved Cache Cleaning Strategy

As evoked previously, on hard formulas the cache size quickly exceeds any rea- sonable bound, which necessitates a good cache management, especially a good approach to cache cleaning.

What is a cache cleaning strategy? A cache cleaning strategy must make precise the entries that have to be removed from the cache and an agenda for the cleaning operations (i.e., the cleaning operations can be achieved periodically, or be triggered by some events like the number of entries or the fact that the quantity of memory that is available falls down a preset threshold).

Some previous cache cleaning strategies. Observing that the utility of the cached components typically declines dramatically with age, in Cachet [6] each cached component is given a sequence number and those components that are too old are removed from the cache (the age limit is considered as an input parameter). For efficiency reasons, age checking is not done frequently; when a new component is cached, age checking is achieved on the chain that contains the newly cached component. The cache is cleared whenever the number of entries exceeds 2 21 × 10 and only 25% of the entries are kept whenever a cleaning operation takes place.

In sharpSAT [7], the entries to be cleaned up do not depend only on their ages

(i.e., the first time they are encountered), but also on their activity levels and on

(10)

their sizes. A score score(e) is associated with each entry e. At start, score (e) is given by the age of the entry but it is reset during the search each time a positive hit corresponding to the entry is obtained. All scores are divided periodically so as to penalize the oldest entries. The cache is cleared only if its size exceeds a fixed fraction of the maximal allowed size (another input parameter). Entries are considered by increasing scores and removed from the cache until a sufficient amount of space (e.g., half of the maximal allowed size) has been recovered.

Our new cache cleaning strategy. With each entry e in the cache we asso- ciate an integer value score(e) as in sharpSAT, together with a Boolean value flag (e) that is set to true once the entry hits positively. Each time a cache hit occurs on an entry e, score(e) is reset and flag(e) is set to true. Moreover, we also store information about how many entries nbTotal[s] of any given size s the cache data structure contains, as well as how many entries nbHit[s] of size s have their flag variable set to true. Here, the size of an entry is measured as the number of variables in it.

Each time tc new entries have been added to the cache (where tc is a param- eter of the strategy), some cleaning is performed. All the entries of the cache are visited in order to decide the ones that must be removed. Contrary to sharpSAT, our cleaning strategy does not remove half of the entries in a systematic way, and the cleaning operations are not triggered by how filled the cache is. For each entry e, the ratio

r(e) = nbHit [|Var(e)|]

nbTotal[|Var(e)|]

is computed. For each entry size, during the search, this ratio evaluates the proportion of entries of this size having led to a positive hit. In our cache cleaning strategy, entries with a high ratio r(e) are promoted. Indeed, we have observed empirically that along the search, entries e with a high ratio r(e) are often the most promising ones, i.e., if entries of the same size led to many positive hits, it is likely that e will also lead to some positive hits (this observation can be explained by the presence of variables playing symmetric roles in the instances). Thus, as a rule of thumb, it makes sense to give a bonus to such entries. Accordingly, in our cache cleaning strategy, every entry e that has a ratio r(e) less that some fixed threshold rm (another parameter), with a score (e) equals to zero and a flag (e) set to false is flushed. The other entries e are kept and their score (e) are divided by two. Whenever score (e) falls to zero, flag (e) is set to false.

5 Empirical Evaluation

In order to evaluate the performance of the caching schemes and of the cache cleaning strategies, we performed a number of experiments.

Setting. All the experiments have been conducted on a cluster equipped with

quadcore bi-processors Intel XEON E5-5637 v4 (3.5 GHz) and 128 GiB of mem-

ory. The kernel used was CentOS 7, Linux version 3.10.0-514.16.1.el7.x86 64.

(11)

The compiler used was gcc version 5.3.1. A time-out of 1h and a memory-out of 7.6 GiB has been considered for each instance.

We have considered 703 CNF instances from the sat LIBrary, 9 and other repositories (for instance, the benchmarks from the BN family (Bayesian net- works) come from http://reasoning.cs.ucla.edu/ace/). We removed from them all those instances which are easy enough to be solved by the compilation-based counter D4 in less that 3600s without using any caching technique. We retained only 225 instances. These instances are gathered in 8 datasets, as follows: BN (82), bmc (8), Circuit (12), Configuration (22), Handmade (6), Planning (85), Random (5), Qif (3), Scheduling (2). The number of variables (resp. clauses) in those “hard” instances vary in [100, 119003] (resp. [150, 386342]) with an average value equal to 3314(±10304) (resp. 13904(±43864)).

Name Explicit / Implicit All residual clauses Not binary Not shortened

n - - - -

b E X

2 E X

i E X

h

0

I X

p I X

i

0

I X

Table 1: Seven caching schemes considered in the paper.

D4 has been used in the model counter mode: when invoked with option -mc, D4 explores the same search space as the one considered when it is used as a Decision-DNNF compiler, but stores in its cache model counts instead of Decision- DNNF representations [3]. The branching heuristic that has been exploited is the one based on dynamic decomposition (DECOMP) used by default in D4 (see [3]

for details).

We have considered several caching schemes, namely n, b, 2, i, as well as h 0 , the variant of h where indexes are compressed, p, and i 0 . The features charac- terizing those schemes are summarized in Table 1. “(E)xplicit/(I)mplicit” makes precise whether residual clauses are represented explicitly (by their literals) in the scheme, or implicitly (by their indexes). When “All residual clauses” is ac- tivated, every residual clause is stored. When “Not binary” is activated, the binary clauses of Σ are not stored. Finally, when “Not shortened” is activated, the binary clauses of Σ and the clauses of Σ that have not been shortened are not stored. The hash function used in the implementation of the cache is MurMurHash2 (see https://en.wikipedia.org/wiki/MurmurHash).

We have also considered several cache cleaning strategies: no cache cleaning, the strategy used by Cachet, the one used by sharpSAT, and our own strategy.

9

www.cs.ubc.ca/∼hoos/SATLIB/index-ubc.html

(12)

The parameters used in the strategy implemented in Cachet and the ones used by sharpSAT were set to their default values. tc was set to 2 18 and rm to 1 2 .

For each combination caching scheme/cache cleaning strategy and each bench- mark, the performance of D4 has been assessed by measuring the model counting time, and the memory consumed by D4.

Results. Table 2 makes precise for each combination caching scheme / cache cleaning strategy, some empirical data of the form x(y) where x is the number of instances solved (out of 225) and y the number of memory-out that occurred.

The leftmost column (n) corresponds to the cases when no caching takes place.

The last three columns (b, 2, i) correspond to schemes for which residual clauses are represented by their literals (the difference between the three schemes lying in the sets of clauses explicitly represented, which by construction are never increasing w.r.t. ⊆ when switching from b to 2, and from 2 to i). The three remaining columns (h 0 , p, i 0 ) correspond respectively to b, 2, i in term of the clauses which are represented, but for any of those three schemes, clauses are represented implicitly by their indexes.

Cache cleaning strategy n h

0

p i

0

b 2 i

No cleaning 116(0) 162(62) 164(51) 169(44) 152(69) 167(51) 171(47) Cachet cleaning 116(0) 169(16) 170(11) 173(5) 157(26) 173(10) 177(6) sharpSAT cleaning 116(0) 167(16) 167(16) 171(11) 166(52) 173(11) 174(10)

Our own cleaning 116(0) 170(20) 172(10) 175(4) 164(31) 173(17) 179(6) Table 2: Number of instances solved by D4 and number of memory-out reached for several combinations of caching scheme / cache cleaning strategy.

In Table 2, the largest numbers of instances solved for each caching scheme

are boldfaced, and the largest numbers of instances solved for each cache clean-

ing strategy are reported in lilac cells. One can observe that the lighter codes

obtained by considering i (when compared to b and 2) permit to solve more in-

stances. Indeed, whatever the cache cleaning strategy used, the caching scheme

i dominates each other scheme as to the numbers of instances solved. The other

way around, our new cache cleaning strategy appears as the best cleaning strat-

egy most of the time, whatever the caching scheme under consideration. The sin-

gle exception concerns the caching scheme b (for this scheme, the cache cleaning

strategy used by sharpSAT led to solve two additional instances). The underlying

principle (trying to learn what are the most promising entries) looks quite useful

in this respect. Especially, it can be observed that our new cache cleaning strat-

egy performs not bad in term of the numbers of memory-outs that are obtained

(in particular when it is coupled to i or i 0 ), despite the fact that the amount of

available memory is not exploited in this strategy, while cleaning operations are

triggered by the number of entries / amount of available memory in Cachet /

sharpSAT. Empirically, the best combination turns out to be i together with the

(13)

new cleaning strategy. Interestingly enough, this combination corresponds in our experiments to the virtual best solver (VBS): every instance solved by another combination has been solved as well by i and the new cleaning strategy.

In order to better figure out the savings (in terms of time and memory) which are feasible thanks to the various caching schemes and cleaning strategies considered in the paper, we have pairwise compared all the 28 combinations (7 caching schemes, 4 cache cleaning strategies) and drawn all the scatter plots corresponding to those comparisons. A selection of them is presented in the following. 10 In those plots, each dot represents an instance; each coordinate represents either the time (in seconds) needed to solve it or the memory used (in MiB) by D4 (provided that the computation terminated normally).

The scatter plots reported in Figure 1 shows the time/space trade-off achieved when D4 is used as a model counter and the scheme i is used vs. no caching is done (the n scheme). In both cases, no cache cleaning has been performed. On the one hand, Figure 1a clearly shows (as expected) that taking advantage of a cache usually leads to huge improvements in terms of solving times. On the other hand, Figure 1b shows that these benefits in terms of computation times are possible only if a sufficient amount of memory is available.

500 1000 1500 2000 2500 3000 3500 4000

500 1000 1500 2000 2500 3000 3500 4000

no cache

i + no cleaning

(a) i vs. n: time

500 1000 1500 2000 2500 3000 3500 4000

500 1000 1500 2000 2500 3000 3500 4000

no cache

i + no cleaning

(b) i vs. n: memory

Fig. 1: Computation times and memory consumptions of D4 equipped with the caching scheme i with the computation times of D4 when no caching is done. No cache cleaning.

The scatter plots reported in Figure 2 are useful to compare in term of compu- tation time / memory consumption the “explicit” caching schemes (b, 2, i) to the corresponding “implicit” caching schemes (h 0 , p, i 0 , respectively). Again, no cache cleaning took place. As expected, each “explicit” caching scheme proves better than the corresponding “implicit” caching scheme as to computation times, pro- vided that all clauses are not stored (indeed, their numbers have an impact not only on the memory used but also on the times needed to perform the cache

10

Due to space limitations, one cannot report all of them in the paper; the full set of

plots can be downloaded on https://miniurl.be/r-31qh.

(14)

500 1000 1500 2000 2500 3000 3500 4000

500 1000 1500 2000 2500 3000 3500 4000

h’ + no cleaning

b + no cleaning

(a) b vs. h

0

: time

500 1000 1500 2000 2500 3000 3500 4000

500 1000 1500 2000 2500 3000 3500 4000

p + no cleaning

2 + no cleaning

(b) 2 vs. p: time

500 1000 1500 2000 2500 3000 3500 4000

500 1000 1500 2000 2500 3000 3500 4000

i’ + no cleaning

i + no cleaning

(c) i vs. i

0

: time

500 1000 1500 2000 2500 3000 3500 4000

500 1000 1500 2000 2500 3000 3500 4000

h’ + no cleaning

b + no cleaning

(d) b vs. h

0

: memory

500 1000 1500 2000 2500 3000 3500 4000

500 1000 1500 2000 2500 3000 3500 4000

p + no cleaning

2 + no cleaning

(e) 2 vs. p: memory

500 1000 1500 2000 2500 3000 3500 4000

500 1000 1500 2000 2500 3000 3500 4000

i’ + no cleaning

i + no cleaning

(f) i vs. i

0

: memory

Fig. 2: Comparing the computation times and memory consumptions of D4

equipped with “explicit” caching schemes vs. “implicit” caching schemes. No

cache cleaning.

(15)

operations), but it proves often worse in term of amount of memory used (just compare the numbers of dots above / below the diagonal).

The scatter plots reported in Figure 3 enable a pairwise comparison in term of computation times of the best “explicit” scheme i with the two other “explicit”

caching schemes (b, 2) on the one hand, and of the best “implicit” scheme i 0 with the two other “implicit” caching schemes (h 0 , p) on the other hand. Again, no cache cleaning took place. These plots show that i (resp. i 0 ) performs better than b, 2 (resp. h 0 , p). This can be explained by the fact that they are associated with smaller codes (less clauses are stored in the cache).

500 1000 1500 2000 2500 3000 3500 4000

500 1000 1500 2000 2500 3000 3500 4000

b + no cleaning

i + no cleaning

(a) i vs. b: time

500 1000 1500 2000 2500 3000 3500 4000

500 1000 1500 2000 2500 3000 3500 4000

2 + no cleaning

i + no cleaning

(b) i vs. 2: time

500 1000 1500 2000 2500 3000 3500 4000

500 1000 1500 2000 2500 3000 3500 4000

h’ + no cleaning

i’ + no cleaning

(c) i

0

vs. h

0

: time

500 1000 1500 2000 2500 3000 3500 4000

500 1000 1500 2000 2500 3000 3500 4000

p + no cleaning

i’ + no cleaning

(d) i

0

vs. p: time

Fig. 3: Comparing the computation times of D4 equipped with i (resp. i 0 ) with those obtained when using other “explicit” (resp. “implicit”) caching schemes.

No cache cleaning.

Finally, the scatter plots reported in Figure 4 enables to compare the com-

putation times of D4 when the best cache cleaning strategy (our own strategy)

has been used, with those obtained by D4 when the cleaning strategy of Cachet

or of sharpSAT was used instead. Here, the caching scheme used was the best

performer (i). Clearly enough, as Table 2 already pointed it out, using the new

cache cleaning strategy leads to solve more instances.

(16)

500 1000 1500 2000 2500 3000 3500 4000

500 1000 1500 2000 2500 3000 3500 4000

i + Cachet cleaning

i + our own cleaning

(a) Our strategy vs. Cachet: time

500 1000 1500 2000 2500 3000 3500 4000

500 1000 1500 2000 2500 3000 3500 4000

i + sharpSAT cleaning

i + our own cleaning

(b) Our strategy vs. sharpSAT: time Fig. 4: Comparing the computation times of D4 equipped with our new cleaning strategy with those obtained when using the cleaning strategy of Cachet or the one of sharpSAT. The cache scheme used is i.

6 Conclusion

We have presented an improved caching scheme that can be exploited for model counting or the Decision-DNNF compilation of CNF formulae Σ. We proved the correctness of this scheme i and of the corresponding scheme i 0 obtained by con- sidering implicit representations of clauses by indexes. We have also presented an improved cache cleaning strategy, which elaborates on the one used in sharpSAT, and takes account for the ages, activities, and on the proportion of entries of the same size that led to positive hits in order to decide which entries should be kept and which ones should be flushed. We have reported the results of an empirical evaluation showing the i scheme and the new cleaning strategy as useful for model counting when compared to caching schemes and cleaning strategies used in state-of-the-art #sat solvers. In light of our experiments, i associated with the new caching strategy is the best combination among those which have been considered. This combination corresponds empirically to the virtual best solver.

The performance of i compared to the one of p, as illustrated by the empirical results that have been obtained and are reported above, is one of the factors explaining why D4 challenges Dsharp, the Decision-DNNF compiler associated with sharpSAT (see [3] for an empirical comparison of D4 and Dsharp). Interestingly, the caching scheme i and the new cleaning strategy are not dedicated to D4 but can be used as well in other #sat solvers and compilers which are based on other branching rules. Especially, it can be noted that the implementation of D4 as presented in [3] does not exploit any cache cleaning strategy, hence our new cleaning strategy can be leveraged to give rise to an improved release of D4.

As a perspective for further research, we plan to define and evaluate “mixed”

caching schemes, i.e., schemes for which both explicit and implicit representa-

tions of clauses can be considered. The choice for an explicit vs. implicit repre-

sentation of a clause may depend on the size of the clause under consideration

and may change during search (depending on the number of hits for the corre-

sponding entry).

(17)

References

1. Darwiche, A.: Decomposable negation normal form. Journal of the ACM 48(4), 608–647 (2001)

2. Darwiche, A.: New advances in compiling CNF into decomposable negation normal form. In: Proc. of ECAI’04. pp. 328–332 (2004)

3. Lagniez, J.M., Marquis, P.: An Improved Decision-DNNF Compiler. In: Proc. of IJCAI’17. pp. 667–673 (2017)

4. Moskewicz, M., Madigan, C., Zhao, Y., Zhang, L., Malik, S.: Chaff: Engineering an efficient SAT solver. In: Proc. of DAC’01. pp. 530–535 (2001)

5. Muise, C., McIlraith, S., Beck, J., Hsu, E.: Dsharp: Fast d-DNNF compilation with sharpSAT. In: Proc. of AI’12. pp. 356–361 (2012)

6. Sang, T., Bacchus, F., Beame, P., Kautz, H., Pitassi, T.: Combining component caching and clause learning for effective model counting. In: Proc. of SAT’04 (2004) 7. Thurley, M.: sharpSAT - counting models with advanced component caching and

implicit BCP. In: Proc. of SAT’06. pp. 424–429 (2006)

8. Zhang, H., Stickel, M.E.: An efficient algorithm for unit propagation. In: Proc. of

ISAIM’96. pp. 166–169 (1996)

Références

Documents relatifs

In this paper we offer several models of reference sequences (traces of references) using Markov chains for testing of the replacement policies in caching systems.. These models

This popularity evolution is typical for a catch-up television service as studied in this paper (see [1]). Each video has its own popularity decay curve that follows

We use the lagrangian relaxation dualizing the assignment constraints (2) outlined in the previous section to compute the initial lower bound, and also to compute the lower bounds

Pre-computation constructs expressions for verification from a system model described in discrete time Markov chain (DTMC) model [9], which associates state transitions

On the other hand and as a counterpart to the uniqueness question studied in Theorem 5, the fact that q achieves values less than one in Ω allows the existence of solutions u of

Independent variables and possible confounders identified through the literature and theoretical reasoning were broken down into four categories: socio-demographic

We proposed a multilevel probabilistic model, the Poisson regressor based on a Gaussian process, that can exploit the content features and provide accurate popularity estimation.

c) Cache Manager: periodically computes the ideal cache configuration (i.e., what objects should be cached and how many chunks for each) based on object popularity statis- tics from