-
Notifications
You must be signed in to change notification settings - Fork 46
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
iterator method for interactions dict #329
Comments
I do not mind the additionnal method if there is a use for it. At first glance, it looks a bit wastefull to create such a very redundant tuple at every iteration, and to deal with the book keeping required to check if the type changed; but that may be a matter of use case. All of that to ask: what is your use case? |
Hi the test case is pretty common for what I do. Basically if one wants to use the vermouth molecule to do some computations, you frequently encounter loops over bond, angle etc. interactions. Most of the loops look the following nature:
At the same time the information that really matters are the inter_type and what is contained in the interaction tuple. Considering that the molecule has a special iterator (i.e. molecule.atoms) only for looping over node-keys, I thought having something for interactions is also justified. In addition there is the "problem" that the order over which the dict is iterated is not defined. I think we could gain some significant speed-up both in vermouth but also poyply or other projects by defining a normal order over which the interaction dict is looped over (i.e. first bonds, constraints, then angles and higher order interactions). I'd propose the following strategy:
|
Why did this get closed? I don't see the immediate advantage of this, but I don't hate it either. Creating a separate class is definitely overkill though. class Molecule(nx.Graph):
...
def interactions_iter(self):
order = self.sort_interactions() # Something like this already exists! See __str__.
for i_type in order:
for interaction in self.interactions[i_type]:
yield i_type, interaction No need to unpack the interaction, Especially when in the far far future we may turn Interaction into a class capable of evaluating energies (stares into the distance) |
I closed this because I didn't really see it go anywhere in near future and it seemed just polluting the issues for now. But I am already using vermouth to evaluate interactions both in polyply but also the mapping program for AA COG that I wrote. But I hacked a new class to overcome the issues here. |
Ok, in light of #443 it's time to reopen this. To summarize the discussion there: we need to be able to index interactions by atom indices in O(1) to quickly figure out which interactions already exist, and which are to be added. This means that the interactions need to be a dict with atom indices as keys. The catch is that some interactions (e.g. bonds) are symmetric, and this dict should somehow be clever enough to take that into account when determining membership. IMO the best way of doing that is to promote the namedtuple Sidenote: "let's use a set?" This doesn't work, since you'll be able to quickly see if a bond between atoms 3 and 5 exists, you won't be able to retrieve the associated parameters. To recap: we want a dict mapping atom indices in a symmetry-aware way to interactions which also contain/describe the atoms. Or, we go for the simple option where key = value. That sounds relatively clean? To summarize:
Example code: class SymmetricInteraction(Interaction):
def __hash__(self):
return hash((self.__class__.__name__, frozenset((self.atoms, tuple(reversed(self.atoms))), self.version))
def __eq__(self, other):
return hash(self) == hash(other) molecule.add_interaction(Bond(3, 5, params=['1', '0.2', '140'])
molecule.add_interaction(Angle(1, 3, 5, params=['1', '45', '25'])
bond_params = molecule.interactions[Bond(5, 3)].params
if Angle(5, 3, 1) in molecule.interactions: ...
for interaction_with_params in molecule.interactions: ... Advantages:
Drawbacks:
|
Currently the interactions dict needs to be iterated over in a two-fold fashion (i.e. first over inter_types the the interactions themselves). API wise I think we would greatly benefit from a iter_over_ineractions method that simply returns inter_type, interaction when looped over. Perhaps it can also be useful for book-keeping if there is a special order this function loops over the dictionary. @pckroon @jbarnoud any thoughts on this?
The text was updated successfully, but these errors were encountered: