Download Notebook

Composition of QOperations

This note describes how to calculate composition of qoperations.

Composition

Composition is an operation in the time direction. To compute the tensor product, use compose_qoperations() in the quara.objects.operators module.

As a simple example, let’s look at how to compute the composition of the following State and Gate.

formula:

\((G_{z}, \rho_{z0})\)

quantum circuit diagram:

── \(\rho_{z0}\)\(G_{z}\) ──

First, prepare State and Gate to be used for the operation. Note that the IDs of the ElementalSystems between QOperations to be calculated with composition must be same.

[1]:
from quara.objects.composite_system_typical import generate_composite_system
from quara.objects.qoperation_typical import generate_qoperation

# Prepare State and Gate
c_sys = generate_composite_system("qubit", 1, ids_esys=[0])
state = generate_qoperation(mode="state", name="z0", c_sys=c_sys)
gate = generate_qoperation(mode="gate", name="z", c_sys=c_sys)

print(f"vec of state: \n{state.vec}")
print(f"HS of gate: \n{gate.hs}")
vec of state:
[0.70710678 0.         0.         0.70710678]
HS of gate:
[[ 1.  0.  0.  0.]
 [ 0. -1.  0.  0.]
 [ 0.  0. -1.  0.]
 [ 0.  0.  0.  1.]]

The composition of State and Gate can be written as follows. Note that the argument to compose_qoperations() specifies QOperations in the same order as the formula, not in the order on the quantum circuit.

[2]:
from quara.objects.operators import compose_qoperations

# Composition
result = compose_qoperations(gate, state)

# Result
print(result)
Type:
State

Dim:
2

Vec:
[0.70710678 0.         0.         0.70710678]

Composition of three or more QOperations

For three or more QOepration operations, add to the argument. Let’s look at how to compute the composition of the following State, and Gate.

formula:

\((G_{x}, G_{z}, \rho_{z0})\)

quantum circuit diagram:

── \(\rho_{z0}\)\(G_{z}\)\(G_{x}\) ──

[3]:
# Prepare State, POVM, and Gate
c_sys_0 = generate_composite_system("qubit", 1, ids_esys=[0])

state = generate_qoperation(mode="state", name="z0", c_sys=c_sys)
gate_0 = generate_qoperation(mode="gate", name="z", c_sys=c_sys)
gate_1 = generate_qoperation(mode="gate", name="x", c_sys=c_sys)

# Composition of three or more QOperations
result = compose_qoperations(gate_1, gate_0, state)
print(result)
Type:
State

Dim:
2

Vec:
[ 0.70710678  0.          0.         -0.70710678]

It is also possible to specify QOperations as a list. For example, the following two expressions have the same meaning.

[4]:
# Specify by appending to the argument
result = compose_qoperations(gate_1, gate_0, state)

# Specify by list
result = compose_qoperations([gate_1, gate_0, state])

Supported operations

The compose_qoperations() supports the following combinations of QOperations.

Input

Output

(Gate, Gate)

Gate

(Gate, MProcess)

MProcess

(MProcess, Gate)

MProcess

(MProcess, MProcess)

MProcess

(Gate, State)

State

(MProcess, State)

StateEnsemble

(Mprocess, StateEnsemble)

StateEnsemble

(Povm, Gate)

Povm

(Povm, MProcess)

Povm

(Povm, State)

MultinomialDistribution

(Povm, StateEnsemble)

MultinomialDistribution

Examples

(Gate, Gate) -> Gate

[5]:
# Prepare
c_sys = generate_composite_system("qubit", 1, ids_esys=[0])
gate_0 = generate_qoperation(mode="gate", name="z", c_sys=c_sys)
gate_1 = generate_qoperation(mode="gate", name="x", c_sys=c_sys)

# Compose
result = compose_qoperations(gate_1, gate_0)
print(result)  # Gate
Type:
Gate

Dim:
2

HS:
[[ 1.  0.  0.  0.]
 [ 0. -1.  0.  0.]
 [ 0.  0.  1.  0.]
 [ 0.  0.  0. -1.]]

(Gate, MProcess) -> MProcess

[6]:
# Prepare
c_sys = generate_composite_system("qubit", 1, ids_esys=[0])
gate = generate_qoperation(mode="gate", name="z", c_sys=c_sys)
mprocess = generate_qoperation(mode="mprocess", name="x-type1", c_sys=c_sys)

# Compose
result = compose_qoperations(gate, mprocess)
print(result)  # MProcess
Type:
MProcess

Dim:
2

HSs:
[array([[ 0.5,  0.5,  0. ,  0. ],
       [-0.5, -0.5,  0. ,  0. ],
       [ 0. ,  0. ,  0. ,  0. ],
       [ 0. ,  0. ,  0. ,  0. ]]), array([[ 0.5, -0.5,  0. ,  0. ],
       [ 0.5, -0.5,  0. ,  0. ],
       [ 0. ,  0. ,  0. ,  0. ],
       [ 0. ,  0. ,  0. ,  0. ]])]

ModeSampling:
False

(MProcess, Gate) -> MProcess

[7]:
# Prepare
c_sys = generate_composite_system("qubit", 1, ids_esys=[0])
mprocess = generate_qoperation(mode="mprocess", name="x-type1", c_sys=c_sys)
gate = generate_qoperation(mode="gate", name="z", c_sys=c_sys)

