Abstract 1 Introduction 2 Preliminaries 3 Relational Circuits 4 Algorithms for Building Circuits 5 Fine-grained consequences References

Building Relational Circuits

Florent Capelli ORCID Univ. Artois, CNRS, UMR 8188, Centre de Recherche en Informatique de Lens (CRIL), F-62300 Lens, France
Abstract

We review two algorithms which allow to build a factorized representation of the answers set of join queries. In a nutshell, the representation builds a circuit representing the answers set of a join query by starting from atomic relations and iteratively combine them by either constructing the Cartesian product or the disjoint union of previously computed relations. The first one can be seen as the trace of the celebrated Yannakakis algorithm, building the answer set from the inputs to the output of the circuit while the second adopts a top-down approach which can be seen as a generalization of the exhaustive DPLL algorithm, originally designed to solve the #SAT problem.

Keywords and phrases:
Conjunctive queries, factorized databases, knowledge compilation
Category:
Invited Talk
Copyright and License:
[Uncaptioned image] © Florent Capelli; licensed under Creative Commons License CC-BY 4.0
2012 ACM Subject Classification:
Information systems Relational database model
Funding:
This work was supported by KCODA project, ANR-20-CE48-0004.
Supplementary Material:
InteractiveResource: https://florent.capelli.me/algorithms/dpll/
Editors:
Balder ten Cate and Maurice Funk

1 Introduction

From the seminal paper by Codd [19], it has been quite clear that organizing data as relations is a powerful abstraction, leading to a clear and intuitive separation of the data itself, its structure and how it can be queried. In a way, a query can be seen as a succinct way of specifying a relation. Yet, this succinctness comes at the price of making the relation harder to manipulate and most of the time, one ends up materializing it, which can be costly [18], before using the results. A notorious result by Yannkakis identified a class of queries for which this materialization was not necessary to decide whether the query has at least one answer, namely, the class of acyclic queries [50] (called acyclic scheme in the original paper), a large body of work has focused on finding other tractable tasks that can be efficiently solved on acyclic join queries, beyond simply deciding whether it has at least one answer. For example, it has been observed that one can efficiently enumerate the answers of an acyclic join query [7], compute their number [44], aggregates the answer over different semirings [1, 31] etc. Following the line of research on factorized databases [42, 43, 40] having its root in the field of knowledge compilation [23, 40] which focuses on efficient representations of knowledge bases, we argue in this paper that this tractability can be seen as the fact that the answer sets of acyclic queries can be efficiently represented in a factorized, yet tractable data structure, namely, a relational circuit.

This paper contains notes related to my invited ICDT lecture. It aims at giving an introduction to relational circuits (see Section 3.1), how to use them (see Section 3.2) and how to construct them (see Section 4), either by adapting Yannakakis algorithm (see Section 4.1) or by using an algorithm originally designed for solving #SAT (see Section 4.2). We then explore the consequences of these constructions regarding several known tractability results from the literature(see Section 5). It does not aim at giving full formalization and voluntarily stays high level. We also tried to give many pointers to related literature but many other relevant and interesting results and research are still unfortunately missing.

2 Preliminaries

Tuples and relations.

We let DX to be the set of mapping from a set X of attributes to a set D called the domain. An element τDX is called a tuple over attributes X and domain D. For τDX, we let attr(τ)=𝖽𝖾𝖿X to be the attributes of τ. Given a set of attributes Y, we let τ|Y to be the tuple defined over attributes Yattr(τ) and defined as τ|Y(y)=τ(y) for every yYattr(τ). If τ1,τ2 are two tuples such that τ1|Z=τ2|Z where Z=attr(τ1)attr(τ2), we say that τ1 and τ2 are consistent and write τ1τ2. In this case, we let τ1τ2 to be the tuple defined over attr(τ1)attr(τ2) as (τ1τ2)(x)=τ1(x) if xattr(τ1) and (τ1τ2)(x)=τ2(x) otherwise. We write τ1×τ2 when attr(τ1)attr(τ2)= to insist on the fact that they have disjoint attributes. We write tuple between angle brackets and with a list of couples of the form x/d where x is an attribute and d a domain value, meaning that the tuple assigns value d to x. For example τ=𝖽𝖾𝖿x/1,y/2,z/1 is the tuple over attributes {x,y,z} such that τ(x)=τ(z)=1 and τ(y)=2. We denote by the empty tuple (that is, the only tuple whose attributes are , and the identity of ×).

A relation RDX on attributes X and domain D is a set of tuples. We extend notations of tuples to relations: we define attr(R)=𝖽𝖾𝖿X to be the attributes of R, the projection of R over attributes Y to be the relation over XY defined as R|Y:={τ|YτR}. The natural join of two relations R and S is defined as RS:={τστR,σS,τσ}. Again, if attr(R)attr(S)=, we write R×S instead of RS. In this case, we say that R×S is the Cartesian product of R and S. Observe in this case that |R×S|=|R|×|S|. Given two relations R,SDX over attributes X, we write RS for the union of relations R and S, seen as sets of tuples. Now when RDX and SDY are not defined over the same attributes, we define the extended union of R and S over domain D, denoted by R¯DS, to be R×DYXS×DXY. We simply write R¯S when D is clear from context. Given a relation R over attributes X and τ a tuple over attributes Y, we denote by R/τ the relation over attributes XY containing the tuple σ such that σ×τ|YXR. Despite the notation being non standard, we think it is natural: the “/” symbol here is to be interpreted as the inverse of the Cartesian product ×.

Join and conjunctive queries.

In this paper, we focus on join queries (also known as full conjunctive queries or quantifier-free conjunctive queries). A join query is traditionally defined only over relation names, and the content of each relation, the data, is defined outside of the query itself, in a database. To ease notations and concepts, we slightly deviate from this point of view in this paper and we define a join query Q=R1(X1),,Rm(Xm) as a finite list of relations, called the atoms of Q, R1DX1,,RmDXm over a finite domain D and finite sets of attributes X1,,Xm.

The variables of a join query Q are defined as var(Q)=𝖽𝖾𝖿i=1mXi. A join query Q implicitly represents a relation over attributes var(Q) and domain D which is defined as performing the natural join of each relation it contains. Formally, we define the answers set 𝖺𝗇𝗌(Q) of Q as 𝖺𝗇𝗌(Q)=𝖽𝖾𝖿{τDvar(Q)i[m],τ|XiRi}Dvar(Q).

We consider two notions of sizes for join queries, inherited from the original separation between the logical layer and the data layer. The query size of Q, denoted by |Q| is defined as RQ|var(R)|. The query size does not take into account the content of the relation, but only their structure. The data size of Q, denoted by Q, is defined as RQ|var(R)||R|. The data size is sensible to the number of tuples in each relation, while the query size only depends on the number of relations and their arities.

A conjunctive query is defined as a pair (Q,Z) where Q is a join query and Zvar(Q) is a subset of attributes of Q called the free variables of Q. We often simply write it as Q(Z)=R1(X1),,Rm(Xm) to make the free variables explicit. The answers set 𝖺𝗇𝗌(Q(Z)) is defined as 𝖺𝗇𝗌(Q)|Z, that is, {τ|Zτ𝖺𝗇𝗌(Q)}. We extend the query size and data size to conjunctive queries, where |Q(Z)| is defined as |Q| and Q(Z) as Q.

Model of computation.

We use the word-RAM model of computation where registers contain O(logn) bits, where n is the size of the input and arithmetic operations over two registers can be done in constant time. Observe that in this model, we can perform arithmetic operations and comparisons over integers bounded by nc in polynomial time in c (actually, in time O(clogc)) [29]. In the case of join queries over variable X and domain D, we will often use numbers of size up to |D||X| (for example, when counting tuples), which means that this number can be manipulated in time O(|X|log|X|). Using radix sort, we can also sort m such values or tuples in time O(|X|(|D|+m)) [20, Section 6.3]. In other words, we can sort the tuples of a relation R in time linear in |R||var(R)|.

3 Relational Circuits

In this section, we introduce a succinct way of describing relations using circuits whose syntactic properties make them suitable for further analysis.

3.1 Main definitions

From a general point of view, a relational circuit is a circuit whose inputs are labeled by atomic relations and gates are functions building new relations from its input relations. In this setting, we can see a join query Q=R1(X1),,Rm(Xm) as a flat relational circuit, with relations Ri being inputs of a single -labeled gate. We show how one can use factorization and syntactic restrictions to design representations that are both succinct and tractable.

Join circuits.

We start with a very general definition that serves as a starting point before restricting it into more interesting classes of circuits. A {,¯}-circuit C on attributes X and domain D is defined as a labeled direct acyclic multi-graph (that is, there may be more than one edge between two vertices of the graph) with one distinguished vertex called the output of C and denoted by 𝗈𝗎𝗍(C). The vertices of the underlying DAG of C are called gates. If two gates g,g are connected by a directed edge gg, we say that g is an input of g and that g is an output of g. The gates of C are labeled as follows:

  • Every gate g without input (that is, without any incoming edge) is called an input of the circuit and is labeled by either , or x/d for some attribute xX and domain value dD. If g is labeled by or , we say that g is a constant input.

  • Every other gate (that is, every gate with at least one input) is labeled by either ¯ or .

