Accelerating lemma learning using joins - DPLL( t) Nikolaj Bjørner Bruno Dutertre

Accelerating lemma learning using joins - DPLL( t) Nikolaj Bjørner Bruno Dutertre
Accelerating lemma learning using joins - DPLL(t)
Nikolaj Bjørner
Microsoft Research
Bruno Dutertre
SRI International
Leonardo de Moura
Microsoft Research
Abstract
State-of-the-art satisfiability modulo theory solvers use a combination of the Davis-PutnamLogemann-Loveland (DPLL) procedure for performing Boolean search and an integration of theory
solvers for identifying theory conflicts. Theory conflicts are presented as clauses over the propositional vocabulary that prune the DPLL search. This combination is often highly effective, as propositional reasoning is handled by state-of-the-art methods for propositional satisfiability, while theory
solvers can be invoked incrementally as the DPLL core asserts literals. However, there are several
cases where this integration misses short proofs if the short proofs require additional literals that
are not part of the input. We present a method based on joins for identifying a sufficient basis of
additional literals and lemmas that can speed up proof search for DPLL with theories exponentially.
We then compare variants of the proposed methods with proof systems based on superposition and
resolution. The theoretical result is that general formulations of joins are equivalent in succinctness
to superposition and resolution.
1 Introduction
Abstract interpretation and theorem proving are both used in program verification but they traditionally approach the problem from different perspectives. Abstract interpretation focuses on automatically
generating program invariants [1] whereas theorem proving is used to verify that given assertions are
invariant. However, the concept of logical interpretation [5] shows that deductive methods based on
theorem proving can be used to build abstract interpreters. In this paper, we examine the opposite issue,
namely, the use of abstraction techniques in automated theorem proving. More specifically, our goal is to
improve performance of Satisfiability Modulo Theory (SMT) solvers by generating useful lemmas using
abstraction.
SMT solvers decide the satisfiability of formulas in logical theories such as linear arithmetic, the
theory of arrays, and bitvectors. Most SMT solvers use the DPLL(T ) architecture. They combine a
Boolean satisfiability solver based on the Davis-Putnam-Logemann-Loveland procedure (DPLL) with
a theory solver that can decide satisfiability of conjunctions of atoms in a specific theory T [2]. In
the last few years, specialized theory solvers and the development of new integration methods have led
to dramatic performance improvement in SMT solving. Still, there are “easy” formulas that cannot
be solved efficiently using the standard DPLL(T ) model, because the literals that are necessary for a
short proof are not present in the original formula. This problem has been recognized in the setting of
difference logic constraints [6], where a solution based on adding atoms based on transtivity of inequality
was investigated. We present a method based on abstraction for cheaply discovering additional literals
and lemmas. Essentially, the method discovers atomic facts that are implied by both side of a disjunction
Φ1 ∨ Φ2 , which can drastically reduce the search space by avoiding extraneous case splits. Formula (1)
motivated some of the techniques presented here. It is an abstraction of a pattern seen in verification
conditions from program verification tools. The pattern corresponds roughly to propagating weakest
preconditions over branch statements.
2 DPLL(T ) as a Non-deterministic Transition System
The DPLL(T ) procedure for satisfiability modulo theories is a combination of the DPLL algorithm for
Boolean satisfiability and a theory solver for a theory T . In this paper, we focus on the quantifier-free
1
DPLL(t)
M || F =⇒
Bjørner, Dutertre, and de Moura
M `d || F
M || F, C ∨ ` =⇒
M `C∨` || F
if
` or ` occurs in F
` unassigned in M
(Decide)
if
` unassigned in M
M
¬C
(UnitPropagate)

