The constraint-solver now uses the logic-solver in such a way that
accessing variables that weren't part of the problem statement will
never throw an error. That way, we don't have to worry about
present and future cases where we don't generate any logical formulas
involving a package "foo" and then we say to minimize some weighted
sum over packages including "foo".
Turn recursive addClauses->useFormulaTerm->addClauses into iterative.
Also do a couple tweaks that seem to improve performance.
The "stack overflow bug" case is now hovering around 10-20 seconds.
(It's a failure case, but it sure takes a while to fail.)
From running benchmarks while changing the code:
* It doesn't seem to slow things down to *always* try to "hit 0"
when minimizing
* It does seem to slow things down if the "<= 0" constraint is
expressed using <= instead of "forbid the terms with non-zero
weights"
This change also fixes a bug where we required terms with zero
weights to be 0.
I thought it would help me write a test for a bug that turned
up in code review, but it doesn't. Still, I'm sure it will be
useful.
Also, Logic.Solution#getFormula is something I've been wanting
to write for a while.
Lots of things happened here:
* Refactored how cost minimization is expressed
* Cost function now distinguishes major/minor/patch/rest
* Order of terms is improved
* Reachability analysis of catalog makes benchmarks much faster
* Lock down versions of special packages before solving rest (perf)
* Explaining conflicts no longer crashes on cycles
* Antigravity for patches (and wrap nums, prereleases, etc.) so that
we take bug fixes to indirect dependencies.
TODO:
* Refuse to make breaking changes to root reps
* Make sure we don't have antigravity changing any previous solutions
for no reason
* Proper pre-release handling
* Unit tests
It even explains conflicts. It just doesn't spit out the list of
other constraints on conflicted packages yet (easy to do).
Left to do:
- Remove old solver code
- Call nudge()
- More nuanced cost function
- Clean up solver.js a little
- Proper handling of pre-release versions
- Lots more tests of different scenarios!
It really just says which assumptions created the conflict when
solveAssuming is used. And currently we only support one assumption
(which may represent a formula). If we supported N assumptions, it's
possible MiniSat's analysis would tell us which of the N is the
problem. It's not clear if it would be a minimal set though.
Still, might as well have the capability at the level of interfacing
with MiniSat in case it comes in handy.
…in terms of what is which’s responsibility.
Allow Logic.xor(…) to return a term in the one-arg case. From now on, helpers like Logic.and, Logic.or, and Logic.xor don’t have to return AndFormulas, OrFormulas, or XorFormulas; they can return other formulas or terms if they like, resulting in fewer intermediate variables.
This completes nested formula generation, so now we are ready for atMostOne.