The attributes attr(g) of a gate g of C are defined to be the set of attributes appearing in at least one input of the subcircuit rooted at g. In other words, attr(g)= if g is labeled by or , attr(g)={x} if g is labeled by x/d for some dD, and attr(g)=i=1kattr(gi) if g1,,gk are the inputs of g.

Each gate g computes a relation 𝗋𝖾𝗅(g)Dattr(g) defined inductively as:

  • If g is an input then: either it is labeled by and 𝗋𝖾𝗅(g)=, or by and 𝗋𝖾𝗅(g)={}, or by x/d then 𝗋𝖾𝗅(g)={x/d}.

  • If g has input g1,,gk and is labeled by then 𝗋𝖾𝗅(g)=𝗋𝖾𝗅(g1)𝗋𝖾𝗅(gk).

  • If g has input g1,,gk and is labeled by ¯ then 𝗋𝖾𝗅(g)=𝗋𝖾𝗅(g1)¯¯𝗋𝖾𝗅(gk).

The relation 𝗋𝖾𝗅(C) computed by C is defined as 𝗋𝖾𝗅(C):=𝗋𝖾𝗅(𝗈𝗎𝗍(C))×DXZ where Z=attr(𝗈𝗎𝗍(C)). If X is not made explicit, we simply let 𝗋𝖾𝗅(C)=𝗋𝖾𝗅(𝗈𝗎𝗍(C)).

The size |C| of a {,¯}-circuit is defined as the number of edges of its underlying graph. Sometimes, the size of circuits is defined as the number of gates, but this definition is often less natural. Indeed, an algorithm visiting every edge of the circuit is linear in the size of the input but no necessarely linear in the number of gates in the circuit since there may be O(N2) edges in a circuit with N nodes.

The family of {,¯}-circuits is not interesting from a complexity point of view as they are more general than join queries. We now restrict {,¯}-circuits in order to find representations of relations that are more tractable than join queries.

Cartesian products.

The main syntactic restriction that we impose on relational circuits is the following: in a {,¯}-circuit, we say that a -gate g is a Cartesian product gate, or ×-gate for short, if attr(g1)attr(g2)= for every distinct input g1,g2 of g. Observe that in this case, if g1,,gk are the inputs of g, then 𝗋𝖾𝗅(g)=×i=1k𝗋𝖾𝗅(gi). A {×,¯}-circuit is a {,}-circuit where every -gate is a ×-gate. Obviously, given a {,}-circuit C, we can check whether it is a {×,¯}-circuit in time O(|C||X|) by computing attr(g) for every g.

Union gates.

Another useful restriction regarding relational circuits is to restrict how ¯-gates are operating. Indeed, ¯-gates are cumbsersome to use because they force us to keep track of the attributes of each gate and to be explicit about the domain. We hence define a {×,}-circuit as a {×,¯}-circuit such that for every ¯-gate g with input g1,,gk, we have attr(g1)==attr(gk). In this case, one can easily check that 𝗋𝖾𝗅(g)=i=1k𝗋𝖾𝗅(gi).

Disjoint unions.

While {×,}-circuits allow for enumeration, one can observe that they do not allow to efficiently compute statistics on 𝗋𝖾𝗅(C). Indeed, one can easily see that it is #P-hard to compute |𝗋𝖾𝗅(C)| when C is a {×,}-circuit given on the input, by a direct reduction to the problem #DNF, though, if one is interested in approximation, this problem admits an FPRAS [36]. The hardness of counting mainly stems from the fact that unions of relations in the circuit may overlap, which makes the cardinality of the union hard to estimate.

To avoid it, we need an extra property: given a {×,}-circuit C, we say that a -gate g with inputs g1,,gk is deterministic111We keep here the usual terminology from knowledge compilation [22] and from seminal work on factorized databases [43], though the naming is slightly misleading, as it is not deterministic in the usual sense. “Unambiguous” would be a better term. if for every i<jk, we have 𝗋𝖾𝗅(gi)𝗋𝖾𝗅(gj)=. In this case, observe that i=1k𝗋𝖾𝗅(gi) is a disjoint union, denoted by i=1k𝗋𝖾𝗅(gi). A deterministic -gate will be denoted by . As for union, we also have ¯D to denote the union of relations on different attributes but having no common tuple on their shared attributes. A {×,}-circuit is then a {×,}-circuit where every -gate is deterministic.

Given a {×,}-circuit, we can now compute |𝗋𝖾𝗅(C)| with O(|C|) arithmetic operations using a straightforward dynamic programming, see Section 3.2 for details.

Decision-gates.

One can see that checking whether a given -gate is deterministic is not easy. Indeed, it is a semantic property on the relation computed by each gate and not an easy-to-check syntactic property. In practice, we know that a -gate is deterministic because the algorithm which built the circuit formally guarantees that this is the case. While in some cases, determinism may depend on complex reasons, in every algorithm we will describe in this document, determinism is ensured because some attribute x has a different value in each subcircuit. To model this very specific case, we introduce the notion of decision-gate: a decision-gate g is a gate labeled by a variable x and each incoming edge e of g is labeled by a value deD. Moreover, if e1=g1g,,ek=gkg are the incoming edges of g respectively labeled by d1,,dk, then for every i<j, didj and xattr(gi). We define 𝗋𝖾𝗅(g)=i=1k{x/di}×𝗋𝖾𝗅(gi). Clearly, by definition, we could rewrite every decision-gate with k incoming edges using only -gates and ×-gates222Observe that for this, we need the condition that xattr(gi). and at most 3k edges, hence decision-gates is only a useful syntactic sugar. A {×,dec}-circuit C is a circuit whose every gate are either Cartesian products or decision-gates.

Ordered {×,}-circuitdec.

Different paths of decision-gates in a {×,dec}-circuit may use different order. For example, we could have a path testing variable x then y then z and another path testing x then z then y. That said, the algorithm we give in Section 4 will always test variables in the same order, and we will actually use this fact to recover some results on direct access. Let π=(x1,,xn) be an order on X. We say that a {×,dec}-circuit on attributes X respects order π if for every decision-gate g labeled by xi and g an input of g, we have attr(g){xi+1,,xn}.

We observe here that some -gates are not decision-gates. For example, let g0,g1 be gates such that 𝗋𝖾𝗅(g0)={x/0,y/0,x/1,y/1} and 𝗋𝖾𝗅(g1)={x/0,y/1,x/1,y/0}, then a -gate with input g0,g1 is deterministic because 𝗋𝖾𝗅(g0) only contains tuples with an even number of ones and 𝗋𝖾𝗅(g1) with an odd number of ones but it cannot be seen as a decision-gate since both x and y can take values 0 and 1 in 𝗋𝖾𝗅(g0) and in 𝗋𝖾𝗅(g1). In this case, determinism is witnessed by a parity argument. Actually, this idea forms the base of the argument to show that {×,}-circuit are exponentially more succinct than {×,dec}-circuit [9].

Example 1.

We illustrate the previous definitions on Figure 1. We give two circuits computing the same relation R(x,y,z)={x/1,y/1,z/1,x/2,y/1,z/2,x/2,y/3,z/2}. Observe that the output of the first circuit is a -gate which is not a -gate because the relation computed by its two input gates both contain the tuple x2,y1,z2. The second circuit only has decision-gates.

Figure 1: A {×,}-circuit and a {×,dec}-circuit computing the same relation R(x,y,z)={x/1,y/1,z/1,x/2,y/1,z/2,x/2,y/3,z/2}.

Constants elimination and smoothing.

While we can be flexible on the syntax of relational circuits, useless gates may induce complexity. In particular, constant gates (-gates and -gates) may induce hidden costs. We observe that we can remove them in the circuit with a linear time procedure as follows: we remove every input of ×-gates labeled by and every input of -gate labeled by without changing the relation they compute. We also replace a ×-gates with a -labeled input by a -gate and a -gate with a -labeled input by a -gate. Each change reduces the size of the circuit by at least one, hence applying these transformations iteratively finishes and returns a circuit without constant gates.

We also observe here that {×,¯}-circuits may also be transformed into {×,}-circuit in time O(|X||C|): we can indeed precompute attr(g) for every gate of C and, for each ¯-gate g of C with input g, we can add a ×-gate g′′ between g and a circuit computing DΔi where Δ=attr(g)attr(g) and plug g′′ into g instead of g. This operation is known as smoothing in knowledge compilation [23] and can sometimes be costly if the number of variables is high. One can avoid it in some cases [46, 4]. In this work, the algorithm we will present naturally build {×,dec}-circuit so we will not focus much on {×,¯}-circuit nor {×,¯}-circuit.

3.2 Tractable tasks

In this section, we show how we can exploit properties of relational circuits to get insights on the relation they compute. This approach is akin to the one used in knowledge compilation [23]: for each class of circuits, we try to understand the tractable tasks and their complexity.

Enumeration.

Given a {×,}-circuit C on attributes X and domain D, one of the first tasks one can do is to list every tuple of 𝗋𝖾𝗅(C). To measure the complexity of such algorithm, it is customary to analyze the time spent between two outputs of the algorithm, which we call the delay. Sometimes, we need to precompute some values on the circuit before starting. This time will be accounted for as preprocessing time.

