Closed dwhswenson closed 9 years ago
This is done, but leave this open for now to copy some stuff into the documentation!?!
Applying (newly-created) label "docs" to this and closing; that way we can find it in closed issues while writing docs, without it filling up open issues. We should find similar things in already-closed issues/PRs (many good ones can probably be easily found by looking for the longest conversations!)
(Note: I wrote all of this a couple weeks ago, and kept forgetting to post it. JHP, please take a look, and let me know what you think of the
move_path
attribute, whether it'll cause problems for storage: I think there's a problem there we need to solve, but I'm open to other solutions.)Highlights
PathMover
s, included several classes which I’ve already mostly implementedMoveDetails
object, in particular replacing themover
attribute with amove_path
attribute, which is a list of 2-tuples(mover, accepted)
Sample.details.accepted
can be derived fromSample.details.move_path
and how this allows much more analysis of the behavior of ourPathMover
s (a key tool for practical troubleshooting)PathMover
s can be implemented using these combination toolsThe main thing I need is advice from @jhprinz on whether this
Sample.details.move_path
will be a pain to add to storage.If you see any holes in this implementation, let me know, but I think it will allow us to quickly add new move schemes in the future. It’s currently being implemented in the branch for PR #106.
As I’ve been putting together the framework for
PathMover
s in general, I’ve been thinking about the fact that many of our more interesting moves in path space can be described as some combination of more elementary moves. This is much the same as how ourEnsemble
s are made of particular combinations of other the elementary ensembles.So the questions I’ve been working on answering are:
For the first two, we’re fine if the answers are only partially complete. In fact, I’m not planning to implement some parts of this. But we do want to correctly anticipate best way to handle the last one.
The Move Tree
Before diving into the specifics, let me introduce the general idea of the move tree. The basic idea is that we typically have a decision tree to select which
PathMover
will generateSample
s for this step in the Monte Carlo. For example, perhaps you first choose a replica exchange out of the list of shooting, replica exchange, minus move, or path reversal. Then you have to choose a specific replica exchange pair to use.In order to make this sort of process as flexible as possible, we use the idea of the move tree. In general (at least with
PathSampling
approaches) we’ll have aroot_mover
which leads to the whole tree.The point is that we need to, in some way, record the move tree path that led to generating a specific
Sample
. In fact, I’d argue that theSample
should be labelled as generated by the move tree path, not just by a given mover (in fact, JHP already added something to this effect by havingMixedMover
modify thesample.details
-- what I propose here is to generalize and complete that).Some moves also consist of several sequential submoves. That’s also handled in this discussion.
Elementary Moves
I don’t claim that this list is exhaustive, but here are a few of the moves I have identified as elementary. We may add others as we go along:
ForwardShooting
andBackwardShooting
TwoWayShooting
(not to be implemented in version 1.0)ReplicaExchange
EnsembleHop
I think that a number of other moves (e.g.,
StateSwap
) are just special cases ofReplicaExchange
orEnsembleHop
. A few sections below, I’ll show thatOneWayShooting
andMinusMove
can be described using these elementary moves and the combination tools I describe in the next section.It’s possible that 2-way shooting can be implemented as a combination move. I’d prefer that, although I haven’t thought out all the details of what would be needed to make that happen.
MultiMover
s: Combining other movesWe need various ways to combine these moves to give the overall behavior we want. I’ve identified 5 such combinations; there may be others to be made. I describe each as a move consisting of submoves.
MixedMover
: Selects a submove at random (optionally with weighted selection probabilities). Does only that move.SequentialMover
: Does its submoves in order, attempting all submoves and applying them to the global state sequentially. For example, this could be a move scheme that involved doing all repex in increasing order of replica, followed by shooting on all replicas, followed by all repex in decreasing order of replica.PartialAcceptanceSequentialMover
: Does its submoves in order until/unless one is rejected. All moves up to that point are applied to the global state. For example, a bootstrapping move first does aShooting
; if that is accepted, then it attempts anEnsembleHop
. But even if theEnsembleHop
is rejected, we want to apply the success of theShooting
.ConditionalSequentialMover
: Does its submoves in order until/unless one is rejected, but if one is rejected, previous steps are not applied to the global state. For example, aMinusMove
involves first attempting a replica exchange, and then doing an extension (specialized shooting) move. If the replica exchange fails, then we never start the expensive extension process. If the extension fails, then the whole move is rejected (including the successful replica exchange).SimultaneousMover
(not implemented in version 1.0): This is similar to theSequentialMover
, but instead of updating the global state after each move, all samples are generated starting from the same global state. I think this is only a good idea if there’s no overlap in the replicas affected by the submoves (for example, when doing a shooting move on all replicas). In principle, this could be parallelized. For now, such cases give equivalent results if run as aSequentialMover
.Common Moves as Combinations of Elementary Moves
As discussed in #104, we could either make moves like these as pseudoclasses (i.e., offer convenience functions that construct them, but don’t actually have a class named, for example,
OneWayShooting
) or we can make actual classes which are mostly subclasses with different__init__
functions. I prefer the latter, because I think it will make analysis easier, and it may make fancier moves possible as well. Advanced users can always use either approach to create their own moves.One-Way Shooting
Subclass of
MixedMover
, consisting ofForwardShootingMover
andBackwardShootingMover
, both using the sameShootingPointSelector
. This is, indeed, how we’ve already implemented this.Minus Move
Subclass of
MixedMover
, consisting ofForwardMinusMover
andBackwardMinusMover
. Each of those are, in turn, subclasses ofConditionalSequentialMover
. The submoves of thoseConditionalSequentialMover
s are a replica exchange move followed by a shooting move (which selects the endpoint as the shooting point).Managing
MoveDetails
One part that gets tricky is that we now have to manage all the details of this information in the MoveDetails object. My suggestion is to replace the
MoveDetails.mover
object with a list,MoveDetails.mover_path
, which consists of 2-tuples of(mover_ID, accepted)
for each of the moves in the move tree path that led to this sample.MoveDetails.accepted
is true if and only if all moves in the tree path were accepted.This allows us to easily analyze acceptance ratios (which give us the first sign of problems) from many different angles: by starting with a move that includes all shooting moves, we can get the overall shooting accepted. Then we can drill down to see the acceptance for each individual replica. Then we can drill even further down to see how forward/backward shooting acceptance ratios differ for each replica.
To make this work, we need to think about the acceptance given in the
mover_path
2-tuple for each multimover. For all movers exceptConditionalSequentialMover
, this is alwaysTrue
: acceptance of the sample depends only on acceptance of the submove. The previous paragraph is done by taking allSamples
containing a givenmover
in theirsample.details.mover_path
s, and looking atsample.details.accepted
.But consider a
MinusMove
where the replica exchange part is accepted, but the extension is not. This will generate two samples: one from the replica exchange, and one from the extension. Themover_path
entry from the replica exchange sample will say that the replica exchange was accepted, whereas the entry from the extension part will say it was accepted. The key is that in BOTH cases, themover_path
entry associated with theConditionalSequentialEnsemble
will be rejected. In this case, we can analyze the acceptance ratio of the replica exchange part by looking at its contributions to themover_path
list, which will give different information from the overall acceptance given bysample.details.accepted
, which would be false for both of these.Storage changes
The only downside of this approach is that it does require some modification to storage. Basically, we need to be able to store these
move_path
lists. @jhprinz, would that be hard to implement?