:

## Quantum Teleportation in Dirac notation with MAPLE

Maple

This is an application of the previous posts
https://www.mapleprimes.com/posts/209057-Procedure-For-Expanding-Tensor-Product

I have a fourth version of the ExpandQop that will expand automaticaly the power of
quantum tensor product. This is just a minor change to the procedure.

Now here is an application for all this that will help understanding a little about
quantum computing. This is the classical concept of quantum teleportation.

You will need to run the above mentionned file and uncomment the save line in the file
before running the example.

LL

 > ###################################################################### # NOTICE                                                             # # Author: Louis Lamarche                                             # #         Institute of Research of Hydro-Quebec (IREQ)               # #         Science des données et haute performance                   # #         2018, March 7                                              # #                                                                    # # Function name: ExpandQop (x)                                       # #       Purpose: Compute the tensor product of two quantum           # #                operators in Dirac notations                        # #      Argument: x: a quantum operator                               # #  Improvements: Manage all +, -, *, /, ^, mod  operations           # #                in the argument. Manages multiple tensor products   # #                like A*B*C*F                                        # #       Version: 3                                                   # #                                                                    # #  Copyrigth(c) Hydro-Quebec.                                        # #        Note 1: Permission to use this softwate is granted if you   # #                acknowledge its author and copyright                # #        Note 2: Permission to copy this softwate is granted if you  # #                leave this 21 lines notice intact. Thank you.       # ###################################################################### restart;
 > with(Physics): interface(imaginaryunit=i): Setup(mathematicalnotation=true);
 (1)
 > Setup(unitaryoperators={I,U,X,Y,Z,H,HI,CNOT,CnotI}); Setup(noncommutativeprefix={q,beta,psi});
 (2)
 > Setup(bracketrules= { %Bracket(%Bra(q0), %Ket(q0))=1,                       %Bracket(%Bra(q1), %Ket(q1))=1,                       %Bracket(%Bra(q1), %Ket(q0))=0,                       %Bracket(%Bra(q0), %Ket(q1))=0                     });
 (3)
 > #################################################################################### # Load the procedure and set the required global variables # read "ExpandQop.m": optp:=op(0,Ket(q0)*Ket(q1)): optpx:= op(0,(Ket(q0)+Ket(q1))^2): # ####################################################################################
 > # # Pauli operators # print("Pauli gates"); I:=Ket(q0)*Bra(q0)+Ket(q1)*Bra(q1);        # = sigma[0] X:=Ket(q1)*Bra(q0)+Ket(q0)*Bra(q1);        # = sigma[1] = sigma[x] Y:=-i*Ket(q1)*Bra(q0)+i*Ket(q0)*Bra(q1);   # = sigma[2] = sigma[y] Z:=Ket(q0)*Bra(q0)-Ket(q1)*Bra(q1);        # = sigma[3] = sigma[z]
 (4)
 > ############################## # Defining the Hadamard gate # ############################## print("Hadamard gate"); H:= Ket(q0)*Bra(q0)/sqrt(2)+Ket(q0)*Bra(q1)/sqrt(2)+Ket(q1)*Bra(q0)/sqrt(2)-Ket(q1)*Bra(q1)/sqrt(2);
 (5)
 > # This is usefull to represent a 2 qubits system # A more general approach is needed for a n qubit system. DefineStates:=proc()     Ket(q00):=Ket(q0)*Ket(q0);  Ket(q01):=Ket(q0)*Ket(q1);     Ket(q10):=Ket(q1)*Ket(q0);  Ket(q11):=Ket(q1)*Ket(q1);     Bra(q00):=Dagger(Ket(q00)); Bra(q01):=Dagger(Ket(q01));     Bra(q10):=Dagger(Ket(q10)); Bra(q11):=Dagger(Ket(q11));     return;     end proc: UndefineStates:=proc()     Ket(q00):='Ket(q00)'; Ket(q01):='Ket(q01)';     Ket(q10):='Ket(q10)'; Ket(q11):='Ket(q11)';     Bra(q00):='Bra(q00)'; Bra(q01):='Bra(q01)';     Bra(q10):='Bra(q10)'; Bra(q11):='Bra(q11)';     return;     end proc:
 > #################################### # Defining the CNOT gate (2 qubits) #################################### print("CNOT gate"); CNOT:=Ket(q00)*Bra(q00)+ Ket(q01)*Bra(q01)+ Ket(q11)*Bra(q10)+Ket(q10)*Bra(q11); DefineStates(); 'CNOT'=CNOT;
 (6)
 > ########################### # Defining the Bell states ########################### Ket(beta,x,y)='CNOT.(((H.Ket(x)))*Ket(y))'; Ket(beta00):=CNOT.(Expand((H.Ket(q0)))*Ket(q0)); Ket(beta01):=CNOT.(Expand((H.Ket(q0)))*Ket(q1)); Ket(beta10):=CNOT.(Expand((H.Ket(q1)))*Ket(q0)); Ket(beta11):=CNOT.(Expand((H.Ket(q1)))*Ket(q1));
 (7)
 > ########################################################## # Quantum teleportation # Reference: Quantum Computation and Quantum Information #            10th Anniversary Edition #            Michael A. Nielsen & Isaac L. Chuang #            Cambridge University Press, Cambridge 2010 #            pp 25-28 ########################################################## print("State to be teleported"); Ket(psi) := a*Ket(q0)+b*Ket(q1); print("Step 1: Compute the tensor product of the state to be teleported with ", 'Ket(beta00)'); Ket(psi[0])='Ket(psi)'*'Ket(beta00)'; Ket(psi[0]):=Expand(Ket(psi)*Ket(beta00)); print("This is a 3 qubits state"); ####### print("Step 2: Pass these 3 qubits through a  CNOT*I  operator"); 'CnotI'='CNOT*I'; CnotI:=ExpandQop(Expand(CNOT*I)): # # To see what the CNOTI operator looks like # # print("CNOTI="); # print(op(1,CNOTI)+op(2,CNOTI)+op(3,CNOTI)+op(4,CNOTI)); # print(op(5,CNOTI)+op(6,CNOTI)+op(7,CNOTI)+op(8,CNOTI)); 'Ket(psi[1])'='CnotI.Ket(psi[0])'; Ket(psi[1]):=Expand(CnotI.Ket(psi[0])); ####### print("Step 3: Pass these 3 qubits through an Haldamard*I  operator"); 'HalI'='H*I'; HalI:=ExpandQop(Expand(H*I)): # # To see what the Haldamard*I operator looks like # # print("HalI="); # print(op(1,HalI)+op(2,HalI)+op(3,HalI)+op(4,HalI)); # print(op(5,HalI)+op(6,HalI)+op(7,HalI)+op(8,HalI)); 'Ket(psi[2])'='HalI.Ket(psi[1])'; Ket(psi[2]):=Expand(HalI.Ket(psi[1]));
 (8)
 > UndefineStates(); print("Using contracted names for the first two qubits"); Ket(q00)*Bra(q0)*Bra(q0)='I'; Ket(q01)*Bra(q0)*Bra(q1)='I'; Ket(q10)*Bra(q1)*Bra(q0)='I'; Ket(q11)*Bra(q1)*Bra(q1)='I'; 'Ket(psi[2])'=Ket(q00)*Bra(q0)*Bra(q0).Ket(psi[2])+               Ket(q01)*Bra(q0)*Bra(q1).Ket(psi[2])+               Ket(q10)*Bra(q1)*Bra(q0).Ket(psi[2])+               Ket(q11)*Bra(q1)*Bra(q1).Ket(psi[2]);
 (9)
 > print("Rewriting this result by hand"); 'Ket(psi[2])'=(Ket(q00)*(a*Ket(q0)+b*Ket(q1))+                Ket(q01)*(a*Ket(q0)-b*Ket(q1))+                Ket(q10)*(a*Ket(q1)+b*Ket(q0))+                Ket(q11)*(a*Ket(q1)-b*Ket(q0)))/2;
 (10)
 > DefineStates(); print("If Alice measures 00 Bob does noting"); ''I'.   '2*Bra(q00).Ket(psi[2])'' =  I.   2*Bra(q00).Ket(psi[2]); print("If Alice measures 01 Bob applies the X gate"); ''X'.   '2*Bra(q01).Ket(psi[2])'' =  X.   2*Bra(q01).Ket(psi[2]); print("If Alice measures 10 Bob applies the Z gate"); ''Z'.   '2*Bra(q10).Ket(psi[2])'' =  Z.   2*Bra(q10).Ket(psi[2]); print("If Alice measures 11 Bob applies the X gate and then the Z gate"); ''Z'.'X'. '2*Bra(q11).Ket(psi[2])'' =  Z.X. 2*Bra(q11).Ket(psi[2]);
 (11)
 >