It is easy to see that we can find a tuple in 𝗋𝖾𝗅(C) in time O(|C|) by inductively constructing for each g, a tuple τg in 𝗋𝖾𝗅(g) for every gate g in the circuit, or report that 𝗋𝖾𝗅(g)=. But we can even output every tuple in 𝗋𝖾𝗅(C) with delay O(|X||C|) as follows. The main idea is to observe that giving a tuple τ over YX and xXY, we can find in time O(|C|) the subset DD such that D is the set of domain values for which τ×x/d can be extended to a full tuple of 𝗋𝖾𝗅(C). This can be done by plugging every variable in Y to their value (ie, replace input y/d by if d=τ(y) and by otherwise) and every input in zX(Y{x}) by . It gives a {×,}-circuit on variable {x} whose computed relation is exactly D. By propagating constants in the circuit in time O(|C|), it simplifies to a circuit where D can be read directly as the remaining input of the form x/d. This is enough to implement a flashlight search to enumerate 𝗋𝖾𝗅(C) by constructing each tuple one variable at a time, without never exploring partial tuples that cannot be extended to full solutions: we start by computing every possible values D that x1 can take in 𝗋𝖾𝗅(C), then pick dD and find every value of x2 can take when x1 is set to d etc. This method ensures that every partial tuple we built can be extended to a full tuple in 𝗋𝖾𝗅(C). Once such a tuple is found, we backtrack to the last variable for which it remains at least one unexplored value. Between two outputs, we do at most |X| oracle calls to the previously describe procedure, hence a delay of O(|C||X|). This method can even be extended to the case where one wants to output the tuples by increasing weights, see [3] for details.

The delay of this algorithm may be too high to recover the existing enumeration bounds from the database literature, as we would like to have a complexity that only depends on the number of variables of C. We show that in the case of {×,}-circuit, we get better bounds. Indeed, to enumerate 𝗋𝖾𝗅(g) when g is a -gate with inputs g1,,gk, one only needs to successively enumerate 𝗋𝖾𝗅(gi) for every 1ik. The delay is thus maxdi where di is the delay to enumerate 𝗋𝖾𝗅(gi). To enumerate 𝗋𝖾𝗅(g) where g is a ×-gate with input g1,,gk, we enumerate one tuple from 𝗋𝖾𝗅(g1), then every tuple from 𝗋𝖾𝗅(g2)××𝗋𝖾𝗅(gk). The delay between two outputs is idi since it is the time needed to find the first tuple. If we again ensure that each ×-gate has no trivial input, we can show that the delay is O(nh) where h is the depth of the circuit and n the number of variables. Observe that in the worst-case, the depth h could be of the order of |C|. We can however always rewrite into a circuit with depth at most n by ensuring the every -gate has no other -gate as input. Doing it naively may however increase the size of the circuit quadratically. Amarilli, Bourhis, Jachiet and Mengel proposed a work-around in [4] to quickly find the gates that could be reached from a -gate in linear time allowing for enumeration with delay O(n) after linear preprocessing.

Observe that in the particular case of {×,dec}-circuit, the previous algorithm directly gives O(n) delay as long as for every ×-gate g with input g1,,gk, we have attr(gi), which can be ensured with linear time preprocessing by simply removing constants in the circuit.

Counting.

Given a {×,}-circuit, we can now compute |𝗋𝖾𝗅(C)| with O(|C|) arithmetic operations using a straightforward dynamic programming. For each gate g, we compute |𝗋𝖾𝗅(g)| inductively: if g is an input, then |𝗋𝖾𝗅(g)|=0 if g is a -gate and |𝗋𝖾𝗅(g)|=1 otherwise. If g is a ×-gate with input g1,,gk , then |𝗋𝖾𝗅(g)|=i=1k|𝗋𝖾𝗅(gi)|. If g is a -gate with input g1,,gk then |𝗋𝖾𝗅(g)|=i=1k|𝗋𝖾𝗅(gi)|. Hence, we can compute |𝗋𝖾𝗅(C)| with O(|C|) arithmetic operations. For every g, |𝗋𝖾𝗅(g)| does not exceed |D||X|, where D is the domain of C and X its attributes. Hence, each number can be stored in at most |X| registers in a RAM machine, and each arithmetic operation can be performed in time O(|X|log|X|), resulting in a final complexity of O(|X|log|X||C|). For {×,¯}-circuit, we have a similar result but we need to precompute attr(g) for every gate g. If g is a ¯-gate, we have |𝗋𝖾𝗅(g)|=i=1k|𝗋𝖾𝗅(gi)||D|δi where δi=|attr(g)attr(gi)|.

Sampling.

Interestingly the previous algorithm can be leveraged into a uniform sampling algorithm. Assume |𝗋𝖾𝗅(g)| has been precomputed for every gate g of C. If one wants to draw a tuple τ𝗋𝖾𝗅(g) uniformly, we can do this simple procedure:

  • If g is a -gate, then fail (this case should not happen unless 𝗋𝖾𝗅(C)=).

  • If g is a -gate or a gate labeled by x/d, then return the only tuple in 𝗋𝖾𝗅(g).

  • If g is a -gate with input g1,,gk, then draw 1ik with probability |𝗋𝖾𝗅(gi)||𝗋𝖾𝗅(g)| and uniformly sample in 𝗋𝖾𝗅(gi).

  • If g is a ×-gate with input g1,,gk then return τ1××τk where τi is sampled uniformly from 𝗋𝖾𝗅(gi).

In the case of {×,}-circuit, without further assumptions, we can show that this procedure runs in time O(|X|h) where h is the depth of the circuit, that is, the longest path from the output to an input of C. If C is a {×,dec}-circuit and if we have removed trivial inputs from ×-gate (that is, for every ×-gate g, attr(g)), then we can show that this procedure runs in time O(|X|).

Direct Access.

We can go one step further and compute a numbering on 𝗋𝖾𝗅(C) so that we can efficiently access 𝗋𝖾𝗅(C)[i], as if it was a table. This kind of algorithm have been called “direct access algorithm” [8, 16, 25, 17, 14]. We define an order on 𝗋𝖾𝗅(C) by inductively defining, for every gate g of C, a one-to-one mapping Ig:𝗋𝖾𝗅(g)[0,Ng1] where Ng=|𝗋𝖾𝗅(g)|. We call Ig an index on 𝗋𝖾𝗅(g). We first assume for every gate g, its input g1,,gk are listed in some arbitrary order. We now define the index functions inductively.

  • If g is an input, not labeled by , we define Ig(τ)=0, for τ the only assignment in 𝗋𝖾𝗅(g).

  • If g is a -gate with input g1,,gk, let τ𝗋𝖾𝗅(g). We define Ig(τ)=i=1j1Ni+Igj(τ) where Ni=|𝗋𝖾𝗅(gi)| for every ik and j is the only value in [k] such that τ𝗋𝖾𝗅(gj). In other words, we order 𝗋𝖾𝗅(g) by first taking every tuple from g1, then g2 etc.

  • If g is a ×-gate with input g1,,gk, let τ𝗋𝖾𝗅(g). Let τi=τ|attr(gi) and Ni=|𝗋𝖾𝗅(gi)|. We by τi𝗋𝖾𝗅(gi) for every ik. We define

    Ig(τ)=𝖽𝖾𝖿j=1kIgj(τj)i=j+1kNi,

    that is Ig(τ) is the rank of (Ig1(τ1),,Igk(τk)) in [N1]××[Nk] ordered lexicographically.

Interestingly , we can revert this indexing structure. Indeed, given I{0,,|𝗋𝖾𝗅(g)|1}, we can efficiently compute Ig1(I), that is, the tuple τ𝗋𝖾𝗅(g) such that Ig(τ)=I. Indeed, assume we have precomputed, for every -gate g with input g1,,gk and jk, the value lj=i=1j|𝗋𝖾𝗅(gi)| and stored them in an ordered table Lg=[l1,,lk]. We also precompute |𝗋𝖾𝗅(g)| for every ×-gate g.

First assume g is a -gate and let I|𝗋𝖾𝗅(g)|. To find the Ith tuple of 𝗋𝖾𝗅(g), we need look for the smallest j such that ljI which can be done via a binary search with O(logk)=O(log|C|) comparisons, each comparison being on integers smaller than |D||X|. Then we inductively output the Igi1(Ilj) tuple of gi.

Now assume g is a ×-gate with input g1,,gk and let I|𝗋𝖾𝗅(g)|. We are looking for τ=τ1××τk𝗋𝖾𝗅(g1)××𝗋𝖾𝗅(gk) such that

I=j=1kIgj(τj)i=j+1kNi,

where Ni=|𝗋𝖾𝗅(gi)| has been precomputed already. Observe that Igk(τk)=ImodNk since every other term of the sum can be divided by Nk. Similarly, Igk1(τk1)=(I/Nk)modNk1 where I/Nk is the quotient of the division of I by Nk. We similarly have Igj(τj)=(I/i=j+1kNi)modNj. Hence we can compute inductively τj as Igj1((I/i=j+1kNi)modNj).

Hence, after a precomputation step of O(|X||C|), we can, on input I, fail if I>|𝗋𝖾𝗅(C)|, and otherwise, output τ=I𝗈𝗎𝗍(C)1(I) with O(h|X|log|C|) comparisons or arithmetic operations on integers smaller than |D||X|, where h is the depth of C. Hence, in total time O(h|X|2(log|X|)(log|C|)(log|D|)).

