Cool results in represent

This post right now is just a quick update with an example python session showing the cool things we can do in represent now, after a very hectic week of code writing. I’m currently in the process of finalizing things in the way that represent works, so I will post a much more detailed post at some point later, but right now I just want to show that we can actually do quantum mechanics in continuous bases! (In this case, with the particle in a box system).

Here is an example python session with notes on the output:

>>> from sympy.physics.quantum import *
>>> from sympy.physics.quantum.piab import *
>>> wf = represent(PIABKet())
>>> wf
Wavefunction(2**(1/2)*(1/L)**(1/2)*sin(pi*n*x_1/L), (x_1, 0, L))
>>> wf.norm
1

We get a particle-in-the-box Wavefunction when it is represented and it’s properly normalized.

>>> represent(XOp()*PIABKet())
Wavefunction(2**(1/2)*x_2*(1/L)**(1/2)*sin(pi*n*x_2/L), x_2)

We now get a wavefunction with an extra factor of x!

>>> represent(PxOp()*PIABKet(), basis=XKet)
Wavefunction(-2**(1/2)*hbar*I*pi*n*(1/L)**(1/2)*cos(pi*n*x_2/L)/L, x_2)

The PxOp actually takes the derivative of the wavefunction correctly! (Momentum operators in the position basis are differential operators).

>>> represent(PIABBra()*XOp()*PIABKet(), basis=XKet)
0

Here, we insert two unities. The first one integrated collapses a delta function, but the second one integrated actually computes the expectation value of x for the particle-in-a-box wavefunction (which is what you expect from representing <psi|X|psi>).

EDIT: As you’ll see in the comments, Raoul pointed out that this is actually incorrect, and I will be looking into it!

There are still a few kinks being worked out, but we’re very close to having a nice finished product which is why I am reserving a longer post for tomorrow. I am quite pleased with the results we’re seeing so far though!

Advertisements

An altered internal API for default representations and fun with Wavefunctions

This week was a very, very busy week. While there were only a handful of commits, they were probably some of the most crucial ones yet in bringing this home and being able to start writing example systems. With pencils down only two weeks away, it is seriously crunchtime.

A very nice development was the incorporation of Wavefunctions (Wf) and Differential Operators (DO) into the main represent logic. If you now try to represent anything in cartesian.py, you will get expressions that actually include Wf and have the DO applied appropriately! (I will soon be adding support for a qapply flag, which if set to false will leave all DOs intact without applying them.) Support for this included adding calls to qapply as well a function which unwraps all Wf around expressions before integrating over unities, then rewrapping the final result in a single Wf object.

With this done, I moved on to another quite important task in the represent logic that I discussed with Brian. This involves dealing with the ambiguous case in represent where no basis is specified in the initial call to represent. The current way that the quantum modules are set up to handle this logic involves the states having an internal _represent_default_basis method, which simply calls the appropriate _represent_FOO method internally in the class. This entire process is basically a black box to the outer represent logic. This becomes a problem in continuous bases, where we actually need to know which basis was chosen for representing (in order to know if there were any unities inserted and integrate appropriately). This is also a more general problem in that if you have an arbitrary expression, you don’t know if all of the internal _represent_default_basis calls actually represent the individual QExprs in the same basis! You could, in fact, have one QExpr represented in a different basis than another and end up with some very weird things.

So, there are really two problems exposed by this API weakness, and we need to address them both. First, the main represent logic needs to know what the default basis for a given QExpr is. Second, in the case of arbitrary quantum expressions, we need to choose one basis to represent all of the individual QExprs in.

Brian and I have discussed strategies to address both of these issues. The first is a change in the internal API for default representations. Rather than using the current _represent_default_basis, classes should now contain an internal _get_default_basis, which simply returnsĀ  the class which is meant to be the default basis for that QExpr. This way, we can still replicate the previous behavior, but the main represent logic now knows which basis is the default for that class. Because this involves changing an already quite large base of classes in the spin and quantum computing modules, this was quite an arduous task. After much testing and grappling with errors, the spin and cartesian classes now follow the new represent conventions for this, with the quantum computing classes soon to follow. (I should note, that as these changes were made, the spin classes were also changed to follow additional new conventions for represent. The first is that internally, the basis option is converted to a basis state rather than left as an operator in represent. This means that all _represent_Op methods had to be changed to _represent_Ket methods. Second, rather than being able to specify a single operator, you must now specify the complete commuting set of operators for a given eigenket. This means, for the spin classes, rather than being able to pass basis=Jx, you now pass basis=set([J2, Jx]).)

The second change is to have represent choose which basis to represent in during the first step of the recursion. With the current algorithm, _represent_default_basis was simply called at the lowest level of the recursion, on the individual QExpr. Now, the basis is chosen based on the default basis of the first QExpr in the expression, and all QExprs in the arbitrary expression are represented in this basis. This means all the representations will be consistent and we aren’t left with any strange final expressions. This change in the represent logic is next on my TODO list.

It is really nice to see all of the pieces of a now very robust representation logic coming together. The schedule I have been following is not quite what I initially planned, but the changes to represent logic for continuous bases ended up being way more subtle than what I initially anticipated. With all the possibilities for different quantum systems out there, I really envision that at the end of the day this revamped represent will be able to handle what is thrown at it. By GSoC pencils down, I will have at least a few different nice example systems implemented and some very clear documentation. Documenting this is very important to me because I’ve put a ton of time into making sure it will work in very general cases (with Brian’s amazing help and discussion), so making sure users know how it works and how to use its full power is the most important thing to me.