Skip to content
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

Compatibility with qutip v5 #116

Open
wants to merge 5 commits into
base: qutip5
Choose a base branch
from
Open

Compatibility with qutip v5 #116

wants to merge 5 commits into from

Conversation

BoxiLi
Copy link
Collaborator

@BoxiLi BoxiLi commented May 26, 2024

This is a fix to make krotov compatible with qutip version 5.

  • I replaced the oct_result.dump with the result from the first Jupyter Notebook example.
  • @Ericgig Would you have time to double-check if any of the changes I made may affect the performance? Especially the replacement of dense2D_to_fastcsr_fmode and spmvpy_csr. For the latter one, I simply multiply the data layer matrix to the vector and hope the dispatch works.
  • I have to lose the tolerance for the test of mesolve result from 1e-7 to 5e-4 in tests/test_objectives.py. I think it is just machine precision but I'm not entirely sure.
  • @goerz I don't know how to create a test file oct_result_incomplete.py for the serialization test, which is now the only test failing on my machine.

@goerz goerz added this to the 2.0 milestone May 26, 2024
Copy link
Member

@goerz goerz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This is super helpful!

The automatic tests seem to have had a lot of bitrot in the last couple of years, so it probably makes sense to deal with #117 first, and then rebase this. I'll try to have a look at that soon.

And then, of course, #119 would be the next step

@@ -15,6 +15,11 @@

import numpy as np
import qutip
from packaging.version import parse as parse_version
if parse_version(qutip.__version__) < parse_version("5"):
is_qutip5 = False
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to go into krotov v2.0, and I think it would be fine to make qutip v5.0 a requirement for that release. So I don't think this is needed. We can drop compatibility with QuTiP 4

@goerz goerz force-pushed the master branch 2 times, most recently from 28e1367 to e9754de Compare June 3, 2024 01:56
Comment on lines 261 to 266
return qutip.Qobj(
unstack_columns(self._y),
dims=state.dims,
isherm=True,
dtype="csr"
)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dtype is not a parameter of Qobj.
Is that output really sparse?
If the output need to be converted, use to:

Suggested change
return qutip.Qobj(
unstack_columns(self._y),
dims=state.dims,
isherm=True,
dtype="csr"
)
return qutip.Qobj(
unstack_columns(self._y),
dims=state.dims,
isherm=True,
).to("CSR")

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just as a note (and this could be a separate PR): The sparse storage of QuTiP objects was probably a major source of slowness in krotov. Most usages of this package would be for small Hilbert spaces – certainly all the examples are for small Hilbert spaces. If I followed QuTiP's development correctly, version 5 should have the ability to use dense storage internally, and it would be good to use that as much as possible here (in the examples). Of course, if people manually define their objectives with sparse objects, those should still be respected.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, with qutip v5 you can do things all dense. One should set the qutip default as dense matrix in krotov and use sparse only if required by users.

BTW, this function seems not tested, since the mistake Eric mentioned doesn't lead to any falling tests. Maybe they are in the notebooks you mentioned?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quite possibly… the notebooks definitely serve as "integration tests". With my update of the tooling, you should be able to run it locally and/or the CI should run it for you.

@@ -266,11 +280,17 @@ def _rhs(t, rho, L_list):
out = np.zeros(rho.shape[0], dtype=complex)
L = L_list[0][0]
L_coeff = L_list[0][1]
spmvpy_csr(L.data, L.indices, L.indptr, rho, L_coeff, out)
if is_qutip5:
out = L_coeff * L @ rho
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rho and out are numpy arrays that need to be wrapped.

Suggested change
out = L_coeff * L @ rho
rho = qutip.data.Dense(rho, copy=False)
out = qutip.data.matmul(L, rho, scale=L_coeff)

With return out.as_ndarray() at the end.

for n in range(1, len(L_list)):
L = L_list[n][0]
L_coeff = L_list[n][1]
spmvpy_csr(L.data, L.indices, L.indptr, rho, L_coeff, out)
if is_qutip5:
out = L_coeff * L @ rho
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spmvpy_csr has an implicit out += that was forgotten.

Suggested change
out = L_coeff * L @ rho
out = qutip.data.add(qutip.data.matmul(L, rho, scale=L_coeff), out)