This direct access algorithm has interesting consequences. It allows to enumerate 𝗋𝖾𝗅(C) in a uniformly chosen order, or, equivalently, perform sampling without replacement: we sample or randomly enumerate values in {1,,|𝗋𝖾𝗅(C)|}, and output the corresponding tuple in 𝗋𝖾𝗅(C). This can be done efficiently by adapting the Fisher-Yates shuffle algorithm in a lazy way, as in [17].

We again get better complexity bounds for {×,dec}-circuits. Indeed, in this case, we can bound the arity of -gates (in the form of decision-gates) by the size of the domain D and we can show that we can recover the Ith element of 𝗋𝖾𝗅(C) with O(|X|log|D|) arithmetic operations because each recursive call is done on gates having strictly less attributes, hence a total time of O(|X|2(log|X|)(log|D|)). More interestingly, if the circuit respects order (x1,,xn), then we can actually solve the direct access problem for the lexicographical order induced by (x1,,xn) on DX with a slightly more involved access technique that can still be executed with O(|X|log|D|) arithmetic operations and comparisons. Indeed, in this case, given a tuple τ over attributes {x1,,xk} with kn, we can find how many tuple from 𝗋𝖾𝗅(C) are smaller than τ in the lexicographical order. We can use it to build the Ith element of 𝗋𝖾𝗅(C) by discovering it one variable at a time, using counting queries to find the value of the next variable with a binary search, see [14] for details.

We conclude this section by summarizing the results we will use the most in the context of databases:

Theorem 2.

Given an ordered {×,dec}-circuit C on attributes X and domain D respecting order π, we can:

  • Enumerate 𝗋𝖾𝗅(C) with preprocessing O(|C|) and delay O(|X|),

  • Compute |𝗋𝖾𝗅(C)| in time O(|X||C|),

  • Uniformly sample τ𝗋𝖾𝗅(C) after preprocessing O(|X||C|),

  • Find the Ith element of 𝗋𝖾𝗅(C) according to the lexicographical order induced by π in time O(|X|2log|X|log|D|) after O(|X||C|) preprocessing.

3.3 Previous work

Factorized databases.

Relational circuits originated under the name factorized databases in the seminal paper by Olteanu and Závodný [42]. In this document, we decided to use the name relational circuits to describe the object used to represent the relation, in contrast to the term factorized databases which, in our opinion, describe a set of techniques covering, in particular, the notion of relational circuit. In this work, the class of {×,}-circuits appears under the name factorized representation with definitions, or d-representations, while {×,}-circuit have been introduced as deterministic d-representations. In [43], the definition explicitly enforces unions to be defined over gates having the same attributes. We decided to deviate from the original terminology because we think that {×,}-circuit is more natural than d-representation and it allows to be more precise on the syntactic restriction we want to enforce on the circuit, where the term d-representation is too general.

We want to clearly distinguished in this paper between the syntactic properties of relational circuits and the algorithm constructing the circuits. This is why, in this work, we decided to separate the notion of relational circuits that simply represent relations, sometimes with specific semantics or syntactic restrictions, and how such relational circuits are produced.

NNFs and Relational circuits.

Syntactically restricted Boolean circuits have been used for representing Boolean functions since the 80s, at first through the lens of ordered binary decision diagrams [13] (which can be seen as {dec}-circuits) and then later generalized to restricted Boolean circuits under the name Decomposable Negation Normal Form (DNNF) [23, 21, 22] with decomposable -gates, corresponding to ×-gates, and deterministic -gates, corresponding to ¯-gates on domain {0,1}. The similarity of knowledge compilation and factorized databases has been observed in [40] but the connections between classes of circuit is not covered. We provide a comparison in Table 1 using the circuit notations from the previous sections and the main classes studied in knowledge compilation. Previous work have been using DNNF in many areas of computer for enumeration by encoding database queries answers into DNNF [4, 3], probabilistic databases by representing the Boolean provenance a query with DNNFs [41, 10, 9, 48], for computing Shapley scores [6, 11], see [5] for a more detailed introduction on the applications of circuits in databases.

We do not include definitions of the Boolean counterpart of relational circuits and refer to [23]. that one can also recover them by simply taking the corresponding class of relational circuit and specializing them over domain {0,1}: indeed each line illustrates the correspondence between a Boolean circuit and relational circuits as follows: when considering circuits on the right column on domain D={0,1}, it corresponds exactly to the Boolean circuit on the left.

The correspondence actually works both ways: for non-binary domain D={d0,,dk1}, we can encode D with bitstrings over b=logk bits by representing di with the binary representation of i over b bits. Hence, given a {,}-circuit C over attributes X={x1,,xn} and domain D={d0,,dk1}, we can convert it into an NNF over variables X~={x10,,x1b1,,xn0,,xnb1} by replacing every input xi/dj by a circuit over variables xi0,,xib1 accepting only the assignment encoding j in binary. This can easily be done by {dec}-circuit of size 2b. It can be encoded in any NNF subclass from Table 1, showing that every relation circuit on attributes X and domain D from the right column can be naturally casted into an NNF from the left column with an additional increase of at most |X|log|D| increase.

We conclude this section by observing that most relational circuits, with relevant syntactic restrictions, can be understood as automaton on finite language. For example, ordered {dec}-circuits correspond to finite state automaton without loop, hence on a finite language, while Context-Free grammar could be associated to restricted {×,}-circuit where ×-gates are only allowed to split variables according to some total order. Other syntactic restriction of {×,}-circuit not presented in this paper can also be shown to correspond to tree automaton. These connections have been studied in [33, 2].

Table 1: Rosetta Stone of Tractable Circuits.
KC Relational circuits
NNF circuit {,}-circuit if smooth, {,¯}-circuit otherwise.
DNNF circuit {×,}-circuit if smooth, {×,¯}-circuit otherwise.
d-DNNF circuit {×,}-circuit if smooth, {×,¯}-circuit otherwise.
dec-DNNF circuit {×,dec}-circuit if smooth, {×,dec¯}-circuit otherwise.
FBDD {dec}-circuit if smooth, {dec¯}-circuit otherwise.

4 Algorithms for Building Circuits

Now that we have introduce relational circuits as a handy way of representing relations, we turn our attention on two main algorithms to build them. The first one can be seen as revisiting the celebrated Yannakakis Algorithm [50] while the second one is a generalization, to the database setting, of the exhaustive DPLL algorithm [45] which has originally been devised for solving #SAT, but which is known to implicitly build decision-DNNF, the Boolean counterpart of {×,dec}-circuit [30] and which is used in practice by many knowledge compilers such as d4 [35] or (a modification of) SharpSAT-TD [34, 32].

4.1 Bottom-up compilation and Yannakakis Algorithm

Yannakakis algorithm has originally been devised to check for consistency of acyclic database schemes in time linear in the size of the data [50], which is the same as checking whether an acyclic join query has at least one answer. It has quickly been observed that the same idea allows to also efficiently find every answer of the acyclic queries [7] or count them [44]. In this section, we explain how it could also be used as a way of constructing an ordered {×,dec}-circuit computing 𝖺𝗇𝗌(Q) of size linear in Q for any acyclic join query Q.

A join query Q=R1(X1),,Rm(Xm) is acyclic if there exists a tree 𝒯, called a join tree, such that:

  • The vertices of 𝒯 are in one to one correspondence with R1,,Rm, and for a node t of T, we let Rt be the relation labeling it.

  • For every variable xvar(Q), {txvar(Rt)} is connected in 𝒯 (we call this property the connectedness of 𝒯).

It is known that we can decide whether Q is acyclic and if so, construct a join tree of Q in linear time in |Q| [47]. Yannakakis algorithm exploits the properties of join tree to propagate just the right information along it, in order to decide whether 𝖺𝗇𝗌(Q) is empty or not. In the rest of this section, we generalize this algorithm into a circuit construction establishing:

Theorem 3.

Let Q be an acyclic join query. We can construct a {×,dec}-circuit C computing 𝖺𝗇𝗌(Q) of size O(Q) in time O(poly(|Q|)Q). Moreover, C respects an order π on var(Q).

Circuit construction.

Let Q be a join query and 𝒯 a join tree for Q. Assume 𝒯 is rooted at an arbitrary node, and let t be a node of 𝒯. We let 𝒯t be the subtree of 𝒯 rooted in t and Qt to be the join query whose atoms are exactly the atoms appearing in 𝒯t. The crux of Yannakakis algorithm is the following observation: if t1,t2 are two children of t, then var(Qt1)var(Qt2)var(Rt). Indeed, every path from 𝒯t1 to 𝒯t2 must go through t. Hence if x appears on both side, by connectedness, it must be in var(Rt) too.

Let t1,,tk be the children of t in 𝒯. An answer σ of Qt have the following shape:

  • Projected over var(Rt), they must be equal to some tuple τ in Rt.

  • Projected over var(Qti), they must be an answer of Qti that extends τ.

In other words, an answer of Qt is of the form τ×τ1××τk where (τ×τi)|Vi𝖺𝗇𝗌(Qti) where Vi=var(Qti). In other words, we have established:

𝖺𝗇𝗌(Qt)/τ=𝖺𝗇𝗌(Qt1)/τ××𝖺𝗇𝗌(Qtk)/τ. (1)