` unassigned in M


 ` or ` occurs in F
if
T ` C ∨`



¬C
M
M || F =⇒ M `C∨` || F
M || F, C =⇒ M || F, C || C
M || F =⇒ M || F, C || C
M || F || C 0 ∨ ` =⇒ M || F || C ∨ C 0
(T -Propagate)
if M
¬C
T `C
if
¬C
M
(Conflict)
if `C∨` ∈ M
(Resolve)
M `d0 M 0 || F || C ∨ ` =⇒ M `C∨` || F, C ∨ ` if M
¬C
(T -Conflict)
(Backjump)
Figure 1: Abstract DPLL(T ) Procedure
theory of pure equalities (called E).
Given a quantifier-free formula φ, we denote that φ is valid in T by T ` φ. A theory solver for T is
an algorithm for deciding the satisfiability of conjunction of ground literals of T . Dually, a theory solver
can decide whether T ` `1 ∨ . . . ∨ `n holds, where `1 , . . . , `n are ground literals.
The DPLL(T ) procedure starts with a formula φ written in conjunctive normal form. It searches
for a truth assignment that satisfies all the clauses of φ and is consistent with respect to theory T . The
search can be described by the transition system of Figure 1. The system states are of the form M || F or
M || F || C where M is a partial truth assignment, F is a set of clause, and C is a clause.
The assignment M is represented as a finite sequence of the form `e11 . . . `enn , where `i is a literal and
ei is an explanation. For every i, the explanation is either the symbol d, in which case `i is a decision
literal, or a clause C that explains why `i must be assigned. The explanation clause is used during
conflict resolution. The assignment is implicitly divided in segments of successive decision levels, where
the decision level of a literal `i is the number of decisions in M prior to its occurrence. In states of the
form M || F , the procedure attempts to extend the current truth assignment by using the unit and theory
propagation rules or the decision rule. A conflict is detected when the assignment M falsifies a clause
C of F (rule Conflict) or when M is not consistent with respect to the theory (rule T -Conflict). In both
cases, the system moves to a conflict state of the form M || F || C. In any such state, it can be shown
¬C). The rules Resolve and Backjump correspond to
that the clause C is false in M (written M
conflict-driven clause learning employed by modern SAT solvers. Resolve constructs a new conflict
clause C ∨ C 0 by applying resolution. Backjump is applicable when the conflict clause has a unique
literal ` of maximal decision level. The conflict clause is then added to F , backtracking is performed
(i.e., literal assignments are undone), then ` is assigned as implied by C ∨ l and the search can continue
from a consistent state.
DPLL(T ) terminates when none of the rules of Figure 1 is applicable. This can happen in a state
M || F where all literals of F are assigned. In such a case, M is a full assignment that satisfies all the
2
DPLL(t)
Sup
Bjørner, Dutertre, and de Moura
C ∨ a'b
D[a]
C ∨ D[b]
E-Res
C ∨ `
Res
C ∨ a 6' a
C
D ∨ ¬`
C ∨D
Fact
E-Fact
C ∨ a'b ∨ a'c
C ∨ a ' b ∨ b 6' c
C ∨ ` ∨`
C ∨ `
Figure 2: The SP(E) calculus
clauses of F and is consistent with respect to T . In other words, the initial formula φ is satisfiable.
The other terminal states are of the form M || F || 2 where 2 is the empty clause. In such a case, φ is
unsatisfiable. Proof of termination and details can be found in [2].
2.1 A Superposition Calculus SP(E)
Figure 2 summarizes basic superposition inference rules for the theory of pure ground equalities. It is a
simple instance of more general and complete superposition calculi for the first-order theory of equality,
but in this paper we will only consider equalities between constants, and we omit ordering constraints in
side conditions on the rules (SP(E) is finitely saturating without orderings). By D[a] we refer to the 0
or more, but not necessarily all, of the a positions in D, these selected as are replaced by b in D[b].
3 A Hard Formula for DPLL(E)
Consider the unsatisfiable formula (1) (and illustrated in Figure 3) also used in [3], and present in the
2008 SMT competition for the EUF division (http://www.smtcomp.org).
a1 6' a50 ∧
49
^
[(ai ' bi ∧ bi ' ai+1 ) ∨ (ai ' ci ∧ ci ' ai+1 )]
(1)
i=1
b1
a1
a2
c1
a4
a3
c2
b49
b3
b2
·
c3
a49
a50
c49
Figure 3: Diamond equalities
The formula is unsatisfiable because in every diamond, it is the case that ai ' ai+1 because either
ai ' bi ∧ bi ' ai+1 or ai ' ci ∧ ci ' ai+1 . Therefore, by repeating this argument for every i, we
end up with the implied equality a1 ' a50 . This contradicts the disequality a1 6' a50 . A proof search
method directly based on DPLL(E) is not able to produce a succinct proof like the informal justification
just given. In a propositional abstraction of the problem, each of the equalities ai ' bi , bi ' ai+1 ,
ai ' ci , ci ' ai+1 and a1 ' a50 is treated as a propositional variable. Because the atoms ai ' ai+1
are not present DPLL assigns truth values to the propositional variables, and a decision procedure for
equalities detects a contradiction only when for every i = 1, . . . , 49 ai ' ai+1 follows from either
ai ' bi ∧ bi ' ai+1 or ai ' ci ∧ ci ' ai+1 . There are 249 different such equality conflicts, none of which
subsumes the other. There is no short unsatisfiability proof that uses only the original atoms.
3
DPLL(t)
Bjørner, Dutertre, and de Moura
On the other hand, the formula has a short proof in SP(E). More, generally, every proof in DPLL(E)
can be simulated by a proof of equal length in SP(E), but not conversely. We write F1 F2 if
every proof in the formal system F2 can be reduced to a proof in the formal system F1 using at most a
polymomial overhead; ≡ is used if reduction is possible in both directions and ≺ holds if the reduction
only holds in one direction. To summarize:
Theorem 3.1. SP(E) ≺ DPLL(E).
4 A Sufficient Basis of Literals
There is a very simple way of augmenting DPLL(T ) to allow it to simulate SP(E): First create the set
∆ consisting of all literals of the form a ' b, where a and b are constants in the original formula F .
Then allow these literals to participate in the Decide and propagation rules. For reference, we call the
resulting system DPLL(E + ∆).
Theorem 4.1. SP(E) ≡ DPLL(E + ∆). In particular, any superposition inference can be simulated by
DPLL(E + ∆).
The set ∆ is quadratic in the size of the input, so additional techniques are needed to make this
approach efficient, but then neither does SP(E) provide any built-in guidance.
5 A Solution Based on Joins
Our approach to solving such problems efficiently is based on ideas from abstract interpretation. It is
based on the availability of a join operator on constraints maintained by theory solvers to discover atomic
facts that are implied by both sides of a disjunction or case split.
To describe the basic procedure in the context of DPLL(T ), consider a state M || F where M does
not contain decision literals (literals annotated as `d ). We can then choose an unassigned propositional
variable p; first assign it to true, perform UnitPropagate and T -Propagate to derive all consequences
of p to obtain the context M1 , second assign p to false and perform the same propagation to obtain the
context M2 . We then use an operator t such that M1 t M2 is a set of literals that are implied by M1 and
M2 to compute a joint set of implied literals. The rule can be formulated in the context of the abstract
transition system for DPLL(T ) as an inference rule t11 :
M pd || F =⇒ M1 || F
M ¬pd || F =⇒ M2 || F
p is the only decision variable in M1 , M2
t11
M || F =⇒ M1 t M2 || F
For the propositional case, the resulting system is reminiscent of Stålmarck’s method [4], except, that
method also allows learning equivalences between literals. The rule allows some proof-acceleration in
formulas like (1), but it is also limited as we have:
Theorem 5.1. SP(E) ≺ DPLL(E + t11 ) ≺ DPLL(E).
5.1 Joining Equalities
Let E be the equivalence
classes of a set of constants at state M . So for every e, e0 ∈ E if e 6= e0 then
S
0
e ∩ e = ∅, and E consists of all the constants in M . For a given constant t, associate E(t) as the class
in E such that t ∈ E(t) ∈ E. We can characterize the join of two partitions as:
[
E1 t E2 := {E1 (t) ∩ E2 (t) | t ∈
E}
(2)
4
DPLL(t)
Bjørner, Dutertre, and de Moura
Also, the set of equalities associated with a partition is then just a spanning tree of equalities per equivalence class.
5.2 Generalized Join
There is an obvious limitation to the rule t11 : It can only be applied when M does not contain decision
literals. Consequently, it allows only learning units facts. The limitation is on purpose: the rule requires
at most a quadratic number of applications (based on the number of atoms in F ) to either assign all
literals, or saturate. The more generic formulation of the inference rule is to allow it being applied at any
level and add new literals to M without these being unit facts. For reference, we will call this system
DPLL(E + tω ). The definition of joins will then have to be adjusted so that explanations are tracked
correctly when literals are joined. We will not give the full details of DPLL(E + tω ), instead we will
arrive at a system that is equally succinct as the one just sketched. But we do so the hard way to examine
the limitations of the more conservative liftings of DPLL(E + t11 ).
5.3 k-lookaheads
The rule t11 allows for splitting on a single atom p. The implied consequences of the different cases
for p are then combined. We say that this approach uses one lookahead. One lookahead is not always
sufficient for learning the right implied facts. Consider a simple extension of the diamond problem given
in equation (3), and illustrated in Figure 4.
a1 6' a50
b2
b1
c1
a1
d1


(ai ' bi ∧ bi ' ai+1 )
 ∨ (ai ' ci ∧ ci ' ai+1 ) 
∧
i=1
∨ (ai ' di ∧ di ' ai+1 )
49
^
a2
c2
d2
b49
b3
a3
c3
(3)
a4
·
a49
c49
a50
d49
d3
Figure 4: Double diamond equalities
In order to learn that a0 ' a1 we now need two splits. The obvious generalization of rule t11 is to
combine multiple branches in a join. We call the resulting system DPLL(t1k ) where k are the number
of lookaheads admitted. Note that k lookaheads produce up to 2k branches. It admits short proofs for
formulas such as (3), but it can still be simulated by SP(E).
Theorem 5.2. SP(E) ≺ DPLL(E + t1k ) ≺ DPLL(E + t11 ) ≺ DPLL(E).
5.4 m-disjunctions
The inequality in Theorem 5.2 is strict, as can be seen from the formula in (4) and Figure 5.
a1 6' a50 ∧
49
^
(ai ' ai+1 ∨ ai ' bi+1 ) ∧
49
^
(bi ' ai+1 ∨ bi ' bi+1 ) ∧ b50 ' a50
i=2
i=1
5
(4)
DPLL(t)
Bjørner, Dutertre, and de Moura
a2
a3
a4
a5
·
a1
b2
b3
b4
·
·
b5
a48
·
b48
a49
a50
b49
b50
Figure 5: Butterfly equalities
1
Let DPLL(E + tm
k ) be the extension of DPLL(E + tk ) where join may return not only units but
disjunctions with up to m literals. This is also known as disjunctive join. Instead of adding non-units to
M the resulting (non-unit) clauses are added to F . We also don’t need to examine 2k branches because
we can trade additional disjunctions for explored branches. Finally, the resulting system is equivalent to
SP(E) in succinctness:
Theorem 5.3. SP(E) ≡ DPLL(E + tm
k ).
6 Conclusions
We have examined the following equivalently succinct systems:
ω
SP(E) ≡ DPLL(E + ∆) ≡ DPLL(E + tm
k ) ≡ DPLL(E + t )
so what is the difference in practice? The advantages of DPLL(T ) have been the availability of spaceefficient and adaptive search techniques developed in the context of SAT solvers. The advantage of using
t was that we could combine results from different branches into unit facts or lemmas. In future work we
examine the more general problem of the quantifier-free theory of uninterpreted functions with equality,
as well as describe applying the framework on selected theories, such as the theory of arrays. There are
inherent theoretical limitations in the approaches studied so far. For example, the pigeon hole principle
can be encoded as:


^ _
^

di ' rj  ∧
di 6' dj
(5)
i≤m j<m
i<j≤m
There are no short superposition proofs of unsatisfiability for this formula, but there are short proofs in
Frege systems, which amounts to short proofs if arbitrary literals and definitions (cuts) can be introduced.
References
[1] P. Cousot and R. Cousot. Abstract interpretation: a unified lattice model for static analysis of programs by
construction or approximation of fixpoints. In POPL-14, pages 238–252, Los Angeles, California, 1977. ACM
Press, New York, NY.
[2] R. Niewenhuis, A. Oliveras, and C. Tinelli. Solving SAT and SAT modulo theories: From an abstract DavisPutnam-Logemann-Loveland procedure to DPLL(T). Journal of the ACM, 53(6):937–977, November 2006.
[3] M. Rozanov and O. Strichman. Generating minimum transitivity constraints in P-time for deciding equality
logic. In SMT 2007, volume 198 of ENTCS, pages 3–17, 2007.
[4] Mary Sheeran and Gunnar Stålmarck. A Tutorial on Stålmarck’s Proof Procedure for Propositional Logic.
Formal Methods in System Design, 16(1):23–58, 2000.
[5] A. Tiwari and S. Gulwani. Logical interpretation: Static program analysis using theorem proving. In F. Pfenning, editor, CADE-21, volume 4603 of LNAI, pages 147–166. Springer, 2007.
[6] Chao Wang, Aarti Gupta, and Malay Ganai. Predicate learning and selective theory deduction for a difference
logic solver. In DAC ’06: Proceedings of the 43rd annual conference on Design automation, pages 235–240,
New York, NY, USA, 2006. ACM.
6
DPLL(t)
A
Bjørner, Dutertre, and de Moura
Proof Outlines
Sketch proof of Theorem 3.1. The theorem states that SP(E) ≺ DPLL(E). Formula (1) shows that
DPLL(E) 6 SP(E), so it suffices to establish that SP(E) DPLL(E). Thus, every DPLL(E) proof
can be directly simulated in SP(E). First notice that DPLL induces a propositional resolution proof. In
fact the conflict resolution steps derive the conflict clause using a sequence of resolution steps based on
clauses that annotate the literals in the context M . These clauses are either extracted from the original
formula F or obtained from conflict resolution. Second, let us examine T -Propagate and T -Conflict.
These rules supply additional T -lemmas (clauses) into the produced proofs. SP(E) cannot directly
derive T -lemmas, so we cannot just replace these lemmas by superposition steps. Instead, consider a
supoerposition
proof-tree that contains T -lemmas. In the theory of equality all T lemmas are of the form
Wk−1
a1 ' ak ∨ i=1
ai 6' ai+1 . We will show how to eliminate T -lemmas from a proof tree, starting from
the lower-most occurrences of T -lemmas. So suppose that a ' c ∨ a 6' b ∨ b 6' c is a lower-most
T -lemma in a proof-tree. Then there are nodes labeled by C ∨ a ' b, D ∨ b ' c, and E ∨ a 6' c that
resolve with the literals from the T -lemma (and there are other nodes that resolve with literals in C, D
and E). Apply rule Sup to C ∨ a ' b, D ∨ b ' c to obtain the clause C ∨ D ∨ a ' c. Then apply Sup
on the result and E ∨ a 6' c, to obtain C ∨ D ∨ E ∨ a 6' a. Use E-Fact to remove the last disequality.
The remaining literals can be resolved using the same clauses that were used in the original proof. By
repeating this argument, we can eliminate all T -lemmas.
Remark 1. Note that we are giving SP(E) some flexibility. In particular, we do not refer to any term
orderings in the side-conditions. The succinctness results for SP(E) would not work if one requires
a total ordering on all constants and that the superposition rules respect these. For example, create the
disjunction of formula (1) and another copy of it, but swap ai and bi in the second copy. We claim that a
good ordering for the (1) is a bad ordering for the second copy, and vice versa. So the disjunction does
not have a short proof if a total ordering on ground constants is required.
Sketch proof of Theorem 4.1. By case analysis, where we consider the rules specific to SP(E):
Sup
C ∨ a'b
D[a]
C ∨ D[b]
It can be simulated in DPLL(E + ∆) in the following way: Use Decide to build the context with C and
D[b]. By unit propagation deduce a ' b. By congruence deduce D[a] (conflict with clause D[a]). Use
all decided conflict resolution strategy to get (C ∨ D[b]).
The all decided conflict resolution strategy consists in applying (Resolve) until the clause C
inM || F || C contains only decided literals.
E-Res
C ∨ a 6' a
C
DPLL(T ) keeps the clauses fully simplified.
E-Fact
C ∨ a'b ∨ a'c
C ∨ a ' b ∨ b 6' c
Use Decide to build the context with C, a 6' b, b ' c. By unit propagation deduce a ' c. From a 6' b
and a ' c deduce b 6' c (conflict) Use all decided conflict resolution strategy to get C ∨ a ' b ∨ b 6' c.
7
DPLL(t)
Bjørner, Dutertre, and de Moura
So, any SP(E) proof can be simulated by DPLL(E + ∆).
The converse direction, that any DPLL(E + ∆) proof can be simulated by SP(E), follows from the
proof of Theorem 3.1.
Sketch proof of Theorem 5.1. Example (1) has a linear size proof in DPLL(E +t11 ) but not in DPLL(E).
Using Tseitsin’s translation into clausal form, the sub-formula a1 ' b1 ∧ b1 ' a2 is associated with a
predicate p1 , and similarly, the subformula a1 ' c1 ∧ c1 ' a2 is associated with a fresh predicate q1 ,
and the clauses (p1 ∨ q1 ), (¬p1 ∨ a1 ' b1 ), (¬p1 ∨ b1 ' a2 ), (¬q1 ∨ a1 ' c1 ), (¬q1 ∨ c1 ' a2 ) are
added. Similarly, all the other conjunctions are represented using proxies. The proof in DPLL(E + t11 )
is obtained by first splitting on p1 . In the branch where p1 is asserted, both a1 ' b1 and b1 ' a2 are
asserted. From these two equalities it follows that a1 ' a2 . In the branch where ¬p1 is asserted, unitpropagation over the clause p1 ∨q1 ensures that q1 is asserted. Similarly a1 ' c1 and c1 ' a2 get asserted
and therefore also a1 ' a2 is learned. It therefore follows that DPLL(E + t11 ) ≺ DPLL(E).
Formula (3) shows that DPLL(E + t11 ) 6 SP(E) because the corresponding clausification of the
formula produces instead of (p1 ∨ q1 ) the clause (p1 ∨ q1 ∨ r1 ), and adds ¬r1 ∨ a1 ' d1 , ¬r1 ∨ d1 ' a2 .
Splitting on any of ¬p1 , ¬q1 or ¬r1 does not allow propagating any equalities because these assignments
don’t imply any equalities directly and the clause (p1 ∨ q1 ∨ r1 ) cannot yet be used for unit-propagation.
Two splits are required to learn any equalities, and in particular learn that a1 ' a2 .
We finally show that SP(E) DPLL(E +t11 ). Thus, we need to simulate proofs in DPLL(E +t11 )
using SP(E). The new proof rule t11 is simulated by using the decision variable as the selected literal
for resolution. The literals learned in one branch correspond to the clauses p ∨ `i , for i = 1, . . . , k for
some k. The literals learned in the other branch correspond to clauses ¬p ∨ `0j , for j = 1, . . . , m. All
binary clauses in the cross-product can therefore be derived as well. Suppose ` ∈ M1 t M2 . Then, ` is
already in M or there is a sequence of super-position steps from one of the binary clauses `i ∨ `0j such
that factoring applies to produce a single learned literal.
Sketch proof of Theorem 5.2. Formula (3) has a linear size proof in DPLL(E + t1k ) but not in
DPLL(E + t11 ). This establishes that DPLL(E + t1k ) ≺ DPLL(E + t11 ). Formula (4) can be used
to establish that DPLL(E + t1k ) 6 SP(E).
Establishing that SP(E) DPLL(E + t1k ) is a direct extension of the argument for SP(E) DPLL(E + t11 ): Consider the pairwise join of branches that have all but one assignment to a decision
literal in common. The argument from Theorem 5.1 can be used in this case to derive a clause that
contains the joined literal and all other decision variables. The clauses produced in this way can be
resolved with each-other leaving just the new literals.
Sketch proof of Theorem 5.3. Establishing SP(E) DPLL(E + tkm ) follows by extending the arguments from the sketch proofs of Theorems 5.1 and 5.2. The difference is that we don’t necessarily
need to apply factoring to produce a unit literal. Similar to the proof of Theorem 4.1, we show that
DPLL(E + tkm ) SP(E) examining each rule of SP(E).
d
Sup: To simulate Sup we guess first C . This causes a ' b to be added using UnitPropagate.
The context is thus Ca ' b || F, C ∨ a ' b, D[a]. Then guess all variants of the literals in D[a]. The
corresponding copies of D[b] are implied by the equality a ' b. The resulting joined clause is the desired
resolvent C ∨ D[b].
d
E-Fact: First guess C , then guess (a 6' b)d . This causes a ' c to be derived using UnitPropagate.
d
The context is thus C , (a 6' b)d , a ' c || F, C ∨ a ' b ∨ a ' c. Then consider the other branch
d
C , a ' b || F, C ∨ a ' b ∨ a ' c. This branch is consistent with the clause, but the join of their
8
DPLL(t)
Bjørner, Dutertre, and de Moura
difference: ((a 6' b)d ∧ a ' c) t a ' b is the disjunction a ' b ∨ b 6' c which we need for the result of
d
E-Fact. The other literals from C are added as we only consider C .
9
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF

advertising