GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/prop/cadical.cpp Lines: 65 85 76.5 %
Date: 2021-09-16 Branches: 39 142 27.5 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Mathias Preiner, Andres Noetzli, Liana Hadarean
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 *
13
 * Wrapper for CaDiCaL SAT Solver.
14
 *
15
 * Implementation of the CaDiCaL SAT solver for cvc5 (bit-vectors).
16
 */
17
18
#include "prop/cadical.h"
19
20
#include "base/check.h"
21
#include "util/statistics_registry.h"
22
23
namespace cvc5 {
24
namespace prop {
25
26
using CadicalLit = int;
27
using CadicalVar = int;
28
29
// helper functions
30
namespace {
31
32
32986
SatValue toSatValue(int result)
33
{
34
32986
  if (result == 10) return SAT_VALUE_TRUE;
35
14209
  if (result == 20) return SAT_VALUE_FALSE;
36
  Assert(result == 0);
37
  return SAT_VALUE_UNKNOWN;
38
}
39
40
/* Note: CaDiCaL returns lit/-lit for true/false. Older versions returned 1/-1.
41
 */
42
576560
SatValue toSatValueLit(int value)
43
{
44
576560
  if (value > 0) return SAT_VALUE_TRUE;
45
384943
  Assert(value < 0);
46
384943
  return SAT_VALUE_FALSE;
47
}
48
49
19699984
CadicalLit toCadicalLit(const SatLiteral lit)
50
{
51
19699984
  return lit.isNegated() ? -lit.getSatVariable() : lit.getSatVariable();
52
}
53
54
12298
CadicalVar toCadicalVar(SatVariable var) { return var; }
55
56
}  // namespace helper functions
57
58
6149
CadicalSolver::CadicalSolver(StatisticsRegistry& registry,
59
6149
                             const std::string& name)
60
6149
    : d_solver(new CaDiCaL::Solver()),
61
      // Note: CaDiCaL variables start with index 1 rather than 0 since negated
62
      //       literals are represented as the negation of the index.
63
      d_nextVarIdx(1),
64
      d_inSatMode(false),
65
12298
      d_statistics(registry, name)
66
{
67
6149
}
68
69
6149
void CadicalSolver::init()
70
{
71
6149
  d_true = newVar();
72
6149
  d_false = newVar();
73
74
6149
  d_solver->set("quiet", 1);  // CaDiCaL is verbose by default
75
6149
  d_solver->add(toCadicalVar(d_true));
76
6149
  d_solver->add(0);
77
6149
  d_solver->add(-toCadicalVar(d_false));
78
6149
  d_solver->add(0);
79
6149
}
80
81
12292
CadicalSolver::~CadicalSolver() {}
82
83
5188228
ClauseId CadicalSolver::addClause(SatClause& clause, bool removable)
84
{
85
19386600
  for (const SatLiteral& lit : clause)
86
  {
87
14198372
    d_solver->add(toCadicalLit(lit));
88
  }
89
5188228
  d_solver->add(0);
90
5188228
  ++d_statistics.d_numClauses;
91
5188228
  return ClauseIdError;
92
}
93
94
ClauseId CadicalSolver::addXorClause(SatClause& clause,
95
                                     bool rhs,
96
                                     bool removable)
97
{
98
  Unreachable() << "CaDiCaL does not support adding XOR clauses.";
99
}
100
101
1332819
SatVariable CadicalSolver::newVar(bool isTheoryAtom,
102
                                  bool preRegister,
103
                                  bool canErase)
104
{
105
1332819
  ++d_statistics.d_numVariables;
106
1332819
  return d_nextVarIdx++;
107
}
108
109
43
SatVariable CadicalSolver::trueVar() { return d_true; }
110
111
157
SatVariable CadicalSolver::falseVar() { return d_false; }
112
113
SatValue CadicalSolver::solve()
114
{
115
  TimerStat::CodeTimer codeTimer(d_statistics.d_solveTime);
116
  d_assumptions.clear();
117
  SatValue res = toSatValue(d_solver->solve());
118
  d_inSatMode = (res == SAT_VALUE_TRUE);
119
  ++d_statistics.d_numSatCalls;
120
  return res;
121
}
122
123
SatValue CadicalSolver::solve(long unsigned int&)
124
{
125
  Unimplemented() << "Setting limits for CaDiCaL not supported yet";
126
};
127
128
32986
SatValue CadicalSolver::solve(const std::vector<SatLiteral>& assumptions)
129
{
130
65972
  TimerStat::CodeTimer codeTimer(d_statistics.d_solveTime);
131
32986
  d_assumptions.clear();
132
2582723
  for (const SatLiteral& lit : assumptions)
133
  {
134
2549737
    d_solver->assume(toCadicalLit(lit));
135
2549737
    d_assumptions.push_back(lit);
136
  }
137
32986
  SatValue res = toSatValue(d_solver->solve());
138
32986
  d_inSatMode = (res == SAT_VALUE_TRUE);
139
32986
  ++d_statistics.d_numSatCalls;
140
65972
  return res;
141
}
142
143
bool CadicalSolver::setPropagateOnly()
144
{
145
  d_solver->limit("decisions", 0); /* Gets reset after next solve() call. */
146
  return true;
147
}
148
149
14209
void CadicalSolver::getUnsatAssumptions(std::vector<SatLiteral>& assumptions)
150
{
151
2389524
  for (const SatLiteral& lit : d_assumptions)
152
  {
153
2375315
    if (d_solver->failed(toCadicalLit(lit)))
154
    {
155
109534
      assumptions.push_back(lit);
156
    }
157
  }
158
14209
}
159
160
void CadicalSolver::interrupt() { d_solver->terminate(); }
161
162
576560
SatValue CadicalSolver::value(SatLiteral l)
163
{
164
576560
  Assert(d_inSatMode);
165
576560
  return toSatValueLit(d_solver->val(toCadicalLit(l)));
166
}
167
168
576554
SatValue CadicalSolver::modelValue(SatLiteral l)
169
{
170
576554
  Assert(d_inSatMode);
171
576554
  return value(l);
172
}
173
174
unsigned CadicalSolver::getAssertionLevel() const
175
{
176
  Unreachable() << "CaDiCaL does not support assertion levels.";
177
}
178
179
bool CadicalSolver::ok() const { return d_inSatMode; }
180
181
6149
CadicalSolver::Statistics::Statistics(StatisticsRegistry& registry,
182
6149
                                      const std::string& prefix)
183
12298
    : d_numSatCalls(registry.registerInt(prefix + "cadical::calls_to_solve", 0)),
184
12298
      d_numVariables(registry.registerInt(prefix + "cadical::variables", 0)),
185
12298
      d_numClauses(registry.registerInt(prefix + "cadical::clauses", 0)),
186
24596
      d_solveTime(registry.registerTimer(prefix + "cadical::solve_time"))
187
  {
188
6149
}
189
190
}  // namespace prop
191
29577
}  // namespace cvc5