-
Notifications
You must be signed in to change notification settings - Fork 896
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
Infrastructure to run a Sat solver as a command #4303
base: main
Are you sure you want to change the base?
Conversation
kernel/register.cc
Outdated
SatSolver *yosys_satsolver_list; | ||
SatSolver *yosys_satsolver; | ||
|
||
struct MinisatSatSolver : public SatSolver { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure we want this removed. This allowed for a plugin to register a different SAT solver, though I am not sure yosys_satsolver_list
gets used anywhere, so that the other-than-default solver would ever get selected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we are missing a command satselect
, solverselect
or similar which would update the yosys_satsolver
pointer, but the overall approach of these SatSolver
descendants appears sane. On the contrary, instead of removing this, we should arrange for an ezcommand
solver to be instantiable through this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your explanation, now I see the benefit. I thought it was entirely unused.
I can just remove this commit and the next one: ezSATCommand would not be accessible from the global solver yet, but would at least be available from C++ plugins.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like your idea of a solver selection command, although I don't know if there's a need for Sat solver selection. kissat or cadical are difficult to beat, and the only reason to select a non-default solver is because minisat is outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point. I will defer to @jix's judgement on this. Should we e.g. always override the default solver with the one from a plugin, if available?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to have a way to override the default solver, that would also make it easier to test this PR. I don't want to change the default without an explicit command though (sat -select-solver ...
could be added, there is precedent for subcommand like options and it would avoid cluttering the command list, but maybe also make it a bit hard to discover)
libs/ezsat/ezcommand.cc
Outdated
for (auto id : assumptions) | ||
extraClauses.push_back({bind(id)}); | ||
|
||
printDIMACS(dimacs, false, extraClauses); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would there be issues with appending the extra clauses to the file from here, instead of introducing a new argument to printDIMACS
? I see printDIMACS
finds out the maximum term or clause number to arrange for uniform padding, but is that a requirement of the format or just a convenience for inspection?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I preferred to extend printDIMACS rather than duplicate the writing code. You'd prefer not to change the API?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It depends on how much code would be duplicated in practice. How much lines would you estimate that to be?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not that many actually, less than 10
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As pointed out by Jix, the number of clauses is in the header, so we cannot actually add this afterwards
a477dff
to
f06801d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On top of the comments I left inline, there's no easy way to actually test this without manually patching the default or writing a plugin making direct use of it. This should come with either a way to change the default solver or an example plugin with a test case.
libs/ezsat/ezsat.cc
Outdated
@@ -1259,6 +1259,8 @@ void ezSAT::printDIMACS(FILE *f, bool verbose) const | |||
std::vector<std::vector<int>> all_clauses; | |||
getFullCnf(all_clauses); | |||
assert(cnfClausesCount == int(all_clauses.size())); | |||
for (auto c : extraClauses) | |||
all_clauses.push_back(c); | |||
|
|||
fprintf(f, "p cnf %d %d\n", cnfVariableCount, cnfClausesCount); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will print a broken DIMACS CNF header with an incorrect clause count when extraClauses
is non-empty.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right I shouldn't have bolted on this part to handle assumptions as I don't use them myself
libs/ezsat/ezcmdline.cc
Outdated
} | ||
} | ||
}; | ||
if (Yosys::run_command(sat_command, line_callback) != 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Many solvers follow the convention that they exit with status 10 for satisfiable and with status 20 for unsatisfiable instances, so those exit code shouldn't be treated as an error if they match result parsed from the log output.
kernel/register.cc
Outdated
SatSolver *yosys_satsolver_list; | ||
SatSolver *yosys_satsolver; | ||
|
||
struct MinisatSatSolver : public SatSolver { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to have a way to override the default solver, that would also make it easier to test this PR. I don't want to change the default without an explicit command though (sat -select-solver ...
could be added, there is precedent for subcommand like options and it would avoid cluttering the command list, but maybe also make it a bit hard to discover)
e277910
to
8b73af4
Compare
As discussed on the slack channel, here is a patch for a solver interface using an arbitrary command (I used kissat for my test).
It also removes some unused code that was supposed to register arbitrary solvers.
As the moment, it is only usable for experimental purposes from the C++. I didn't implement any direct access from the command line (sat, equiv, ...)