[docs]classStateBase(QExpr):"""Abstract base class for general abstract states in quantum mechanics. All other state classes defined will need to inherit from this class. It carries the basic structure for all other states such as dual, _eval_adjoint and label. This is an abstract base class and you should not instantiate it directly, instead use State. """@classmethoddef_operators_to_state(self,ops,**options):""" Returns the eigenstate instance for the passed operators. This method should be overridden in subclasses. It will handle being passed either an Operator instance or set of Operator instances. It should return the corresponding state INSTANCE or simply raise a NotImplementedError. See cartesian.py for an example. """raiseNotImplementedError("Cannot map operators to states in this class. Method not implemented!")def_state_to_operators(self,op_classes,**options):""" Returns the operators which this state instance is an eigenstate of. This method should be overridden in subclasses. It will be called on state instances and be passed the operator classes that we wish to make into instances. The state instance will then transform the classes appropriately, or raise a NotImplementedError if it cannot return operator instances. See cartesian.py for examples, """raiseNotImplementedError("Cannot map this state to operators. Method not implemented!")@propertydefoperators(self):"""Return the operator(s) that this state is an eigenstate of"""from.operatorsetimportstate_to_operators# import internally to avoid circular import errorsreturnstate_to_operators(self)def_enumerate_state(self,num_states,**options):raiseNotImplementedError("Cannot enumerate this state!")def_represent_default_basis(self,**options):returnself._represent(basis=self.operators)#-------------------------------------------------------------------------# Dagger/dual#-------------------------------------------------------------------------@propertydefdual(self):"""Return the dual state of this one."""returnself.dual_class()._new_rawargs(self.hilbert_space,*self.args)@classmethod

[docs]defdual_class(self):"""Return the class used to construt the dual."""raiseNotImplementedError('dual_class must be implemented in a subclass')

def_eval_adjoint(self):"""Compute the dagger of this state using the dual."""returnself.dual#-------------------------------------------------------------------------# Printing#-------------------------------------------------------------------------def_pretty_brackets(self,height,use_unicode=True):# Return pretty printed brackets for the state# Ideally, this could be done by pform.parens but it does not support the angled < and ># Setup for unicode vs asciiifuse_unicode:lbracket,rbracket=self.lbracket_ucode,self.rbracket_ucodeslash,bslash,vert=u'\N{BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT}', \
u'\N{BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT}', \
u'\N{BOX DRAWINGS LIGHT VERTICAL}'else:lbracket,rbracket=self.lbracket,self.rbracketslash,bslash,vert='/','\\','|'# If height is 1, just return bracketsifheight==1:returnstringPict(lbracket),stringPict(rbracket)# Make height evenheight+=(height%2)brackets=[]forbracketinlbracket,rbracket:# Create left bracketifbracketin{_lbracket,_lbracket_ucode}:bracket_args=[' '*(height//2-i-1)+slashforiinrange(height//2)]bracket_args.extend([' '*i+bslashforiinrange(height//2)])# Create right bracketelifbracketin{_rbracket,_rbracket_ucode}:bracket_args=[' '*i+bslashforiinrange(height//2)]bracket_args.extend([' '*(height//2-i-1)+slashforiinrange(height//2)])# Create straight bracketelifbracketin{_straight_bracket,_straight_bracket_ucode}:bracket_args=[vertforiinrange(height)]else:raiseValueError(bracket)brackets.append(stringPict('\n'.join(bracket_args),baseline=height//2))returnbracketsdef_sympystr(self,printer,*args):contents=self._print_contents(printer,*args)return'%s%s%s'%(self.lbracket,contents,self.rbracket)def_pretty(self,printer,*args):fromsympy.printing.pretty.stringpictimportprettyForm# Get bracketspform=self._print_contents_pretty(printer,*args)lbracket,rbracket=self._pretty_brackets(pform.height(),printer._use_unicode)# Put together statepform=prettyForm(*pform.left(lbracket))pform=prettyForm(*pform.right(rbracket))returnpformdef_latex(self,printer,*args):contents=self._print_contents_latex(printer,*args)# The extra {} brackets are needed to get matplotlib's latex# rendered to render this properly.return'{%s%s%s}'%(self.lbracket_latex,contents,self.rbracket_latex)