If we further develop each term of the previous Cartesian product and if we let Δi=var(Rti)var(Rt), we have: µ

𝖺𝗇𝗌(Qti)/τ=σRti,στ(𝖺𝗇𝗌(Qti)/σ)×σ|Δi. (2)

In the original Yannakakis algorithm, these relations are used to dynamically maintain the following information: does Qt have an answer extending τRt? Indeed, Equation 1 tells us that Qt has an answer extending τ if and only if for every ik, Qti has an answer extending τ, which by Equation 2 is equivalent to the fact that Qti has an answer extending σ for some σRti with στ. In Yannakakis algorithm, the latter has been precomputed and hence, we can quickly decide in time O(k|var(Rt)|) whether Qt has an answer extending τ for every τ. When the algorithm reaches the root r of 𝒯, Qr=Q and we can decide whether Q has an answer.

But Equations 1 and 2 can also be seen as a way to build 𝖺𝗇𝗌(Qt)/τ for every τRt from the relations 𝖺𝗇𝗌(Qti)/σ for every σRti, by using decision-gates and one Cartesian product gate. The circuit is build in a bottom-up fashion from the leaves of 𝒯 to its root. We build a circuit having the following property: for each node t of 𝒯 and τRt, there is a gate vtτ computing 𝖺𝗇𝗌(Qt)/τ. If t is a leaf of 𝒯, Qt only has one atom Rt. Hence, for every τRt, 𝖺𝗇𝗌(Qt)/τ={} is the relation containing only the empty tuple. Hence, we define vtτ as a -gate.

Now if t has children t1,,tk, we let τRt. We first create gates to compute 𝖺𝗇𝗌(Qti)/τ. By Equation 2, we can build a tree of decision-gates on attributes Δi, rooted in a gate wiτ whose leaves correspond to assignment σΔi for every σRti such that στ. Each leaf is connected to the gate vtiσ that has been inductively constructed and computes, by induction, 𝖺𝗇𝗌(Qti)/σ. By Equation 2, wiτ computes 𝖺𝗇𝗌(Qti)/τ. Now, we simply define vtτ as a Cartesian product gate ×i=1kwiτ, and by Equation 2, it computes 𝖺𝗇𝗌(Qt)/τ.

To be efficient, observe that if τ1,τ2Rt and τ1|var(Rti)=τ2|var(Rti), then 𝖺𝗇𝗌(Qti)/τ1=𝖺𝗇𝗌(Qti)/τ2, hence we can use wiτ1 for both, without duplicating the gates.

At the root r of 𝒯, we have for every τRr, a gate vrτ computing 𝖺𝗇𝗌(Q)/τ. We hence add a tree of decision-gates rooted in a gate vr whose leaves correspond to τ for every τRr and plug it to vrτ directly. Gate vr computes 𝖺𝗇𝗌(Q) and we choose it to be the output of C.

Example 4.

We illustrate the previous algorithm on the example given on Figure 2. In this example, we assume we have performed the construction in the subtrees rooted in t1 and t2 respectively. Hence, we have constructed gates vt1100,vt1121,vt1200,vt1221 and vt2114,vt2113,vt2213,vt2302,vt2401 corresponding to every tuple of Rt1 and Rt2 respectively. The only common attribute between Rt and Rt1 is x1 which has been grayed in the figure. Hence, the first step of the construction starts by grouping every tuple in Rt1 having the same projection on x1 and build a decision tree for them. In the example, it means that we group x1/1,x3/0,x4/0 and x1/1,x3/2,x4/1 together and hence built a decision tree for the relation {x3/0,x4/0,x3/2,x4/1}. This decision tree is depicted on the bottom left corner of Figure 2. Observe its leaves are connected to vt1100 and vt1121 respectively. The same is done for x1/2,x3/0,x4/0 and x1/2,x3/2,x4/1 but we connect the leaves to vt1200 and vt1221. Observe that we built twice the same decision tree because the tuples of Rt1 where x1=1 projected on x3,x4 are the same as the tuples of Rt1 where x1=2 projected on x3,x4. Yet, we do not identify the subtree because below they may have used x1 in different ways.

We proceed similarly with Rt2. Observe that in this case, despite having we have 4 distinct values of x1 in Rt2, we only construct decision-trees for three of them because the case x1=4 has no possible extension in Rt.

Now, for each τRt, we introduce a Cartesian product gate and connect it to the corresponding decision-gates below. For example, for τ=x1/1,x2/0, we introduce the ×-gate vt10 whose inputs correspond to the roots of the previously constructed decision-tree for tuples of Rt1 and Rt2 where x1=1. Observe in this case that vt10 and vt12 have the same inputs, this is where the factorization happens.

Observe that the case x1=3 is interesting because it both has corresponding tuples in Rt and Rt2 but not in Rt1. In this case, we know that 𝖺𝗇𝗌(Qt)/x11= because Rt1/x11=. Hence, we set vt30 to be a -gate and the root of the join tree corresponding to x50,x62 is dangling in the circuit and will never be used. This is a typical case of the over computation performed by many dynamic programming algorithm: we precompute some values that may have relevance locally but not later in the circuit. The same happens to the tuple where x1=4. Neither Rt nor Rt1 has such tuples, hence, we have a dangling tuple again (observe that in this case, we do not even construct the decision-tree). Observe that we can always postprocess the circuit C in O(|C|)=O(Q) to remove dangling gates and -input propagating constants and removing gates without outputs.

Finally, if t is also the root of the join tree, then it remains to project out the attribute x1 and x2 in the circuit, which is done in the last layer of the circuit.

Figure 2: Local construction of Yannakakis style compilation algorithm. See Example 4.

Properties of the circuit.

A careful analysis reveals that the number of gates in this circuit is bounded by 2Q+1 and can be built in time O(poly(|Q|)Q).

Moreover, if we are consistent in the ordering used to built every tree of decision-gates, we can see that the resulting circuit is ordered. It can actually be made to respect any completion to a total order of the following partial order: given xvar(Q), let tx be the last node of 𝒯 such that xvar(Rtx). That is, no ancestor of tx contain x. Then for x,yvar(Q), we write x𝒯y if and only if ty is below tx in 𝒯. It defines a partial order on var(Q) that intuitively corresponds to ordering the variables from their order of appearance from the root of 𝒯 to its leaves. Let (x1,,xn) be an order on var(Q) completing 𝒯 into a full order. Then, in the construction previously described, we can force the circuit to respect order (x1,,xn). For example, in Example 4, the circuit respects order (x1,,x6), but also (x1,x2,x5,x6,x3,x4).

Beyond acyclic join queries.

If a join query Q is not acyclic, we can still use Yannakakis algorithm but with worse guarantees. We first have to generalize the notion of join tree. A tree decomposition 𝒯 of Q is a tree such that every node of 𝒯 is labeled with Btvar(Q) and such that for every atom R of Q, there exists t such that var(R)Bt and such that for every xvar(Q), the set {txBt} is connected in 𝒯. Now let Qt be the join query whose atoms are R|Bt for every atom R of Q such that var(R)Bt and let t=𝖺𝗇𝗌(Qt). We define Q to be the join query whose atom are {tt𝒯}. By definition, 𝒯 is a join tree of Q, hence Q is acyclic and has the same answers as Q and we can use Yannakakis algorithm to build a {×,dec}-circuit computing 𝖺𝗇𝗌(Q) and of size O(Q). We can always normalize 𝒯 to have at most O(n) nodes where n=|var(Q)|, hence Q=O(nmaxt|t|). Hence, if we know that |t|U and if we can compute t in time O(U), then we can construct a {×,dec}-circuit computing 𝖺𝗇𝗌(Q) in time poly(|Q|)|U|.

The challenge is now to find a relevant upper bound U on |t|=|𝖺𝗇𝗌(Qt)|. The first idea is to bound the number of atoms covering Qt. Indeed, assume Qt contains k atoms whose union of variables is equal to var(Qt)=Bt, then |𝖺𝗇𝗌(Qt)|Qk and we can compute the join of these k atoms and filter the tuples not in 𝖺𝗇𝗌(Qt) in time O(Qk). The number of atoms of Q needed to cover Bt is called the cover number ρ(Bt) and the hypertree width 𝗁𝗍𝗐(Q,𝒯) of Q with respect to 𝒯 [27] is defined as maxtρ(Bt). From what precedes, we can hence construct a {×,dec}-circuit computing 𝖺𝗇𝗌(Q) in time poly(|Q|)Q𝗁𝗍𝗐(Q,𝒯).

We can actually relax the covering notion into a fractional version of it, offering better size guarantees and, using appropriate join algorithms[38, 49, 37, 39, 15], the corresponding time complexity, leading to the more general notion of fractional hypertree width 𝖿𝗁𝗍𝗐(Q,𝒯) of Q with respect to 𝒯 [28] allowing to construct a {×,dec}-circuit computing 𝖺𝗇𝗌(Q) in time poly(|Q|)Q𝖿𝗁𝗍𝗐(Q,𝒯).