We have imatmul_data_dense(left, right, scale, out) that does the matmul implace like spmvpy_csr, but no python binding. (It's only used in QobjEvo.)

Copy link
Collaborator Author

@BoxiLi BoxiLi Jun 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I keep things in qutip.Qobj, not NumPy array, since we have a much better initialization of Qobj now in v5. Will sparse_csr_qobj * dense_ket_qobj automatically use that imatmul_data_dense?

This will allow the switch between dense and csr.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the states, (out, rho) are used by scipy's ODE solver they must enter and exit as numpy's array.
imatmul_data_dense is equivalent to out += left @ right * scale, this can't be represented in Qobj.__matmul__ operation so no. QobjEvo.matmul_data(t, state, out) would use the inplace operation if out is given and dense. But this use the list format directly and rewriting to use QobjEvo is probably not a small task.

qutip.data.add and qutip.data.matmul use qutip's data that can be sparse, dense, jax etc. so it should enough to be able to switch between format.

@goerz
Copy link
Member

goerz commented Jun 4, 2024

I've updated the tooling for the krotov package (using hatch now) so that the CI testing works again. Also, Python and most non-QuTiP-dependencies have been updated to new versions.

So, the current master would be a good to rebase this one.

I don't know how to create a test file oct_result_incomplete.py for the serialization test

I've added comments in the test file to explain where these files come from, in case they need to be updated. Basically, they're copied from the example notebooks (for one of them, you'd have to temporarily add a oct_result.dump(filename) in the notebook)

which is now the only test failing on my machine.

There's probably also still the example notebooks, and for one of them, the weylcamber package will have to be updated to be compatible with QuTiP 5. Like here, it would be okay to make a breaking version that is only compatible with QuTiP 5.

@goerz
Copy link
Member

goerz commented Jun 4, 2024

I've released weylchamber v0.6 which supports qutip v5 (and only qutip v5)

@goerz
Copy link
Member

goerz commented Jun 4, 2024

@BoxiLi I rebased your PR branch on the latest master. For some reason, GitHub wouldn't allow me to force-push that back to your clone. So I've pushed the rebased commits to a quitp5 branch of the main repo.

Maybe you can update your own qutip5 branch with those commits. Alternatively, I've invited you with write access to the krotov repo, so maybe you can continue working on the qutip5 branch here. That would probably require closing this PR and opening a new one. Feel free to do that, if you want to go that way.

@BoxiLi
Copy link
Collaborator Author

BoxiLi commented Jun 4, 2024

Thanks @goerz , will have more time later this week on this!

And thanks @Ericgig for the corrections!

@goerz
Copy link
Member

goerz commented Jun 4, 2024

will have more time later this week on this!

Sounds good! If you run into any technical problems, let me know. You can also hit me up on the Unitary Fund Discord or the Julia Slack if there's something that would benefit from real-time discussion, or we can always hop on a Zoom call or something

@BoxiLi BoxiLi force-pushed the qutip5 branch 2 times, most recently from 189663f to 3743055 Compare June 13, 2024 10:39
@BoxiLi BoxiLi changed the base branch from master to qutip5 June 13, 2024 13:21
@BoxiLi
Copy link
Collaborator Author

BoxiLi commented Jun 14, 2024

@goerz All the main tests are passing now on Linux, I think I'll merge to krotov/qutip5 now and address the rest (like notebooks) separately

@BoxiLi
Copy link
Collaborator Author

BoxiLi commented Jun 14, 2024

The overhead in the new qutip.Qobj is much smaller compared to the old one, if the propagator is replaced by a hand-written expm, the example in notebook 1 (compared to NumPy in notebook 9) takes:
NumPy Array : 2s
qutip-v5 Dense: 3s
qutip-v5 CSR: 6s
qutip-v4: 21s

The overhead for using the ODE solver is still there, unfortunately, for now.

@goerz
Copy link
Member

goerz commented Jun 14, 2024

Very nice! And that's even without the further potential improvements from #119 (right?), which I think will make a big difference.

Let me know if you need any help or input with wrapping this up for final review and merging.

@BoxiLi
Copy link
Collaborator Author

BoxiLi commented Jun 14, 2024

Indeed, that is not considered, but one has to use a simple self-written expm propagator, not the default krotov propagators to bypass that.

Ok! I'll merge this to the development branch qutip5.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants