Search code examples
latexsympymathjaxsage

sage notebook dirac bra-ket notation with latex


I'm having difficulty getting properly formatted latex output for notation in the sage notebook. I am using sympy for sympy.physics.quantum.Bra and Ket, but cant seem to get proper latex behaviour out of them.

for instance, I want to show the symbol psi in a ket.

sage: p = var('Psi')
sage: show(p)

displays the greek character {\Psi}

but using sympy

sage: k = Ket(p)
sage: show(k)

displays plain text |Psi>

I have searched, tested and experimented to try and get formatted output, to no avail.

sage: latex(k)

{\left|\Psi\right\rangle} - plain text

creating a custom latex macro:

sage: from sage.misc.latex import latex_extra_preamble
sage: latex.add_macro("\\newcommand{\\ket}[1]{\\left|{#1}\\right\\rangle}")
sage: var("myket", latex_name=r"\ket{\alpha}")
sage: show(myket)

gives the output i want! latex style ket with the symbol for alpha... however, as soon as I try to apply this method to the sympy Ket, it fails

sage: k = Ket('k', latex_name=r"\left|{\Psi}\right\rangle")
sage: show(k)

and other variants, all spit out plain-text |k>

I have a feeling that there is a simple solution for this, some flag that i'm missing to get sympy to behave properly in sage notebook.


Solution

  • Here is a solution. It is probably not very robust but it could probably be adapted to your need. They are two problems here:

    1 - You need to tell sage how to latex Bra and Ket. This can be done using latex_table which is a dict associating type to latex type-setting functions:

    from sympy.physics.quantum import Bra, Ket
    def latexBra(x):
        if len(x.args) == 1:  # x.args contains the argument of the Bra
            res = latex(x.args[0])
        else:
            res = ",".join(latex(i) for i in x.args)
        return r"{\left|%s\right\rangle}"%res
    
    from sage.misc.latex import latex_table
    latex_table[Bra] = latexBra
    

    Of course you have to do the same for Ket. You probably want to do that also for

    sympy.physics.quantum.operator.OuterProduct
    sympy.physics.quantum.operator.InnerProduct
    ...
    

    However, this only solve part of the problem: latexing the Bra. Note that Phi isn't latexed.

    sage: bPhi = Bra(var('Phi'))
    sage: print latex(bPhi)
    {\left|\text{\texttt{Phi}}\right\rangle}
    

    2 - The reason is that Sympy bPhi argument bPhi.args[0] is not exactly the Sage variable Phi but a Sympy Symbol object:

    sage: type(bPhi.args[0])
    <class 'sympy.core.symbol.Symbol'>
    

    However one can get back Sage's Phi by coercing the Symbol object back to Sage's symbolic ring (SR):

    sage: SR(bPhi.args[0]) is Phi
    True
    

    So you can do tell Sage to to that for latexing Sympy's Symbol:

    from sympy.core.symbol import Symbol
    latex_table[Symbol] = lambda x : latex(SR(x))
    

    And then:

    sage: bPhi = Bra(var('Phi'))
    sage: print latex(bPhi)
    {\left|\Phi\right\rangle}