We now explain how to handle a conjunctive query Q(Z). After having compiled a {×,dec}-circuit for Q, we can project every attributes that are not in Z. This is possible in any {×,}-circuit by replacing, for every yZ, every input labeled by y/d with . However, doing so comes at the price of loosing determinism, that is, the resulting circuit is now a {×,}-circuit, which does not support model counting nor would it give constant delay enumeration. This is not surprising, as it is known that enumerating or finding the number of answers of acyclic conjunctive queries may not be doable with linear preprocessing [7, 24]. The increased complexity from join to conjunctive queries mostly comes from how the free variables interact with the other. We have a similar phenomenon with ordered {×,dec}-circuit: indeed, assume that var(Q)Z appears at the end of the order, then projecting them preserves determinism, which leads to a smaller ordered {×,dec}-circuit representing 𝖺𝗇𝗌(Q(Z)), hence the tractability results of Q transfer to Q(Z).

From the point of view of tree decompositions, this assumption on the order respected by the circuit translates informally into the fact that, in the tree decomposition, the “free variables should be above the projected variables”. This can be formalized as the notion of free-connex tree decomposition [7], where there is a connected subset of nodes of 𝒯 whose variables are exactly the free-variables. Given a free-connex tree decomposition of fractional hypertree width k of a conjunctive query Q(Z), the previous paragraph shows that we can construct a {×,dec}-circuit computing 𝖺𝗇𝗌(Q(Z)) in time poly(|Q|)Qk. Another way of seeing this is that from a free-connex tree decomposition, we can construct an acyclic join query Q with 𝖺𝗇𝗌(Q)=𝖺𝗇𝗌(Q(Z)), by proceeding similarly as before. The free-connexity ensures that we are able to project out variables in var(Q)Z.

4.2 Top-down compilation and Exhaustive DPLL

We now explain another algorithm that can be used to construct an ordered {×,dec}-circuit computing 𝖺𝗇𝗌(Q). It can be applied to any query but if Q has fractional hypertree width k, then using the right variable ordering will construct the circuit in time poly(|Q|)Qk.

The algorithm is based on a recursive procedure which picks a variable x, add a decision-gate on x, and for every value dD, recursively computes 𝖺𝗇𝗌(Q)/x/d. To avoid blow-up, we add two ingredients: (i) caching, where at each recursive call with parameters (Q,τ), we detect whether there already exists a gate in the circuit computing 𝖺𝗇𝗌(Q)/τ, (ii) connected component analysis, where we detect if 𝖺𝗇𝗌(Q)=𝖺𝗇𝗌(Q1)××𝖺𝗇𝗌(Qk), in which case, we create a Cartesian product gate and recursively construct circuits for Q1,,Qk.

To be efficient, we need to perform caching in a syntactic way only. We formalize it as follows: let τ be a tuple of Yvar(Q). If there exists an atom R of Q such that R/τ=, then no answer of Q extends τ. In this case, we say that τ is inconsistent with Q. Otherwise, if var(R)Y, then 𝖺𝗇𝗌(Q)/τ is the same as 𝖺𝗇𝗌(Q)/τ where R has been removed from Q. We hence denote by Q/τ=(Q,τ|Y) where Q is the join query obtained by removing every atom R in Q such that var(R)Y and Y=Yvar(Q). For example, if Q=R(x1,x2)S(x2,x3)T(x3,x4) and τ=x1/1,x2/2R, then Q/τ=(S(x2,x3)T(x3,x4),x2/2) because R has been removed from Q and x1 is no longer a variable in the remaining query. Because of this, instead of writing Q/τ as a couple, we simply write S(2,x3)T(x3,x4). Observe that if τ=x1/2,x2/2R, then Q/τ=Q/τ and 𝖺𝗇𝗌(Q)/τ=𝖺𝗇𝗌(Q)/τ. This kind of equivalence can be check purely syntactically, hence in time poly(|Q|). For this reason, once we have build a gate v in the circuit computing 𝖺𝗇𝗌(Q)/τ, we cache v with key Q/τ. Hence, if at some point, another recursive call on (Q,τ) happens and Q/τ=Q/τ, then we can directly pull v from the cache instead of redoing the same computation.

Connected components analysis is also a purely syntactical analysis of the query. Given a join query Q and a tuple τ over variable Y, we consider the graph whose vertices are the atoms of Q/τ and there is an edge between two atoms if they share a variable not in Y (that is, not yet assigned by τ). If this graph has more than connected components C1,,Ck, it splits Q into Q1,,Qk and τ into τ1,,τk such that Q=Q1,,Qk, τ=τ1××τk and 𝖺𝗇𝗌(Q)/τ=𝖺𝗇𝗌(Q1)/τ1××𝖺𝗇𝗌(Qk)/τk.

We now describe the Exhaustive DPLL algorithm. It takes as input a join query Q, a tuple τ and an order π=(x1,,xn) on var(Q) and returns a gate v in an ordered {×,dec}-circuit respecting π such that v computes 𝖺𝗇𝗌(Q)/τ.

  1. 1.

    If Q is inconsistent with τ, then return a -gate. It is correct since 𝖺𝗇𝗌(Q)/τ=.

  2. 2.

    If τ assigns every variable of Q, then return a -gate. It is correct since 𝖺𝗇𝗌(Q)/τ={}.

  3. 3.

    If Q/τ is mapped in the cache to a gate v, then return v. It is correct since by induction, the cache is correct and hence v computes 𝖺𝗇𝗌(Q)/τ.

  4. 4.

    Otherwise, split Q/τ into connected components {Q1/τ1,,Qk/τk}:

    1. (a)

      If k>1: create a ×-gate v and for i=1,,k, let vi𝖣𝖯𝖫𝖫(Qi/τi,π) which recursively constructs a gate vi computing 𝖺𝗇𝗌(Qi)/τi. Add vi as an input of v. Now v computes ×i=1k𝖺𝗇𝗌(Qi)/τi=𝖺𝗇𝗌(Q)/τ which is what desired. The algorithm then updates the cache to map Q/τ with v and returns v.

    2. (b)

      If k=1: let xi be the smallest variable in Q according to π that is not set by τ. We add a new decision-gate v on variable xi. For every dD, we let vd𝖣𝖯𝖫𝖫(Q/τd,π) where τd=τ×xi/d to recursively construct a gate vd computing 𝖺𝗇𝗌(Q)/τd and add an edge labeled by d between v and vd. By definition, v computes dD𝖺𝗇𝗌(Q)/(τ×xi/d)=𝖺𝗇𝗌(Q)/τ. The algorithm updates the cache to map Q/τ with v and returns v.

On input (Q,,π), Exhaustive DPLL clearly outputs an ordered {×,dec}-circuit respecting π and computing 𝖺𝗇𝗌(Q).

Example 5.

We now give an example333An interactive version of this example can be found at https://florent.capelli.me/algorithms/dpll/ with others.. We consider Q=R(x0,x1),S(x0,x2),T(x1,x3) with R,S,T given on Figure 3. With π=(x0,x1,x2,x3), 𝖣𝖯𝖫𝖫(Q/,π) produces the circuit given on Figure 3. Each gate is labeled by the number of recursive call which produced it. For example, v1 is produced by the first recursive call on input (Q/x0/1,π). Observe that Q/x0/0=R(0,x1),S(0,x2),T(x1,x3) has two connected components: the first one being R(0,x1),T(x1,x3) and the second one being S(0,x2). Hence a ×-gate is created and linked to the result of the first recursive call producing circuits rooted in v2 and v7.

The edge between v11 and v4 is also interesting because it corresponds to a cache hit. Indeed, the recursive call producing v11 is done with parameters Q1/x0/1=R(1,x1),T(x1,x3). Since there is exactly one connected component, a decision-gate on x1 is created and a recursive call with input Q1/x0/1,x1/0=T(0,x3) is made, leading to the creation of the circuit rooted at v12. Then, another recursive call is made with input Q1/x0/1,x1/1=T(1,x3) which is the recursive call which produced v4 since it had parameters Q1/x0/0,x1/1=T(1,x3). Hence, v4 is directly upon reading the cache after call with parameter Q2.

R x0 x1
0 1
1 0
1 1
S x0 x2
0 1
1 0
1 1
T x1 x3
0 0
1 1
Figure 3: The circuit produced from Example 5.

The size of the circuit produced by 𝖣𝖯𝖫𝖫(Q/,π) mostly depends on π. Interestingly, if Q is acyclic with a join tree 𝒯 and π is chosen as for Yannakakis, that is, by ordering the variables from the root of 𝒯 to its leaves, then 𝖣𝖯𝖫𝖫(Q/,π) produces a circuit of size poly(|Q|)Q, matching the guarantee of the top-down construction of Yannakakis. This is because once every variable in the root r of 𝒯 have been set, it splits Q into as many connected component as r has children in 𝒯. Moreover, if t is a child of 𝒯 in r and if two assignments of the variables in r have the same value over the variables in node t, then a cache hit will occur. In a way, we can see Exhaustive DPLL as a mean of constructing a similar circuit as Yannakakis but from the output to the inputs of the circuit, while Yannakakis approach goes from the inputs to the output.

If π is extracted from a tree decomposition 𝒯 of Q whose fractional hypertree width is k, then 𝖣𝖯𝖫𝖫(Q/τ,π) produces a circuit of size poly(Q)Qk, see [14] for details, as the analysis is a bit convoluted. Observe that for running 𝖣𝖯𝖫𝖫(Q/,π), we do not need to know the tree decomposition, this comes handy only in the complexity analysis. In a way, π is the decomposition. We can hence use π to measure how good it is with respect to Q. This actually corresponds to characterization of fractional hypertree width in terms of elimination orders, see [26, 1, 12] for details.

