summaryrefslogtreecommitdiff
path: root/src/generic/problemresolver/problemresolver.h
AgeCommit message (Collapse)AuthorFilesLines
2009-06-18Generalize promotions before using them to strike choices.Daniel Burrows1-2/+6
Without this, bad stuff was happening, like spurious entries in the structural-reasons list that triggered internal sanity checks.
2009-06-17Don't follow forced dependencies when the target is not a processed tier.Daniel Burrows1-1/+2
This doesn't have a practical effect (those steps weren't being processed anyway), but it does suppress spurious errors in the logs.
2009-06-17Log the new solvers set that was created by removing a choice after we ↵Daniel Burrows1-4/+4
update it, not before.
2009-06-17Strip out the sanity-check now that I found the error it was looking for.Daniel Burrows1-21/+0
2009-06-17When generating a successor for a solver whose intrinsic tier is below the ↵Daniel Burrows1-1/+2
parent step's tier, use the parent step's tier. Previously, the code was decreasing the tier in the successor.
2009-06-17Add a temporary sanity-check to the incremental promotion code.Daniel Burrows1-0/+21
Some promotions are never being applied, for reasons that are not currently clear. The sanity check ensures that promotions are always applied, and also logs an error if it ever trips, to help track this down.
2009-06-17Tone the logging around unresolved deps back down.Daniel Burrows1-7/+0
If I need this again, I should probably just make it a separate logging category -- hopefully I won't, though.
2009-06-17When finding new unresolved dependencies, check forward dependencies of the ↵Daniel Burrows1-0/+13
newly selected version, not just reverse dependencies.
2009-06-17Better logging of what's happening while dependencies are being generated.Daniel Burrows1-0/+10
2009-06-16Implement a queuing system for new promotions.Daniel Burrows1-21/+169
The idea is that if there are only "a few" new promotions, it's quicker to test them individually than to use the full promotion set. The exact parameters of what "a few" means should probably be configurable at runtime, not least so I can easily get some statistics on what the effects of various settings are.
2009-06-15Instead of always doing a full incremental recomputation of each step's tier ↵Daniel Burrows1-10/+46
whenever a promotion is added, just retest tiers when steps are pulled off the queue. This seems to be a win overall, probably because most of the computation in the case where lots of promotions have been added is a waste (since the steps won't be processed anyway, or another promotion will come along and override the one that was applied). I would still like to explore a hybrid model, where promotions are applied incrementally if only "a few" have been added since a step was generated -- that should vastly speed up scanning smallish subtrees.
2009-06-15Use unordered containers to return results from promotion lookups too.Daniel Burrows1-4/+4
These don't have any impact on performance that I can see one way or the other -- which probably means they don't hurt much in smaller cases, so it's a cheap way to avoid scalability surprises since the hash tables should be better for large inputs.
2009-06-15Instead of copying deps_solved_by_choice, pass it directly to the ↵Daniel Burrows1-25/+6
promotion-finding routine.
2009-06-15Really fix that comment.Daniel Burrows1-1/+1
Not just grammatically, but semantically.
2009-06-15Fix a typo in a comment.Daniel Burrows1-1/+1
2009-06-13Use the Boost hash table (unordered_set) to implement dep-solver memoization.Daniel Burrows1-14/+16
This almost eliminates the time we were spending comparing dep solvers (according to profiling, it's now down to 5% of the run time). There are several parts to this commit: (1) Making Boost a dependency of aptitude. This involved changing the configure script, writing a README about it, and writing a short shell script to verify that the configure script is up to date. (2) Redesigning the dep-solvers set so that all mutation goes through a member function. The set needs to cache its hash value for the sake of speed, and having mutation go through member functions lets us invalidate the cache. (3) Writing hash functions for the major resolver structures (that is: the concrete package, version, dep, and tier objects in both implementations, the choice object, and the solver_information and dep_solvers objects in the search graph). (4) Changing the std::set that we were using to collect identical dep_solvers objects to a boost::unordered_set.
2009-06-12Optimize dep-solver memoization by only searching the memoization set once.Daniel Burrows1-10/+8
Really, this should use a hash table. I'm seriously tempted to just lean on Boost here -- they have a very nice implementation of hashing.
2009-06-08Optimize the process of searching for promotions in existing steps.Daniel Burrows1-129/+135
According to profiling data, this was one of the main bottlenecks in the new resolver. The new code uses a trick similar to the one used by the promotion set (and hence is also not threadsafe :( ), storing the counts in the step structures themselves (to avoid having to allocate a tree structure); in this case we even use a "generation counter" to avoid having to zero out the counts between runs. That seems to have eliminated it as the main culprit and replaced it with the dep-memoization code (which I knew would be a problem eventually; now it is). Note: if we ever want to support multiple threads in the resolver, the solution would probably be to give each one its own side table containing the counts of various steps (they could even use the "generation" trick to avoid having to reset counts, like the main one does now).
2009-06-08More and better logging of the resolver and the resolver test code.Daniel Burrows1-0/+20
2009-06-07Log when the resolver starts processing the pending promotions list.Daniel Burrows1-0/+1
2009-06-07Proof-of-concept implementation of dep solver memoization.Daniel Burrows1-4/+27
This saves a lot of memory, but needs to be optimized to save CPU time.
2009-06-07Be more careful about setting validity conditions on solvers.Daniel Burrows1-6/+13
A solver should only get a validity condition if its tier has been increased in a way that might be retracted (i.e., by a user constraint or by a promotion derived from a user constraint).
2009-06-07Don't attempt to track tier validity at the solver level; instead, when a ↵Daniel Burrows1-83/+159
promotion is retracted, recompute tiers for solvers that it might have "hit". In this model, the tier_valid member of search_graph is no longer an active expression that recomputes the solver's tier when it becomes invalid. Instead, it's a pure expression that represents whether the last promotion that was applied to the tier was valid. When any promotion becomes invalid, the whole list of active steps is searched for steps that it might have influenced (the same way we would search for steps to apply it to) and the tier of each such step is recomputed. The major reason for making this change is that maintaining all the structures to track which solvers a promotion affected was expensive, particularly in terms of memory usage. This information is only needed rarely, so I don't want to overly burden the normal behavior of the resolver with book-keeping to handle the corner case of retracted promotions. The new code should be correct; it'll be a bit slow to retract promotions and sometimes the wrong solvers will be recomputed, but that's better than eating hundreds of megabytes of memory. A secondary, but also important, reason is that this opens the door to memoizing dependency solver sets. Previously, solver sets contained backpointers to their own step; they had to, in order to maintain the "zap this solver in this step" active expression. Now, solver sets only contain pointers to structures that are common to all solvers for their dependency, or to all solvers that were affected by a particular promotion. This should mean that there are enough equivalent sets that memoization of some sort will be a win. In particular, I hope that this will tackle the last outstanding memory problem, where applying a promotion takes a bunch of identical sets that share memory and creates a bunch of identical sets that don't share memory, massively spiking the program's memory usage in the process.
2009-06-07Be careful whenever iterating over a choice-indexed set/map to always put ↵Daniel Burrows1-9/+12
dependency information back in. We need that information to correctly find choices in various internal maps, but it's eliminated when we pass a choice through a choice-indexed set.
2009-06-07When increasing the tier of a solver, make sure to preserve dependency ↵Daniel Burrows1-1/+1
information.
2009-06-07Better logging of what happens to solver sets.Daniel Burrows1-11/+17
2009-06-06When striking a choice, remove it from the step's index of solvers.Daniel Burrows1-0/+4
For some reason the code wasn't doing this, which led to a situation where every step listed every choice that had ever been mentioned as a solver. This may be part of why promotions were bogging everything down -- most steps looked like they contained any given promotion!
2009-06-06Only modify the tier of a solver if it actually changed.Daniel Burrows1-17/+25
2009-06-06Don't try to insert empty promotions into the promotion set.Daniel Burrows1-1/+3
Lots of empty promotions appear to get generated during the course of the search, and the promotion set doesn't handle them properly. They aren't very interesting (you hardly ever have any valuable knowledge about the empty set), and they sit around eating memory.
2009-06-06Only apply promotions to all the steps in the graph if they're new.Daniel Burrows1-2/+9
2009-06-06Complain if we actually process a dependency with no solvers.Daniel Burrows1-0/+3
Dependencies with no solvers should always cause the step that contains them to be promoted to the conflict tier and thus ejected from the graph.
2009-06-06Ensure that the first time we add a successor to a step, we do not update ↵Daniel Burrows1-1/+1
the "is_last_child" member of the last step in the steps list. This may be a symptom of the fact that the way steps are added is rather error-prone. However, it should work now. The problem was that we were always clearing the "is_last_child" member of the last step in the global list of steps. We want to do this whenever we add a child beyond the first, since otherwise each step would have only one child. But we don't want to do it for the first child, or only the very last step in the list would be marked as a last child (meaning that every "child" list would contain all the steps following its first entry).
2009-06-06Fill in the "reason" field of steps when they're generated.Daniel Burrows1-0/+1
2009-06-06Only generate entries in the global reverse index of steps when a choice is ↵Daniel Burrows1-77/+14
first added. The global index was getting ridiculously huge, and it doesn't need to be. To find all the steps containing a choice, we can just start at the first step where it was introduced as a solver, and trace out the whole subtree below that, stopping whenever a step no longer contains the choice in question. With this commit, the time per step is much more reasonable (when compiled without optimizations, it appears to be approximately as fast as the old resolver was with optimizations). However, it also looks like there are a few bugs left: it branches far too much and it got stuck once in an infinite loop.
2009-06-06Correctly fill in the child link in the parent step when a new step is ↵Daniel Burrows1-0/+2
generated.
2009-06-06When checking whether a choice has a dependency, only do that test for ↵Daniel Burrows1-1/+1
install_version choices. get_has_dep() is only really meant to work for these choices; it will throw an exception if called on a different type of choice.
2009-06-06Log a warning when generating successors if the input choice doesn't have a ↵Daniel Burrows1-0/+5
dependency. This situation will likely lead to a crash.
2009-06-06When generating successors, refer to the parent by index, not by address.Daniel Burrows1-4/+5
Some STL containers can move elements around when new entries are added. I think the deque doesn't do this -- but performance isn't so important that I want to implicitly depend on this level of detail regarding how an STL container is implemented (whether or not the standard would allow me to).
2009-06-06Add a sanity-check to ensure that we don't try to mark a step as a clone of ↵Daniel Burrows1-1/+1
itself.
2009-06-05Put the old handling of "forced" resolutions back in.Daniel Burrows1-46/+65
This just amounts to "if you only made one successor, jump to that successor and repeat".
2009-06-04Split the "process a step and generate successors" logic into a separate ↵Daniel Burrows1-72/+80
routine. This will make it a bit cleaner to implement forced dependencies, I hope.
2009-06-04Don't crash when creating a deferral expression.Daniel Burrows1-1/+2
2009-06-04Only start a new search if nothing has been processed, ever.Daniel Burrows1-4/+3
This means we return NoMoreSolutions whenever we're invoked after all the solutions have been generated. Among other things, the unit tests expect this.
2009-06-04When applying an incipient promotion, use the promotions's choice rather ↵Daniel Burrows1-16/+10
than any choice from a solver. This should be what we do anyway: the promotion's choice will always be the most general one that covers all the solvers that hit it. However, the fact that the previous code wasn't working exposes a bug in contains(): although deps are no longer significant, it's claiming that one choice with a dep doesn't contain another choice with a different dep, even if neither is a from-dep-source choice and they install the same version! That will be fixed momentarily.
2009-06-04Slightly more logging of the process of striking a solver from a step.Daniel Burrows1-0/+4
2009-06-04"Bless" solutions that the resolver has decided to return, to prevent them ↵Daniel Burrows1-0/+35
from being discarded by promotions. I'm not 100% sure this is what we want for the final behavior, but it is one way of attacking the problem where the resolver would generate a solution, then throw it away because it was already generated. Now those solutions are never thrown away for any reason (although they can still be affected by promotions that are discovered or by deferrals).
2009-06-04Strip out more old, unused code.Daniel Burrows1-361/+0
2009-06-03Actually store the solver that caused an incipient promotion when we find one.Daniel Burrows1-2/+12
2009-06-03Invoke process_pending_promotions() after adding a new promotion to the ↵Daniel Burrows1-0/+2
global set. This ensures that we attempt to apply promotions to existing steps. For instance, this should stop the resolver from returning new "solutions" that contain old solutions as strict subsets.
2009-06-03Log when we add a full-solution bonus to a step's score.Daniel Burrows1-1/+7