Skip to content

CBMC additional profiling info: Extend solver hardness to track clauses mapped to an instruction #5480

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Nov 19, 2020
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ main.c
^SIGNAL=0$
^\[main.assertion.\d+\] line \d+ assertion a \+ b \< 10: FAILURE$
^VERIFICATION FAILED$
\"SAT_hardness\":\{(\"Clauses\":\d+|\"Variables\":\d+|\"Literals\":\d+),(\"Clauses\":\d+|\"Variables\":\d+|\"Literals\":\d+),(\"Clauses\":\d+|\"Variables\":\d+|\"Literals\":\d+)\}
\"SAT_hardness\":\{(\"ClauseSet\":\[.*\]|\"Clauses\":\d+|\"Variables\":\d+|\"Literals\":\d+),(\"ClauseSet\":\[.*\]|\"Clauses\":\d+|\"Variables\":\d+|\"Literals\":\d+),(\"ClauseSet\":\[.*\]|\"Clauses\":\d+|\"Variables\":\d+|\"Literals\":\d+),(\"ClauseSet\":\[.*\]|\"Clauses\":\d+|\"Variables\":\d+|\"Literals\":\d+)\}
--
^warning: ignoring
16 changes: 15 additions & 1 deletion src/solvers/sat/satcheck_minisat2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,22 @@ void satcheck_minisat2_baset<T>::lcnf(const bvt &bv)

solver->addClause_(c);

// To map clauses to lines of program code, track clause indices in the
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to be a downer on this but ...

  1. There is not necessarily a 1-to-1 correlations between clauses and lines of code. For example, rewriting and normalisation may mean that multiple lines reduce to the same shared term. Which line should this be credited to? This is worse when it is things like multiplication where additions from other operations can appear as sub-parts of the operator.

  2. Number of variables and clauses is a very crude measure of SAT difficulty. Reducing the number of clauses can make the problem harder; I have seen multiple instances of this.

// dimacs cnf output. Dimacs output is generated after processing clauses
// to remove duplicates and clauses that are trivially true. Here, a clause
// is checked to see if it can be thus eliminated. If not, add the clause
// index to list of clauses in solver_hardnesst::register_clause().
static size_t cnf_clause_index = 0;
bvt cnf;
bool clause_removed = process_clause(bv, cnf);

if(!clause_removed)
cnf_clause_index++;

with_solver_hardness(
[&bv](solver_hardnesst &hardness) { hardness.register_clause(bv); });
[&bv, &cnf, &clause_removed](solver_hardnesst &hardness) {
hardness.register_clause(bv, cnf, cnf_clause_index, !clause_removed);
});
clause_counter++;
}
catch(const Minisat::OutOfMemoryException &)
Expand Down
37 changes: 36 additions & 1 deletion src/solvers/solver_hardness.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ operator+=(const solver_hardnesst::sat_hardnesst &other)
clauses += other.clauses;
literals += other.literals;
variables.insert(other.variables.begin(), other.variables.end());
clause_set.insert(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we sort this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was worried about too many calls to sort().

clause_set.end(), other.clause_set.begin(), other.clause_set.end());
return *this;
}

Expand Down Expand Up @@ -87,14 +89,30 @@ void solver_hardnesst::register_assertion_ssas(
current_hardness = {};
}

void solver_hardnesst::register_clause(const bvt &bv)
void solver_hardnesst::register_clause(
const bvt &bv,
const bvt &cnf,
const size_t cnf_clause_index,
bool register_cnf)
{
current_hardness.clauses++;
current_hardness.literals += bv.size();

for(const auto &literal : bv)
{
current_hardness.variables.insert(literal.var_no());
}

if(register_cnf)
{
#ifdef DEBUG
std::cout << cnf_clause_index << ": ";
for(const auto &literal : cnf)
std::cout << literal.dimacs() << " ";
std::cout << "0\n";
#endif
current_hardness.clause_set.push_back(cnf_clause_index);
}
}

void solver_hardnesst::set_outfile(const std::string &file_name)
Expand Down Expand Up @@ -151,6 +169,14 @@ void solver_hardnesst::produce_report()
sat_hardness_json["Variables"] =
json_numbert{std::to_string(hardness.variables.size())};

json_arrayt sat_hardness_clause_set_json;
for(auto const &clause : hardness.clause_set)
{
sat_hardness_clause_set_json.push_back(
json_numbert{std::to_string(clause)});
}
sat_hardness_json["ClauseSet"] = sat_hardness_clause_set_json;

hardness_stats_json["SAT_hardness"] = sat_hardness_json;

json_stream_array.push_back(hardness_stats_json);
Expand Down Expand Up @@ -183,6 +209,15 @@ void solver_hardnesst::produce_report()
assertion_hardness_json["Variables"] = json_numbert{
std::to_string(assertion_stats.sat_hardness.variables.size())};

json_arrayt assertion_sat_hardness_clause_set_json;
for(auto const &clause : assertion_stats.sat_hardness.clause_set)
{
assertion_sat_hardness_clause_set_json.push_back(
json_numbert{std::to_string(clause)});
}
assertion_hardness_json["ClauseSet"] =
assertion_sat_hardness_clause_set_json;

assertion_stats_json["SAT_hardness"] = assertion_hardness_json;

json_stream_array.push_back(assertion_stats_json);
Expand Down
11 changes: 10 additions & 1 deletion src/solvers/solver_hardness.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ struct solver_hardnesst
size_t clauses = 0;
size_t literals = 0;
std::unordered_set<size_t> variables = {};
std::vector<size_t> clause_set = {};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the performance cost of this?


sat_hardnesst &operator+=(const sat_hardnesst &other);
};
Expand Down Expand Up @@ -105,7 +106,15 @@ struct solver_hardnesst
/// Called e.g. from the `satcheck_minisat2::lcnf`, this function adds the
/// complexity statistics from the last SAT query to the `current_ssa_key`.
/// \param bv: the clause (vector of literals)
void register_clause(const bvt &bv);
/// \param cnf: processed clause
/// \param cnf_clause_index: index of clause in dimacs output
/// \param register_cnf: negation of boolean variable tracking if the clause
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please clarify this comment.

/// can be eliminated
void register_clause(
const bvt &bv,
const bvt &cnf,
const size_t cnf_clause_index,
bool register_cnf);

void set_outfile(const std::string &file_name);

Expand Down