The version of Exhaustive DPLL described above has however an annoying limitation: when branching on a variable x, we brute force over every possible value dD. Some of these calls will directly return . This leads to a factor of |D| in the time needed to construct the circuit, that is, we construct the circuit in time |D|poly(Q)Qk for an order π induced by a decomposition of width k. There are two ways of shaving this factor. We can either use a more involved algorithm to explore only relevant values for variable x, adapting ideas from worst-case optimal join, such that leapfrog join [49]. Another simpler way is to use the binarization technique described in Section 3.3 to reduce the domain to a domain of size 2 while having |X|log|D| variables, hence leading to a construction in time log|D|poly(Q)Qk as in [14]. We observe however that the binarization technique is also an implicit way of reducing the number of candidates which can also be used in the design of worst-case optimal join algorithm [15].

Finally, we observe that Exhaustive DPLL is flexible: we can handle more than just join queries, as long as we have a recursive way of representing a query whose answer are 𝖺𝗇𝗌(Q)/τ and a caching mechanism. In particular, we have used it in [14] to compute ordered {×,dec}-circuit representing the answer set of join queries with negated atoms. In this setting, we want to solve a join query but remove answers that satisfy some relations, that we see as negated atoms. It is straightforward to adapt exhaustive DPLL to this kind of queries: we can simply define Q/τ as before, but also removing negated atoms ¬R from Q for which τ cannot be extended to a tuple in R.

5 Fine-grained consequences

We conclude this paper by spelling out the consequences of the tractability of ordered {×,dec}-circuit from Theorem 2 and the circuit construction from Section 4. In this section, we let Q(Z) be a conjunctive query and 𝒯 a free-connex tree decomposition of Q of fractional hypertree width k. We recover the constant delay enumeration of [7] after poly(|Q|)Qk preprocessing by constructing the circuit for Q(Z) during the preprocessing phase and then enumerating the tuple with delay O(|Z|), which is constant in data complexity. We similarly recover (an extension of) the result from [44] by simply returning |𝗋𝖾𝗅(C)| after having constructed C: the construction of C takes time poly(|Q|)Qk while computing |𝗋𝖾𝗅(C)| takes O(|X||C|)=poly(|Q|)Qk. The direct access algorithm from [16, 12] is also recovered directly since after building the circuit, the access time is O(poly(|X|)log|D|), hence, in data complexity, it corresponds to O(log|D|) from earlier result. DPLL allows to generalize to join queries with negations, see [14].

Finally, we observe that we could have mentioned that the counting algorithm outline in Section 3.2 could be generalized where inputs are labeled with semiring elements and then aggregated over it, allowing to solve FAQ or AJAR types of queries over the circuit with complexity similar to [1, 31], as long as we remain compatible with its underlying order.

