GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/prop/cadical.cpp Lines: 65 85 76.5 %
Date: 2021-08-17 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
33267
SatValue toSatValue(int result)
33
{
34
33267
  if (result == 10) return SAT_VALUE_TRUE;
35
14219
  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
574270
SatValue toSatValueLit(int value)
43
{
44
574270
  if (value > 0) return SAT_VALUE_TRUE;
45
384546
  Assert(value < 0);
46
384546
  return SAT_VALUE_FALSE;
47
}
48
49
19735153
CadicalLit toCadicalLit(const SatLiteral lit)
50
{
51
19735153
  return lit.isNegated() ? -lit.getSatVariable() : lit.getSatVariable();
52
}
53
54
12176
CadicalVar toCadicalVar(SatVariable var) { return var; }
55
56
}  // namespace helper functions
57
58
6088
CadicalSolver::CadicalSolver(StatisticsRegistry& registry,
59
6088
                             const std::string& name)
60
6088
    : 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
12176
      d_statistics(registry, name)
66
{
67
6088
}
68
69
6088
void CadicalSolver::init()
70
{
71
6088
  d_true = newVar();
72
6088
  d_false = newVar();
73
74
6088
  d_solver->set("quiet", 1);  // CaDiCaL is verbose by default
75
6088
  d_solver->add(toCadicalVar(d_true));
76
6088
  d_solver->add(0);
77
6088
  d_solver->add(-toCadicalVar(d_false));
78
6088
  d_solver->add(0);
79
6088
}
80
81
12176
CadicalSolver::~CadicalSolver() {}
82
83
5201426
ClauseId CadicalSolver::addClause(SatClause& clause, bool removable)
84
{
85
19437934
  for (const SatLiteral& lit : clause)
86
  {
87
14236508
    d_solver->add(toCadicalLit(lit));
88
  }
89
5201426
  d_solver->add(0);
90
5201426
  ++d_statistics.d_numClauses;
91
5201426
  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
1335446
SatVariable CadicalSolver::newVar(bool isTheoryAtom,
102
                                  bool preRegister,
103
                                  bool canErase)
104
{
105
1335446
  ++d_statistics.d_numVariables;
106
1335446
  return d_nextVarIdx++;
107
}
108
109
43
SatVariable CadicalSolver::trueVar() { return d_true; }
110
111
154
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
33267
SatValue CadicalSolver::solve(const std::vector<SatLiteral>& assumptions)
129
{
130
66534
  TimerStat::CodeTimer codeTimer(d_statistics.d_solveTime);
131
33267
  d_assumptions.clear();
132
2581816
  for (const SatLiteral& lit : assumptions)
133
  {
134
2548549
    d_solver->assume(toCadicalLit(lit));
135
2548549
    d_assumptions.push_back(lit);
136
  }
137
33267
  SatValue res = toSatValue(d_solver->solve());
138
33267
  d_inSatMode = (res == SAT_VALUE_TRUE);
139
33267
  ++d_statistics.d_numSatCalls;
140
66534
  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
14219
void CadicalSolver::getUnsatAssumptions(std::vector<SatLiteral>& assumptions)
150
{
151
2390045
  for (const SatLiteral& lit : d_assumptions)
152
  {
153
2375826
    if (d_solver->failed(toCadicalLit(lit)))
154
    {
155
109587
      assumptions.push_back(lit);
156
    }
157
  }
158
14219
}
159
160
void CadicalSolver::interrupt() { d_solver->terminate(); }
161
162
574270
SatValue CadicalSolver::value(SatLiteral l)
163
{
164
574270
  Assert(d_inSatMode);
165
574270
  return toSatValueLit(d_solver->val(toCadicalLit(l)));
166
}
167
168
574264
SatValue CadicalSolver::modelValue(SatLiteral l)
169
{
170
574264
  Assert(d_inSatMode);
171
574264
  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
6088
CadicalSolver::Statistics::Statistics(StatisticsRegistry& registry,
182
6088
                                      const std::string& prefix)
183
12176
    : d_numSatCalls(registry.registerInt(prefix + "cadical::calls_to_solve", 0)),
184
12176
      d_numVariables(registry.registerInt(prefix + "cadical::variables", 0)),
185
12176
      d_numClauses(registry.registerInt(prefix + "cadical::clauses", 0)),
186
24352
      d_solveTime(registry.registerTimer(prefix + "cadical::solve_time"))
187
  {
188
6088
}
189
190
}  // namespace prop
191
29337
}  // namespace cvc5