En sympy he definido dos kets y un bra correspondiente, cuando aplico el bra a los kets...
from sympy import sqrt from sympy.physics.quantum import Bra,Ket,qapply superpos = (Ket('Dead')+Ket('Alive'))/sqrt(2) d = qapply(Bra('Dead')*superpos)... obtengo este resultado:
sqrt(2)*<Dead|Alive>/2 + sqrt(2)*<Dead|Dead>/2 ¿Cómo configuro 'Dead' y 'Alive' como estados ortogonales, de modo que d.doit() proporcione sqrt(2)/2 ?
Hasta ahora solo he podido sustituir los frenos a mano:
d.subs(Bra('Dead')*Ket('Dead'),1).subs(Bra('Dead')*Ket('Alive'),0) Pero, ¿cómo hago para que los frenos se evalúen automáticamente? ¿Por qué el producto interno no InnerProduct resultado 1 para paréntesis idénticos y 0 para paréntesis con etiquetas diferentes?
Su problema es que InnerProduct no sabe cómo evaluar estos valores y, por lo tanto, deja la expresión sin simplificar. Mirando la fuente , veo que intenta llamar a _eval_innerproduct() en el Ket , que dice esto.
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. """ Por lo tanto, debería poder resolver su problema creando 2 nuevas clases de Bra y una nueva clase de Ket que implementa 2 métodos, uno para evaluar cada uno de los productos internos (usando la convención de nomenclatura exigida anteriormente).
Para completar, probablemente también desee implementar el otro Ket para su estado ortogonal y asegurarse de que dual_class devuelva la clase correcta en cada caso.
Como Peter señala en su respuesta, debe implementar una nueva clase de Bra and Ket usted mismo. Esta es una buena implementación general para estados ortogonales que puede usar.
Ejemplo de uso:
>>> OrthogonalBra(n)*OrthogonalKet(n) 1 >>> OrthogonalBra(n)*OrthogonalKet(n+1) 0 >>> OrthogonalBra(n)*OrthogonalKet(m) <n|m>Implementación:
class OrthogonalKet(Ket): @classmethod def dual_class(self): return OrthogonalBra def _eval_innerproduct(self, bra, **hints): if len(self.args) != len(bra.args): raise ValueError('Cannot multiply a ket that has a different number of labels.') for i in range(len(self.args)): diff = self.args[i] - bra.args[i] diff.simplify() if diff.is_nonzero: return 0 if not diff.is_zero: return None return 1 class OrthogonalBra(Bra): @classmethod def dual_class(self): return OrthogonalKetEsto no es exactamente lo que está buscando, pero puede usar Qubit para crear estados ortogonales.
from sympy import sqrt from sympy.physics.quantum import Dagger, qapply from sympy.physics.quantum.qubit import Qubit dead = Qubit(0) alive = Qubit(1) Estos crean Ket(0) y Ket(1) . Para hacer el sujetador, puedes usar la función Dagger .
print(Dagger(dead) * dead) <0|0>Cuando se aplica a su problema:
superpos = (dead + alive) / sqrt(2) d = qapply(Dagger(dead) * superpos) print(d) sqrt(2)/2