References

  • [1] Mahmoud Abo Khamis, Hung Q Ngo, and Atri Rudra. Faq: questions asked frequently. In Proceedings of the 35th ACM SIGMOD-SIGACT-SIGAI Symposium on Principles of Database Systems, pages 13–28, 2016. doi:10.1145/2902251.2902280.
  • [2] Antoine Amarilli, Marcelo Arenas, YooJung Choi, Mikaël Monet, Guy Van den Broeck, and Benjie Wang. A circus of circuits: Connections between decision diagrams, circuits, and automata. CoRR, abs/2404.09674, 2024. doi:10.48550/arXiv.2404.09674.
  • [3] Antoine Amarilli, Pierre Bourhis, Florent Capelli, and Mikaël Monet. Ranked enumeration for MSO on trees via knowledge compilation. In Graham Cormode and Michael Shekelyan, editors, 27th International Conference on Database Theory, ICDT 2024, Paestum, Italy, March 25-28, 2024, volume 290 of LIPIcs, pages 25:1–25:18. Schloss Dagstuhl – Leibniz-Zentrum für Informatik, 2024. doi:10.4230/LIPIcs.ICDT.2024.25.
  • [4] Antoine Amarilli, Pierre Bourhis, Louis Jachiet, and Stefan Mengel. A circuit-based approach to efficient enumeration. In Ioannis Chatzigiannakis, Piotr Indyk, Fabian Kuhn, and Anca Muscholl, editors, 44th International Colloquium on Automata, Languages, and Programming, ICALP 2017, Warsaw, Poland, July 10-14, 2017, volume 80 of LIPIcs, pages 111:1–111:15. Schloss Dagstuhl – Leibniz-Zentrum für Informatik, 2017. doi:10.4230/LIPIcs.ICALP.2017.111.
  • [5] Antoine Amarilli and Florent Capelli. Tractable circuits in database theory. SIGMOD Rec., 53(2):6–20, 2024. doi:10.1145/3685980.3685982.
  • [6] Marcelo Arenas, Pablo Barceló, Leopoldo E. Bertossi, and Mikaël Monet. On the complexity of shap-score-based explanations: Tractability via knowledge compilation and non-approximability results. J. Mach. Learn. Res., 24:63:1–63:58, 2023. URL: https://jmlr.org/papers/v24/21-0389.html.
  • [7] Guillaume Bagan, Arnaud Durand, and Etienne Grandjean. On acyclic conjunctive queries and constant delay enumeration. In Jacques Duparc and Thomas A. Henzinger, editors, Computer Science Logic, 21st International Workshop, CSL 2007, 16th Annual Conference of the EACSL, Lausanne, Switzerland, September 11-15, 2007, Proceedings, volume 4646 of Lecture Notes in Computer Science, pages 208–222. Springer, 2007. doi:10.1007/978-3-540-74915-8_18.
  • [8] Guillaume Bagan, Arnaud Durand, Etienne Grandjean, and Frédéric Olive. Computing the jth solution of a first-order query. RAIRO-Theoretical Informatics and Applications, 42(1):147–164, 2008. doi:10.1051/ITA:2007046.
  • [9] Paul Beame, Jerry Li, Sudeepa Roy, and Dan Suciu. Lower bounds for exact model counting and applications in probabilistic databases. In Proceedings of the Twenty-Ninth Conference on Uncertainty in Artificial Intelligence, 2013.
  • [10] Paul Beame, Jerry Li, Sudeepa Roy, and Dan Suciu. Counting of query expressions: Limitations of propositional methods. In Proc. 17th International Conference on Database Theory (ICDT), pages 177–188, 2014. doi:10.5441/002/ICDT.2014.20.
  • [11] Leopoldo E. Bertossi, Benny Kimelfeld, Ester Livshits, and Mikaël Monet. The shapley value in database management. SIGMOD Rec., 52(2):6–17, 2023. doi:10.1145/3615952.3615954.
  • [12] Karl Bringmann, Nofar Carmeli, and Stefan Mengel. Tight fine-grained bounds for direct access on join queries. In Proceedings of the 41st ACM SIGMOD-SIGACT-SIGAI Symposium on Principles of Database Systems, pages 427–436, 2022. doi:10.1145/3517804.3526234.
  • [13] Randal E Bryant. Graph-based algorithms for boolean function manipulation. Computers, IEEE Transactions on, 100(8):677–691, 1986. doi:10.1109/TC.1986.1676819.
  • [14] Florent Capelli and Oliver Irwin. Direct access for conjunctive queries with negations. In Graham Cormode and Michael Shekelyan, editors, 27th International Conference on Database Theory, ICDT 2024, Paestum, Italy, March 25-28, 2024, volume 290 of LIPIcs, pages 13:1–13:20. Schloss Dagstuhl – Leibniz-Zentrum für Informatik, 2024. doi:10.4230/LIPIcs.ICDT.2024.13.
  • [15] Florent Capelli, Oliver Irwin, and Sylvain Salvati. A simple algorithm for worst case optimal join and sampling. In Sudeepa Roy and Ahmet Kara, editors, 28th International Conference on Database Theory, ICDT 2025, Barcelona, Spain, March 25-28, 2025, volume 328 of LIPIcs, pages 23:1–23:19. Schloss Dagstuhl – Leibniz-Zentrum für Informatik, 2025. doi:10.4230/LIPIcs.ICDT.2025.23.
  • [16] Nofar Carmeli, Nikolaos Tziavelis, Wolfgang Gatterbauer, Benny Kimelfeld, and Mirek Riedewald. Tractable orders for direct access to ranked answers of conjunctive queries. ACM Transactions on Database Systems, January 2023. doi:10.1145/3578517.
  • [17] Nofar Carmeli, Shai Zeevi, Christoph Berkholz, Benny Kimelfeld, and Nicole Schweikardt. Answering (unions of) conjunctive queries using random access and random-order enumeration. In Proceedings of the 39th ACM SIGMOD-SIGACT-SIGAI Symposium on Principles of Database Systems, pages 393–409, 2020. doi:10.1145/3375395.3387662.
  • [18] Ashok K Chandra and Philip M Merlin. Optimal implementation of conjunctive queries in relational data bases. In Proceedings of the ninth annual ACM symposium on Theory of computing, pages 77–90, 1977. doi:10.1145/800105.803397.
  • [19] Edgar F Codd. A relational model of data for large shared data banks. Communications of the ACM, 13(6):377–387, 1970. doi:10.1145/362384.362685.
  • [20] Thomas H Cormen, Charles E Leiserson, Ronald L Rivest, and Clifford Stein. Introduction to algorithms. MIT press, 2022.
  • [21] A. Darwiche. Decomposable negation normal form. J. ACM, 48(4):608–647, 2001. doi:10.1145/502090.502091.
  • [22] Adnan Darwiche. On the tractable counting of theory models and its application to truth maintenance and belief revision. Journal of Applied Non-Classical Logics, 11(1-2):11–34, 2001. doi:10.3166/JANCL.11.11-34.
  • [23] Adnan Darwiche and Pierre Marquis. A Knowledge Compilation Map. Journal of Artificial Intelligence Research, 17:229–264, 2002. doi:10.1613/JAIR.989.
  • [24] Arnaud Durand and Stefan Mengel. Structural tractability of counting of solutions to conjunctive queries. Theory Comput. Syst., 57(4):1202–1249, 2015. doi:10.1007/S00224-014-9543-Y.
  • [25] Idan Eldar, Nofar Carmeli, and Benny Kimelfeld. Direct access for answers to conjunctive queries with aggregation. arXiv preprint arXiv:2303.05327, 2023. doi:10.48550/arXiv.2303.05327.
  • [26] Johannes K Fichte, Markus Hecher, Neha Lodha, and Stefan Szeider. An smt approach to fractional hypertree width. In Principles and Practice of Constraint Programming: 24th International Conference, Lille, France, August 27-31, 2018, Proceedings 24, pages 109–127. Springer, 2018.
  • [27] Georg Gottlob, Nicola Leone, and Francesco Scarcello. Hypertree decompositions and tractable queries. In Proceedings of the eighteenth ACM SIGMOD-SIGACT-SIGART symposium on Principles of database systems, pages 21–32. ACM, 1999. doi:10.1145/303976.303979.
  • [28] Martin Grohe and Dániel Marx. Constraint solving via fractional edge covers. ACM Transactions on Algorithms (TALG), 11(1):4, 2014.
  • [29] David Harvey and Joris Van Der Hoeven. Integer multiplication in time o(nlog\,n). Annals of Mathematics, 193(2):563–617, 2021.
  • [30] Jinbo Huang and Adnan Darwiche. DPLL with a trace: From SAT to knowledge compilation. In Proceedings of the Nineteenth International Joint Conference on Artificial Intelligence, pages 156–162, 2005. URL: http://ijcai.org/Proceedings/05/Papers/0876.pdf.
  • [31] Manas R Joglekar, Rohan Puttagunta, and Christopher Ré. Ajar: Aggregations and joins over annotated relations. In Proceedings of the 35th ACM SIGMOD-SIGACT-SIGAI Symposium on Principles of Database Systems, pages 91–106, 2016. doi:10.1145/2902251.2902293.
  • [32] Rafael Kiesel and Thomas Eiter. Knowledge compilation and more with sharpsat-td. In Pierre Marquis, Tran Cao Son, and Gabriele Kern-Isberner, editors, Proceedings of the 20th International Conference on Principles of Knowledge Representation and Reasoning, KR 2023, Rhodes, Greece, September 2-8, 2023, pages 406–416, 2023. doi:10.24963/KR.2023/40.
  • [33] Benny Kimelfeld, Wim Martens, and Matthias Niewerth. A formal language perspective on factorized representations. In Sudeepa Roy and Ahmet Kara, editors, 28th International Conference on Database Theory, ICDT 2025, Barcelona, Spain, March 25-28, 2025, volume 328 of LIPIcs, pages 20:1–20:20. Schloss Dagstuhl – Leibniz-Zentrum für Informatik, 2025. doi:10.4230/LIPIcs.ICDT.2025.20.
  • [34] Tuukka Korhonen and Matti Järvisalo. Integrating Tree Decompositions into Decision Heuristics of Propositional Model Counters. In Laurent D. Michel, editor, 27th International Conference on Principles and Practice of Constraint Programming (CP 2021), volume 210 of Leibniz International Proceedings in Informatics (LIPIcs), pages 8:1–8:11, Dagstuhl, Germany, 2021. Schloss Dagstuhl – Leibniz-Zentrum für Informatik. doi:10.4230/LIPIcs.CP.2021.8.
  • [35] Jean-Marie Lagniez and Pierre Marquis. An improved decision-dnnf compiler. In Carles Sierra, editor, Proceedings of the Twenty-Sixth International Joint Conference on Artificial Intelligence, IJCAI 2017, Melbourne, Australia, August 19-25, 2017, pages 667–673. ijcai.org, 2017. doi:10.24963/IJCAI.2017/93.
  • [36] Kuldeep S. Meel and Alexis de Colnet. #cfg and #dnnf admit FPRAS. CoRR, abs/2406.18224, 2024. doi:10.48550/arXiv.2406.18224.
  • [37] Hung Q. Ngo. Worst-Case Optimal Join Algorithms: Techniques, Results, and Open Problems. In Proceedings of the 37th ACM SIGMOD-SIGACT-SIGAI Symposium on Principles of Database Systems, pages 111–124. ACM, 2018. doi:10.1145/3196959.3196990.
  • [38] Hung Q. Ngo, Ely Porat, Christopher Ré, and Atri Rudra. Worst-case optimal join algorithms: [extended abstract]. In Michael Benedikt, Markus Krötzsch, and Maurizio Lenzerini, editors, Proceedings of the 31st ACM SIGMOD-SIGACT-SIGART Symposium on Principles of Database Systems, PODS 2012, Scottsdale, AZ, USA, May 20-24, 2012, pages 37–48. ACM, 2012. doi:10.1145/2213556.2213565.
  • [39] Hung Q Ngo, Ely Porat, Christopher Ré, and Atri Rudra. Worst-case optimal join algorithms. Journal of the ACM (JACM), 65(3):1–40, 2018. doi:10.1145/3180143.
  • [40] Dan Olteanu. Factorized databases: A knowledge compilation perspective. In Adnan Darwiche, editor, Beyond NP, Papers from the 2016 AAAI Workshop, Phoenix, Arizona, USA, February 12, 2016, volume WS-16-05 of AAAI Technical Report. AAAI Press, 2016. URL: http://www.aaai.org/ocs/index.php/WS/AAAIW16/paper/view/12638.
  • [41] Dan Olteanu and Jiewen Huang. Using obdds for efficient query evaluation on probabilistic databases. In International Conference on Scalable Uncertainty Management, pages 326–340. Springer, 2008. doi:10.1007/978-3-540-87993-0_26.
  • [42] Dan Olteanu and Jakub Zavodny. Factorised representations of query results: size bounds and readability. In Alin Deutsch, editor, 15th International Conference on Database Theory, ICDT ’12, Berlin, Germany, March 26-29, 2012, pages 285–298. ACM, 2012. doi:10.1145/2274576.2274607.
  • [43] Dan Olteanu and Jakub Závodný. Size Bounds for Factorised Representations of Query Results. ACM Transactions on Database Systems, 40(1):1–44, March 2015. doi:10.1145/2656335.
  • [44] Reinhard Pichler and Sebastian Skritek. Tractable counting of the answers to conjunctive queries. Journal of Computer and System Sciences, 79(6):984–1001, September 2013. doi:10.1016/J.JCSS.2013.01.012.
  • [45] Tian Sang, Fahiem Bacchus, Paul Beame, Henry A Kautz, and Toniann Pitassi. Combining component caching and clause learning for effective model counting. Theory and Applications of Satisfiability Testing, 4:7th, 2004.
  • [46] Andy Shih, Guy Van den Broeck, Paul Beame, and Antoine Amarilli. Smoothing structured decomposable circuits. In Hanna M. Wallach, Hugo Larochelle, Alina Beygelzimer, Florence d’Alché-Buc, Emily B. Fox, and Roman Garnett, editors, Advances in Neural Information Processing Systems 32: Annual Conference on Neural Information Processing Systems 2019, NeurIPS 2019, December 8-14, 2019, Vancouver, BC, Canada, pages 11412–11422, 2019. URL: https://proceedings.neurips.cc/paper/2019/hash/940392f5f32a7ade1cc201767cf83e31-Abstract.html.
  • [47] Robert E. Tarjan and Mihalis Yannakakis. Simple linear-time algorithms to test chordality of graphs, test acyclicity of hypergraphs, and selectively reduce acyclic hypergraphs. SIAM J. Comput., 13(3):566–579, July 1984. doi:10.1137/0213035.
  • [48] Timothy van Bremen and Kuldeep S Meel. Probabilistic query evaluation: The combined fpras landscape. In Proceedings of the 42nd ACM SIGMOD-SIGACT-SIGAI Symposium on Principles of Database Systems, pages 339–347, 2023. doi:10.1145/3584372.3588677.
  • [49] Todd Veldhuizen. Triejoin: A Simple, Worst-Case Optimal Join Algorithm. Proceedings of the 17th International Conference on Database Theory (ICDT), Athens, Greece, 2014, 17(13):96–106, 2014. doi:10.5441/002/ICDT.2014.13.
  • [50] Mihalis Yannakakis. Algorithms for Acyclic Database Schemes. In Proceedings of the Seventh International Conference on Very Large Data Bases - Volume 7, pages 82–94. VLDB Endowment, 1981.