Friday, August 6, 2010

QMul, QAdd, and QPow

My time this week has been spent working on Matt's project. In my last post, I mentioned how there was difficulty teaching the code to adhere to special quantum rules as the quantum objects get swallowed up inside Mul, Add and Pow objects. In order to remedy this, I needed to create a new set of binary operation classes that adhere to these rules with the same op-priority as other quantum objects.

To do this, I put logic inside the binary-ops' __new__ method which called a set of logic rules. These rules return an instance of the correct object if an object should be created or raise an error if the input expression is nonesense. For this to work, binary-op objects must know to what quantum type they evaluate (e.g. to what Hilbert space they belong as well as whether they act as a Ket, Bra, or Operator when evaluated). Thus, I used __slots__ to contain 'hilbert_space' and 'evaluates' attributes; these attributes are set during initialization in the 'rules' class methods. To make this simpler, all Quantum Objects inherit from a QuantumBasic class which contains the op_priority information, __slots__ for 'hilbert_space' and 'evaluates', as well as the __mul__, __add__, __pow__ methods which call the __new__ method of our new binary operations.

I mostly have this logic working such that it can flatten non-commutatively for QMul and commutatively for QAdd. However, I still need to get the .expand() method up and working. That said, there is still much testing that needs to be done before I can get this integrated with my code, which makes me worried as the GSoC pencil down date fast approaches.


  1. I should note that if you put your expand code in a method called _eval_expand_basic(), it will automatically work with the normal sympy expand().

  2. Thanks Aaron! You're comments are always very helpful. I was figuring I would put my logic in _eval_expand_mul() as that name seems to more accurately describe the type of expansion that I want to do (distributing a multiplication across an add). Also, Mul already seems to do this same type of logic in _eval_expand_mul. Since they are both set to true by default in Expr.expand(), does it matter which one I use?

  3. Yeah, if it fits one of the existing hints, just use that. I didn't know the exact nature of the expansion, and expand_basic() is designed to be a catch-all for strange expansion behaviors that want to be useable with expand(). The only difference is that you can turn each hint off using keyword arguments to expand(). For example, (x*(1 + y)**2).expand(mul=False) will only expand (1 + y)**2, but not distribute x over the result (similarly, Chris Smith has been working on a patch that would make expand(mul=True) only expand mul and skip all the rest).