From mhagger@rigel.krl.caltech.edu Tue Aug 30 13:29:58 EDT 1994 Article: 35596 of comp.text.tex Path: sifon!newsflash.concordia.ca!uunet!usc!elroy.jpl.nasa.gov!netline-fddi.jpl.nasa.gov!nntp-server.caltech.edu!rigel.krl.caltech.edu!mhagger From: mhagger@rigel.krl.caltech.edu (Michael Haggerty) Newsgroups: comp.text.tex Subject: Dirac bra-kets: subtler than you might think Date: 30 Aug 1994 02:41:40 GMT Organization: California Institute of Technology Lines: 129 Message-ID: <33u694$143@gap.cco.caltech.edu> NNTP-Posting-Host: rigel.krl.caltech.edu Summary: How to make a macro for Dirac bra-ket notation Keywords: Dirac, bra, ket, bracket Hello, I've experimented for hours and finally found a general macro to get TeX or LaTeX to output Dirac bra-ket notation as used in quantum physics. The problem is much subtler than it looks, as described below. My solution is still messy, and I'd welcome suggestions which simplify the macros. [There is a package on some sites called "hep.tex" which does Dirac bra-kets, but it doesn't worry about delimiter sizes---they're always small size---so it doesn't meet my requirements.] The goal is to write a macro so that $\braket{a}{b}$ generates something like: $\bigl< a \bigm| b \bigr>$ which of course looks like when typeset, a notation used frequently in quantum physics. The big problem (pun intended) is to get TeX to automatically choose the correct size (big, bigg, Big, etc or some other size) of delimiter satisfying: (1) appropriate to contain each of the two arguments 'a' and 'b', which may be complex expressions, and (2) with all three delimiters the same size. [There is a package on some sites called "hep.tex" which does Dirac bra-kets, but it doesn't attempt to get the right delimiter sizes---they're always small size---so it doesn't meet my requirements.] [What is really called for is: \def\braket#1#2{\left< #1 \middle| #2 \right>} but unfortunately there is no \middle operator.] The first trick is to use \vphantom to force all of the delimiters to be the same size: \def\braket#1#2{\left< #1 \vphantom{#2} \right| \left. #2 \vphantom{#1} \right>} Well, that's almost it---the delimiters are the right size, and everything's where it belongs...except that a null delimiter (the "\left.") actually causes TeX to put a little space, of width \nulldelimiterspace, in the output. So the result looks like: The obvious thing is to set \nulldelimiterspace=0pt; how to do it is a little less obvious, though. Simply putting it in the macro as written fails, because math mode spacing is not computed until the moment that math mode is left, which doesn't happen until after the context of the macro has been left. By that time our value of \nulldelimiterspace has been restored back to its old value, so the space is still there. Still, following the example of the definitions of \bigr, etc in plain.tex, we try the \hbox trick: \def\braket#1#2{\hbox{$\left< #1 \vphantom{#2} \right| \left. #2 \vphantom{#1} \right> \nulldelimiterspace=0pt \mathsurround=0pt$}} (the \mathsurround=0pt is to prevent TeX adding additional space because of the "$ $" pair). This is almost correct; the only remaining problem is that the arguments are now set in \textstyle, even if the original context was a \displaystyle. So if, for example, a fraction is put in the bra-ket, it is typeset small rather than large. That's not what I wanted. The only way I found to get around this is to use the combersome \mathchoice command, which requires four copies of the argument. To shorten the notation, I defined an auxiliary function \layermath, which adds a layer of \hbox to a math expression, and the following (final!) version of \braket, and a couple more trivial analogous commands dealing with "bra"s and "ket"s. (The only reason that the others are more trivial is that they have an even number of delimiters and so don't need any null delimiters.) ================= The final version: ====================================== \def\bra#1{\left< #1 \right|} \def\ket#1{\left| #1 \right>} \def\layermath#1{ \mathchoice {\hbox{$\displaystyle #1 \mathsurround=0pt$}} {\hbox{$\textstyle #1 \mathsurround=0pt$}} {\hbox{$\scriptstyle #1 \mathsurround=0pt$}} {\hbox{$\scriptscriptstyle #1 \mathsurround=0pt$}} } % produce <#1|#2> (a Dirac "bra-ket" inner product): \def\braket#1#2{\mathinner{\layermath{ \mathopen{\left< #1 \vphantom{#2} \right|} \left. #2 \vphantom{#1} \right> \nulldelimiterspace=0pt }}} % produce <#1|#2|#3> (a Dirac matrix element): \def\matrixel#1#2#3{\mathinner{ \mathopen{\left< #1 \vphantom{#2#3} \right|} #2 \mathclose{\left| #3 \vphantom{#1#2} \right>} }} % produce |#1><#2| (a Dirac projection operator): \def\ketbra#1#2{ \mathord{\left| #1 \vphantom{#2} \right>} \mathord{\left< #2 \vphantom{#1} \right|} } =========================================================================== Everything there has been explained above, except the use of \mathinner, \mathopen, \mathclose, and \mathord, which ensure that the spacing surrounding this expression is correct. This solution seems to work; let me know if you find any problems. However, it is quite inefficient, due to the fact that each of the arguments is typeset 8 (!) times to produce a \braket. I suppose that this could be improved by storing them in boxes during processing, but the arguments are typically small so I didn't worry about it. (Let me know if you make this modification.) I hope this posting prevents at least one person from having to figure these contortions out again. I will try to upload these macros to one of the archive sites, too. Michael mhagger@krl.caltech.edu