[docs]classKetBase(StateBase):"""Base class for Kets. This class defines the dual property and the brackets for printing. This is an abstract base class and you should not instantiate it directly, instead use Ket. """lbracket=_straight_bracketrbracket=_rbracketlbracket_ucode=_straight_bracket_ucoderbracket_ucode=_rbracket_ucodelbracket_latex=r'\left|'rbracket_latex=r'\right\rangle '@classmethoddefdefault_args(self):return("psi",)@classmethoddefdual_class(self):returnBraBasedef__mul__(self,other):"""KetBase*other"""fromsympy.physics.quantum.operatorimportOuterProductifisinstance(other,BraBase):returnOuterProduct(self,other)else:returnExpr.__mul__(self,other)def__rmul__(self,other):"""other*KetBase"""fromsympy.physics.quantum.innerproductimportInnerProductifisinstance(other,BraBase):returnInnerProduct(other,self)else:returnExpr.__rmul__(self,other)#-------------------------------------------------------------------------# _eval_* methods#-------------------------------------------------------------------------def_eval_innerproduct(self,bra,**hints):"""Evaluate the inner product betweeen this ket and a bra. This is called to compute <bra|ket>, where the ket is ``self``. This method will dispatch to sub-methods having the format:: ``def _eval_innerproduct_BraClass(self, **hints):`` Subclasses should define these methods (one for each BraClass) to teach the ket how to take inner products with bras. """returndispatch_method(self,'_eval_innerproduct',bra,**hints)def_apply_operator(self,op,**options):"""Apply an Operator to this Ket. This method will dispatch to methods having the format:: ``def _apply_operator_OperatorName(op, **options):`` Subclasses should define these methods (one for each OperatorName) to teach the Ket how operators act on it. Parameters ========== op : Operator The Operator that is acting on the Ket. options : dict A dict of key/value pairs that control how the operator is applied to the Ket. """returndispatch_method(self,'_apply_operator',op,**options)

[docs]classBraBase(StateBase):"""Base class for Bras. This class defines the dual property and the brackets for printing. This is an abstract base class and you should not instantiate it directly, instead use Bra. """lbracket=_lbracketrbracket=_straight_bracketlbracket_ucode=_lbracket_ucoderbracket_ucode=_straight_bracket_ucodelbracket_latex=r'\left\langle 'rbracket_latex=r'\right|'@classmethoddef_operators_to_state(self,ops,**options):state=self.dual_class().operators_to_state(ops,**options)returnstate.dualdef_state_to_operators(self,op_classes,**options):returnself.dual._state_to_operators(op_classes,**options)def_enumerate_state(self,num_states,**options):dual_states=self.dual._enumerate_state(num_states,**options)return[x.dualforxindual_states]@classmethoddefdefault_args(self):returnself.dual_class().default_args()@classmethoddefdual_class(self):returnKetBasedef__mul__(self,other):"""BraBase*other"""fromsympy.physics.quantum.innerproductimportInnerProductifisinstance(other,KetBase):returnInnerProduct(self,other)else:returnExpr.__mul__(self,other)def__rmul__(self,other):"""other*BraBase"""fromsympy.physics.quantum.operatorimportOuterProductifisinstance(other,KetBase):returnOuterProduct(other,self)else:returnExpr.__rmul__(self,other)def_represent(self,**options):"""A default represent that uses the Ket's version."""fromsympy.physics.quantum.daggerimportDaggerreturnDagger(self.dual._represent(**options))

[docs]classState(StateBase):"""General abstract quantum state used as a base class for Ket and Bra."""pass

[docs]classKet(State,KetBase):"""A general time-independent Ket in quantum mechanics. Inherits from State and KetBase. This class should be used as the base class for all physical, time-independent Kets in a system. This class and its subclasses will be the main classes that users will use for expressing Kets in Dirac notation [1]_. Parameters ========== args : tuple The list of numbers or parameters that uniquely specify the ket. This will usually be its symbol or its quantum numbers. For time-dependent state, this will include the time. Examples ======== Create a simple Ket and looking at its properties:: >>> from sympy.physics.quantum import Ket, Bra >>> from sympy import symbols, I >>> k = Ket('psi') >>> k |psi> >>> k.hilbert_space H >>> k.is_commutative False >>> k.label (psi,) Ket's know about their associated bra:: >>> k.dual <psi| >>> k.dual_class() <class 'sympy.physics.quantum.state.Bra'> Take a linear combination of two kets:: >>> k0 = Ket(0) >>> k1 = Ket(1) >>> 2*I*k0 - 4*k1 2*I*|0> - 4*|1> Compound labels are passed as tuples:: >>> n, m = symbols('n,m') >>> k = Ket(n,m) >>> k |nm> References ========== .. [1] http://en.wikipedia.org/wiki/Bra-ket_notation """@classmethoddefdual_class(self):returnBra

