Repository navigation
MoveScheme and MoveStrategy #279
Description
I’ve been thinking about the best way to implement different move schemes and move strategies. At the heart of the idea is this: a network of transitions is really defined by the ensembles involved. But the same ensembles could be studied using different sets of moves: for example, we can study a network using the standard RETIS move strategy, or we can study it using the SRTIS move strategy. That’s where this discussion matters.
Definitions of terms
- move scheme: for a given simulation, the move scheme is the "move decision tree". Every step of the MC is done by starting with some root move, and tracing a series of decision points to generate (and the accept) a trial.
- move strategy: a general approach to building a move scheme (or a subset thereof). SRTIS is a move strategy. Nearest-neighbor replica exchange is a move strategy. All-replica exchange is a move strategy.
So I use "strategy" to talk about the general idea, and "scheme" to talk about a specific implementation of that idea. "Weina worked on the first practical uses of the SRTIS move strategy. In particular, she implemented an SRTIS-based move scheme in her study of villin headpiece unfolding."
Implementation thoughts
The approach I’m planning is to create a MoveScheme object, which will basically be a container for the current move scheme root, but also has some analysis functions associated with it. (The analysis parts of this object were already created in #266.) Then there will be MoveStrategy objects, which will take a TISNetwork object in their __init__ functions, and have a function (maybe called make_scheme(scheme)?) which creates a modified version of an old MoveScheme. Widely-used strategies will be subclasses of MoveStrategy. Most typical strategies (SRTISStrategy, SetAllExchangeStrategy, NearestNeighborReplicaExchangeStrategy) will be idempotent: running scheme = strategy.make_scheme(scheme) multiple times in a row should return equivalent (though not necessarily identical) objects. The ones that are effectively orthogonal (switching the allowed exchanges as with SetAllExchangeStrategy vs. switching the exchange style with SRTISStrategy vs. switching the shooting point selection, for example) should also be commutative. (That may be a bit challenging to implement, though.)
Think of MoveStrategy as a factory for MoveSchemes.
I thought of several alternatives to aspects of this approach, but I didn’t like any of them as much:
MoveSchemecould be left as is; part of theNetwork. I think this is conceptually confusing. This approach clearly distinguishes between the network itself (ensembles) and the way we study it (moves).- Each
MoveStrategycould be a bare function instead of a class. This is what I originally suggested in Single Replica TIS #260. But this reduces the flexibility of the factory. - There could be one
MoveStrategyfactory class for all strategies. This means that a user creating new strategies would either have to subclass that overall factory or modify it. I think that subclassing a simpler class is more user-friendly, and allows a user to keep using their strategy as the code updates, even if we don't accept it into master. - Instead of having a separate
MoveStrategyclass, different subclasses ofMoveSchemecould apply different strategies. The problem with this is in chaining several modifications together. Starting from the default, maybe a switch from nearest-neighbor to all-replica exchange, then switch to single-replica sampling. This approach would mean this isisinstance(scheme, SingleReplicaMoveScheme)and notisinstance(scheme, AllExchangeMoveScheme), which seems weird to me.
That’s my current view on the implementation of this. It's one of the steps toward getting SRTIS working (#260). Some aspects (esp. around commutativity) might not show up in time for 1.0, but there should be a way to easily do the most obvious move scheme modifications.
Any thoughts?
Activity
dwhswenson commentedon Jun 2, 2015
(Side note: all of this is completely independent of the stuff we discussed in #251, although this should provide shortcuts to give different behaviors discussed in that)
jhprinz commentedon Jun 11, 2015
I like the separation between Scheme and Strategy a lot. It is very good to separate the two concepts of the let's call it the type of simulation 'strategy' and the concrete 'scheme'. Not all schemes will make sense for all strategies of course.
I did not really understand, why you need to have an existing scheme that will be altered. Is this only for flexibility to reuse existing ones and of none is present it will only use the e.g. TISNetwork object?
Or is the Strategy meant to form your scheme in a certain direction and you can chain these to some extend. (Which you mean by commutative, right?) So, this would be possible (and very cool)
When looking at this (and hoping this is close to what you suggested) then it seems that we should put the network into the scheme from the start or is there a reason that all of the schemes will not share the same network definition. I assume of course that the TISNetwork only represents state/interface definitions of a certain type and is thus very general.
So, I see 2 ways to implement this:
factory.
This whole problem looks very similar to website generation: You start with a main template and allow certain blocks to be replaced or altered. Each alteration requires some prerequisits (like set variables) that are present and some hooks that it attaches to or changes (like RepExMoves).
So the function
create_base_scheme()would set up the main template that contains some variables it copies from theTISNetwork, like the interfaces, ensembles, volumes and their relation. The Base Mover would beThen the RETISScheme would be represented by a dictionary of replacement rules:
Then TwoWayShootingScheme means e.g.
The second Scheme will replace the last from the first scheme and so on.
If you want the final mover you have to apply all rules that are left in order. This way you could have almost orthogonal features to add. This would make it very simple for a beginner, although adding new features might be difficult yet very powerful.
One other thing that popped into my mind when reading this was: Each of these features kind of implies some analysis things that make sense. At first I thought, well, maybe a scheme should induce the way rates are computed and the additional features like set the shooter, etc might induce analysis for acceptance ratios, replica flow, etc. which are independent of the way the rate is computed.
Finally this could still be attached to the Strategies. There could be RootStrategies that induce specific way to compute a rate or more than one rate, while other orthogonal strategies will only add some analysis features.
Orthogonality is given by the list of "keys" in the set of rules it acts upon.
Anyway, this could be really great.
dwhswenson commentedon Jun 11, 2015
Yes, this is largely along the lines I'm working (I should mention that I'm already working on this; just need to open the PR).
Particular points:
Yes, the chaining is the basic idea (and hence the question of commutativity: no promise that all orders will be supported as of version 1.0). There's a slight difference from what you typed as an example: in your example, you used
schemeas the argument for eachmake_schemefunction. It should bescheme, thenscheme1, thenscheme2. (I suspect you just mistyped that, though.) Then you have a scheme which uses all-ensemble-exchange strategy with SRTIS (i.e., ensemble hopping instead of replica exchange) and two-way shooting.This is, indeed, exactly what I was thinking.
It should be in the scheme from the start. In current drafts, I'm still moving things around, so I'm not entirely sure where various attributes will end up, but I suspect that there will be a
scheme.network.I'm currently implementing it more along the lines of the second approach. In particular, the
schemeis basically what was previously themoversattribute of networks/transitions. So it includes some structural information (grouping shooting movers, repex, etc). This also makes the translation process easier.The idea of setting it up as a container of many factories is interesting, and I'll consider it further.
While this is the idea in the simplest case, in more complicated cases, it is a bit more difficult. Consider switching to single-replica TIS. There, we'll have to completely restructure the move decision tree to be organized by current ensemble instead of by move type. So that's a bit more work than simple replacement rule.
Yes and no. You give the example of rates. That is not correct: the point here is that we separate the analysis that relates to the move strategy from the analysis that relates to the ensembles sampled. The rate calculation is only based on the ensembles sampled. However, many tests of convergence are based on analyzing the moves themselves.
I'm not entirely sure what kinds of analysis are strategy-specific. This is something I'm still thinking about.
jhprinz commentedon Jun 11, 2015
Exactly, a typo. I meant chaining one to the next! Cool. Go ahead and make a PR. I am curious.
Yes and no. I think that the main point is not to apply the rules at once, but keep the set of rules and always generate a new scheme using all current rules. In the example you give you would replace the initial
BaseMoverand reorder some factories. All options like Shooting etc will then be automatically applied at the new places or ignored if not used anymore.Of course there could be a way to fix a certain set of applied rules and start changing from there.
I think that is what I meant: For rates there are things that are necessary for some way of computing it to make sense. E.g. you need to know which interfaces relate in which way and apply WHAM or some other estimator. The information necessary, like interfaces and their connections will be introduced into the scheme potentially by either the chosen Network/Transition or a Strategy(Feature). So, when writing
all I mean is that scheme also gets a special property to compute the rate. So the scheme now knows that it is a TISNetwork and this implied a rate computation. It could look like:
In some cases this seems quite natural to me, so, if a Strategy defines the RepExMoves, it can now the way how to analyze the flow.
Maybe that is too much for the beginning.
dwhswenson commentedon Jun 11, 2015
Yeah, this is more the view that the
MoveSchemeis a container of factories, which you suggested. And as I think about it, I think this is a better approach. It just wasn't what I was doing originally. I'll need some time to think through exactly what that looks like (in detail), but in principle, it sounds appealing.This was my original idea: to have a default set and require everything to translate to and from
default. But I don't think that's as flexible.That is handled in
TransitionNetworks. The ensembles exist there. That's where we calculate rates. Only the moves exist here. I can sample the same ensembles using nearest-neighbor exchange or all-exchange, single replica or multiple replicas, one-way or two-way shooting: in all cases, the method to calculate the rate is exactly the same. It does not depend on the move strategy, only on the ensembles in the transition network. The rate is absolutely NOT a property of the move scheme. Putting it in there implies that it is.The whole point here is to separate the ensembles from the moves. Only move-related properties should be analyzed here. And I'm not entirely sure that they are best analyzed in this object: I think the existing external
ReplicaNetworkobject is a better place for analyzing replica exchange-related properties.