-
Notifications
You must be signed in to change notification settings - Fork 18
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
Implement subset minimal unsat core #765
Conversation
80f52c4
to
15b1687
Compare
The solution currently uses I decided to make a separate derived class for minimal unsat cores because it requires the other SMT solver to be used, unlike other unsat cores. I think it would be inconvenient to require the user to provide an SMT solver although it might not have been used. |
15b1687
to
42b9678
Compare
src/api/Interpret.cc
Outdated
if (not config.print_cores_full()) { | ||
for (PTRef fla : unsatCore->getNamedTerms()) { | ||
assert(termNames.contains(fla)); | ||
auto const & name = termNames.nameForTerm(fla); | ||
std::cout << name << ' '; | ||
} | ||
} else { | ||
for (PTRef fla : unsatCore->getTerms()) { | ||
if (termNames.contains(fla)) { | ||
std::cout << termNames.nameForTerm(fla); | ||
} | ||
else { | ||
std::cout << logic->printTerm(fla); | ||
} | ||
std::cout << ' '; | ||
} |
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.
Why is this needed?
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.
In the first branch, we use named terms so all of them must be in termNames
. In second branch, we iterate over all terms so not all of them are necessarily in termNames
. If it is not, we just print out string representation of the term, because we do not have any name for it.
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 still don't get it.
I don't see why you need to change the existing functionality.
What does the new option mean?
We should be printing only names, not the terms themselves, no?
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 commit implements option :print-cores-full
from https://cvc5.github.io/blog/2024/04/15/interfaces-for-understanding-cvc5.html
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 see, can you please document the meaning of this option? And maybe also the minimal-unsat-cores
, to make it clear that these are subset minimal, and not global minimum.
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.
Moved to #771
64ca27f
to
cea4259
Compare
test/regression/base/generic/trivial_unsat_core2_full.smt2.expected.out
Outdated
Show resolved
Hide resolved
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.
Do we need these large files? I would prefer to minimize as much as possible the regression tests that we add.
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 removed them from this PR. However, I think some of them will be needed to track the minimization process more thoroughly. They could be simplified, though.
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.
-> #770
cea4259
to
9a840f7
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.
Looks good!
But it seems the two options that you are introducing does not work together correctly.
Maybe the full cores should be introduced in a separate PR? Since it is orthogonal functionality.
Another note is that we should investigate using the Quickxplain algorithm to compute minimal unsat cores.
src/api/MainSolver.cc
Outdated
auto unsatCoreBuilder = [&]() -> std::variant<UnsatCoreBuilder, MinUnsatCoreBuilder> { | ||
if (not config.minimal_unsat_cores()) { return UnsatCoreBuilder{config, proof, pmanager, termNames}; } | ||
|
||
auto auxSMTSolver = std::make_unique<MainSolver>(logic, config, "unsat core solver"); |
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 might be more efficient to give this new solver a fresh config. Specifically, the new solver does not need to compute unsat cores anymore.
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 is a good point.
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.
Based on this, I actually reconsidered the design and I think both builder classes can be merged. Since we use MainSolver
and not SimpSMTSolver
, it is sufficient to extend UnsatCoreBuilder
constructor of just Logic &
parameter, which is fine. The internal SMT solver can be constructed inside only if minimization is desired. Do you agree?
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 would be very good, I think!
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.
Done.
assert(size_t(namedTerms.size()) == namedTermsIdxs.size()); | ||
} | ||
|
||
void MinUnsatCoreBuilder::minimizeAlgNaive() { |
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 algorithm only minimizes the named terms, no?
Thus this does not compute minimal explanation if used together with the option print-cores-full
, no?
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 computes the same minimal explanation of named terms, but the response includes also unnamed terms. I am not sure how CVC5 implements this combination of options, but strictly following their definition would mean ignoring named terms completely, including the minimization process.
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.
My intuition is that if print-cores-full
is set then the names should be ignored and, if minimal cores are required then the minimization algorithm should operate on all terms, not only the named ones.
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.
-> #771
9a840f7
to
7cfe97f
Compare
7cfe97f
to
1f9ef14
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.
LGTM!
I would make the solver and config local to the method where they are needed. Feels like the class would simpler that way.
But I am also fine with how it is now.
setSmtSolver(); | ||
} | ||
|
||
void UnsatCoreBuilder::minimizeAlgNaive() { |
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.
To me it seems like it would be better if the new config and new solver were local to this method. Then, there would be no need for the set
methods.
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.
But then it would not be usable in functions other than minimizeAlgNaive
, and I plan to add more functions and select one of them based on the configuration.
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.
Then each method can have its own local solver.
The solver is not supposed to be shared between different methods, no?
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.
Probably not among distinct algorithms, but more sophisticated minimization algorithms may be divided into more functions or even use subclasses and it would require to always pass the local variable as a parameter. I would do that only if it would turn out to be reasonably more efficient than using the current member variable. Or are your concerns other than performance?
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.
My concerns are readability and simplicity.
And local reasoning.
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.
Another thought: minimization stuff can be enclosed in a nested class (e.g. Minimize
) where common functionalities among various strategies can be shared using inheritance, and member variables within the class can be "local" in a sense - within the scope of minimization. Also minimizeInit
may be replaced by constructor, minimizeFinish
by destructor, etc. It would still not use the variables as local variables within a function, but the scope of the variables would still be limited.
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.
How about we merge this now and you can rethink the design when you want to add another minimization strategy?
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 got a similar idea. I will make it local for now and we will see what to do next.
1f9ef14
to
b7352f4
Compare
b7352f4
to
effdd77
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.
LGTM!
No description provided.