# Compose
result = compose_qoperations(mprocess, gate)
print(result)  # MProcess
Type:
MProcess

Dim:
2

HSs:
[array([[ 0.5, -0.5,  0. ,  0. ],
       [ 0.5, -0.5,  0. ,  0. ],
       [ 0. ,  0. ,  0. ,  0. ],
       [ 0. ,  0. ,  0. ,  0. ]]), array([[ 0.5,  0.5,  0. ,  0. ],
       [-0.5, -0.5,  0. ,  0. ],
       [ 0. ,  0. ,  0. ,  0. ],
       [ 0. ,  0. ,  0. ,  0. ]])]

ModeSampling:
False

(Gate, State) -> State

[8]:
# Prepare
c_sys = generate_composite_system("qubit", 1, ids_esys=[0])
gate = generate_qoperation(mode="gate", name="z", c_sys=c_sys)
state = generate_qoperation(mode="state", name="z0", c_sys=c_sys)

# Compose
result = compose_qoperations(gate, state)
print(result)  # State
Type:
State

Dim:
2

Vec:
[0.70710678 0.         0.         0.70710678]

(MProcess, State) -> StateEnsemble

[9]:
# Prepare
c_sys = generate_composite_system("qubit", 1, ids_esys=[0])
mprocess = generate_qoperation(mode="mprocess", name="x-type1", c_sys=c_sys)
state = generate_qoperation(mode="state", name="z0", c_sys=c_sys)

# Compose
result = compose_qoperations(mprocess, state)
print(result)  # StateEnsemble
Type:
StateEnsemble

States:
states[0]: [0.70710678 0.70710678 0.         0.        ]
states[1]: [ 0.70710678 -0.70710678  0.          0.        ]

MultinomialDistribution:
shape = (2,)
ps = [0.5 0.5]

(MProcess, StateEnsemble) -> StateEnsemble

[10]:
# Prepare
c_sys = generate_composite_system("qubit", 1, ids_esys=[0])
mprocess = generate_qoperation(mode="mprocess", name="x-type1", c_sys=c_sys)
state_ensemble = generate_qoperation(mode="state_ensemble", name="z0", c_sys=c_sys)

# Compose
result = compose_qoperations(mprocess, state_ensemble)
print(result)  # StateEnsemble
Type:
StateEnsemble

States:
states[0]: [0.70710678 0.70710678 0.         0.        ]
states[1]: [ 0.70710678 -0.70710678  0.          0.        ]
states[2]: [0. 0. 0. 0.]
states[3]: [0. 0. 0. 0.]

MultinomialDistribution:
shape = (2, 2)
ps = [0.5 0.5 0.  0. ]

(Povm, Gate) -> Povm

[11]:
# Prepare
c_sys = generate_composite_system("qubit", 1, ids_esys=[0])
povm = generate_qoperation(mode="povm", name="x", c_sys=c_sys)
gate = generate_qoperation(mode="gate", name="z", c_sys=c_sys)

# Compose
result = compose_qoperations(povm, gate)
print(result)  # Povm
Type:
Povm

Dim:
2

Number of outcomes:
2

Vecs:
[[ 0.70710678 -0.70710678  0.          0.        ]
 [ 0.70710678  0.70710678  0.          0.        ]]

(Povm, MProcess) -> Povm

[12]:
# Prepare
c_sys = generate_composite_system("qubit", 1, ids_esys=[0])
povm = generate_qoperation(mode="povm", name="x", c_sys=c_sys)
mprocess = generate_qoperation(mode="mprocess", name="x-type1", c_sys=c_sys)

# Compose
result = compose_qoperations(povm, mprocess)
print(result)  # Povm
Type:
Povm

Dim:
2

Number of outcomes:
4

Vecs:
[[ 0.70710678  0.70710678  0.          0.        ]
 [ 0.          0.          0.          0.        ]
 [ 0.          0.          0.          0.        ]
 [ 0.70710678 -0.70710678  0.          0.        ]]

(Povm, State) -> MultinomialDistribution

[13]:
# Prepare
c_sys = generate_composite_system("qubit", 1, ids_esys=[0])
povm = generate_qoperation(mode="povm", name="x", c_sys=c_sys)
state = generate_qoperation(mode="state", name="z0", c_sys=c_sys)

# Compose
result = compose_qoperations(povm, state)
print(type(result))
print(result)  # MultinomialDistribution
<class 'quara.objects.multinomial_distribution.MultinomialDistribution'>
shape = (2,)
ps = [0.5 0.5]

(Povm, StateEnsemble) -> MultinomialDistribution

[14]:
# Prepare
c_sys = generate_composite_system("qubit", 1, ids_esys=[0])
povm = generate_qoperation(mode="povm", name="x", c_sys=c_sys)
state_ensemble = generate_qoperation(mode="state_ensemble", name="z0", c_sys=c_sys)

# Compose
result = compose_qoperations(povm, state_ensemble)
print(type(result))
print(result)  # MultinomialDistribution
<class 'quara.objects.multinomial_distribution.MultinomialDistribution'>
shape = (2, 2)
ps = [0.5 0.5 0.  0. ]

Download Notebook