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
Weighted trajectories #2369
Weighted trajectories #2369
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for merging the results classes.
The default seems to be a relative weight of 1
. Meaning that it should work fine in solver which does not use it (stochastic). But should they just keep using Result
until we have a use for those weight?
It there a balancing tools for weight values?
If there are 2 runs, can both have a relative weight of 10 or 0.1 without affecting the end results? If there are 2 starting kets that we want to merge with a weight of 10:1, does the actual values matter or only the ratio?
I feel it would be safer to compute the relative weight as W(T) / sum_T(W(T))
instead of using the number of trajectories.
I am not sure how it works with weight changing over time...
qutip/solver/result.py
Outdated
# TODO this is wrong if trajectories have weights | ||
# unclear how to implement in case of time-dependent weights |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does photocurrent make sense for nm_mcsolve?
If it does not, we could raise an error when used with time-dependent weights.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It probably does not make sense for nm_mcsolve. I have added an error in the case of time-dependent weights, and removed the tests for it.
Thank you for your review.
I let them use
I have added a
Hmm unfortunately I think that this won't work. For the "improved sampling" case, the sum of the relative weights is not one. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's nice to merge McResultImprovedSampling
into McResult
, but the overall complexity has increased... I believe it would be better to move MultiTrajResult
to it's own file.
Did you review the dynamics-nmmonte,rst
? Adding a note/example of using the improved sampling option there would be good.
def merge(self, other, p=None): | ||
raise NotImplementedError("Merging results of the stochastic solvers " | ||
"is currently not supported. Please raise " | ||
"an issue on GitHub if you would like to " | ||
"see this feature.") | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is that not supported?
There are no weight to them, it should be the easiest to merge...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, merging the measurement
, dW
etc attributes of stochastic results doesn't work, I think. That was the reason why I removed merge here, but maybe that went too far.
Should I just remove this, or maybe leave in a warning in the case a user tries to merge stochastic results where store_measurement
was used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can be left as is for now. Merging measurement
and dW
should be easy, it can be done in another PR.
random_state = qutip.rand_ket(dim, seed=seed) | ||
traj.add(t, random_state) | ||
|
||
if time_dep_weights and np.random.randint(2): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is that options randomly used?
Having an options explicitly passed ignored randomly depending in a randint
result feels strange.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to add weights to only some of the trajectories, to test that nothing goes wrong if some of the traj don't have weights.
qutip/solver/result.py
Outdated
@@ -895,7 +970,31 @@ def __repr__(self): | |||
lines.append(">") | |||
return "\n".join(lines) | |||
|
|||
def __add__(self, other): | |||
def merge(self, other, p=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The __add__
is already in the users hand and part of the official interface.
It is documented in the guide (and maybe the tutorials).
It's new, so it's probably not used much, but still we shouldn't remove it without a deprecation warning or a major release...
It would be better to keep it as merging with the default value of p
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The __add__
still exists, and it does call merge with the default value of p
: https://github.com/pmenczel/qutip/blob/weighted-trajectories/qutip/solver/multitrajresult.py#L760
I introduced a new function merge
because adding an optional parameter p
to __add__
felt like a bad practice.
Thank you for the review. The complexity has increased, more than I expected when I started writing. I hope it is worth it? I have added a mention about the improved sampling option in the guide, and I will have a look at the tutorial notebook whether it makes sense to include somewhere there. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the increased complexity is fine in this case.
Everything looks good. Thank you.
def merge(self, other, p=None): | ||
raise NotImplementedError("Merging results of the stochastic solvers " | ||
"is currently not supported. Please raise " | ||
"an issue on GitHub if you would like to " | ||
"see this feature.") | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can be left as is for now. Merging measurement
and dW
should be easy, it can be done in another PR.
Description
Introduces weights for the trajectories of trajectory solvers. These weights enter all trajectory averages. This concept is a generalization of two things that are already in qutip:
nm_mcsolve
is simply a time-dependent weight from this point of viewmcsolve
weights the no-jump trajectory with its exact probability, and then only samples from the ensemble of trajectories with at least one jump.Currently, these two things cannot be combined: "improved sampling" does not work for
nm_mcsolve
. With these changes, it would work.In the future, there might be at least one more application for weighted trajectories:
mcsolve
, it might be useful to allow sampling of initial states with frequencies or probabilities that are different from their true prefactor in the initial state. The ratio between the sampling frequencies and true prefactors would be weights on the trajectories.This also fixes some things in merging
McResult
s andNmmcResult
s, and perhaps fixes the target tolerance computation for the "improved sampling" option.Implementation
A difficulty in the implementation is that the weights depend on the total number of trajectories in different ways. For example, the no-jump trajectory has a fixed weight that never changes, but all other trajectories come with prefactors$(1-p_0) / (N-1)$ where $p_0$ is the probability of the no-jump trajectory, and $N$ the total number of trajectories (including the one no-jump trajectory). For this reason, I separate weights into absolute weights (like $p_0$ ) and relative weights (like the others). The average is performed as follows:
where the first sum is over all trajectories T that have absolute weights, and the second sum over all other trajectories. Here,$w_a(T)$ and $w_r(T)$ are the absolute and relative weights, $\rho(T)$ the state associated with a trajectory, and $N_{\text{rel}}$ the number of trajectories that have not been assigned absolute weights.
Intuitively, the idea is that absolute weights are for trajectories where the contribution to the full state is known exactly, and the trajectories without absolute weights are the stochastic part.
Things to do
Related issues or PRs
#2235