[docs]classBra(State,BraBase):"""A general time-independent Bra in quantum mechanics. Inherits from State and BraBase. A Bra is the dual of a Ket [1]_. This class and its subclasses will be the main classes that users will use for expressing Bras in Dirac notation. Parameters ========== args : tuple The list of numbers or parameters that uniquely specify the ket. This will usually be its symbol or its quantum numbers. For time-dependent state, this will include the time. Examples ======== Create a simple Bra and look at its properties:: >>> from sympy.physics.quantum import Ket, Bra >>> from sympy import symbols, I >>> b = Bra('psi') >>> b <psi| >>> b.hilbert_space H >>> b.is_commutative False Bra's know about their dual Ket's:: >>> b.dual |psi> >>> b.dual_class() <class 'sympy.physics.quantum.state.Ket'> Like Kets, Bras can have compound labels and be manipulated in a similar manner:: >>> n, m = symbols('n,m') >>> b = Bra(n,m) - I*Bra(m,n) >>> b -I*<mn| + <nm| Symbols in a Bra can be substituted using ``.subs``:: >>> b.subs(n,m) <mm| - I*<mm| References ========== .. [1] http://en.wikipedia.org/wiki/Bra-ket_notation """@classmethoddefdual_class(self):returnKet#-----------------------------------------------------------------------------# Time dependent states, bras and kets.#-----------------------------------------------------------------------------

[docs]classTimeDepState(StateBase):"""Base class for a general time-dependent quantum state. This class is used as a base class for any time-dependent state. The main difference between this class and the time-independent state is that this class takes a second argument that is the time in addition to the usual label argument. Parameters ========== args : tuple The list of numbers or parameters that uniquely specify the ket. This will usually be its symbol or its quantum numbers. For time-dependent state, this will include the time as the final argument. """#-------------------------------------------------------------------------# Initialization#-------------------------------------------------------------------------@classmethoddefdefault_args(self):return("psi","t")#-------------------------------------------------------------------------# Properties#-------------------------------------------------------------------------@propertydeflabel(self):"""The label of the state."""returnself.args[:-1]@propertydeftime(self):"""The time of the state."""returnself.args[-1]#-------------------------------------------------------------------------# Printing#-------------------------------------------------------------------------def_print_time(self,printer,*args):returnprinter._print(self.time,*args)_print_time_repr=_print_time_print_time_latex=_print_timedef_print_time_pretty(self,printer,*args):pform=printer._print(self.time,*args)returnpformdef_print_contents(self,printer,*args):label=self._print_label(printer,*args)time=self._print_time(printer,*args)return'%s;%s'%(label,time)def_print_label_repr(self,printer,*args):label=self._print_sequence(self.label,',',printer,*args)time=self._print_time_repr(printer,*args)return'%s,%s'%(label,time)def_print_contents_pretty(self,printer,*args):label=self._print_label_pretty(printer,*args)time=self._print_time_pretty(printer,*args)returnprinter._print_seq((label,time),delimiter=';')def_print_contents_latex(self,printer,*args):label=self._print_sequence(self.label,self._label_separator,printer,*args)time=self._print_time_latex(printer,*args)return'%s;%s'%(label,time)

[docs]classTimeDepKet(TimeDepState,KetBase):"""General time-dependent Ket in quantum mechanics. This inherits from ``TimeDepState`` and ``KetBase`` and is the main class that should be used for Kets that vary with time. Its dual is a ``TimeDepBra``. Parameters ========== args : tuple The list of numbers or parameters that uniquely specify the ket. This will usually be its symbol or its quantum numbers. For time-dependent state, this will include the time as the final argument. Examples ======== Create a TimeDepKet and look at its attributes:: >>> from sympy.physics.quantum import TimeDepKet >>> k = TimeDepKet('psi', 't') >>> k |psi;t> >>> k.time t >>> k.label (psi,) >>> k.hilbert_space H TimeDepKets know about their dual bra:: >>> k.dual <psi;t| >>> k.dual_class() <class 'sympy.physics.quantum.state.TimeDepBra'> """@classmethoddefdual_class(self):returnTimeDepBra

[docs]classTimeDepBra(TimeDepState,BraBase):"""General time-dependent Bra in quantum mechanics. This inherits from TimeDepState and BraBase and is the main class that should be used for Bras that vary with time. Its dual is a TimeDepBra. Parameters ========== args : tuple The list of numbers or parameters that uniquely specify the ket. This will usually be its symbol or its quantum numbers. For time-dependent state, this will include the time as the final argument. Examples ======== >>> from sympy.physics.quantum import TimeDepBra >>> from sympy import symbols, I >>> b = TimeDepBra('psi', 't') >>> b <psi;t| >>> b.time t >>> b.label (psi,) >>> b.hilbert_space H >>> b.dual |psi;t> """@classmethoddefdual_class(self):returnTimeDepKet