State initialization
Qadence offers convenience routines for preparing initial quantum states.
These routines are divided into two approaches:
As a dense matrix.
From a suitable quantum circuit. This is available for every backend and it should be added
in front of the desired quantum circuit to simulate.
Let's illustrate the usage of the state preparation routine.
from qadence import random_state , product_state , is_normalized , StateGeneratorType
# Random initial state.
# the default `type` is StateGeneratorType.HaarMeasureFast
state = random_state ( n_qubits = 2 , type = StateGeneratorType . RANDOM_ROTATIONS )
# Check the normalization.
assert is_normalized ( state )
# Product state from a given bitstring.
# NB: Qadence follows the big endian convention.
state = product_state ( "01" )
Ra n dom i n i t ial s tate ge nerate d wi t h ro tat io ns :
s tate = [ 0.46333446+0.31591776 j 0. + 0. j -0.68407745-0.46642811 j
0. + 0. j ]
Produc t s tate correspo n di n g t o bi tstr i n g ' 01 ' :
s tate = [ 0.+0. j 1.+0. j 0.+0. j 0.+0. j ]
Now we see how to generate the product state corresponding to the one above with
a suitable quantum circuit.
from qadence import product_block , tag , hea , QuantumCircuit
from qadence.draw import display
state_prep_block = product_block ( "01" )
# display(state_prep_block)
# Let's now prepare a circuit.
n_qubits = 4
state_prep_block = product_block ( "0001" )
tag ( state_prep_block , "Prep block" )
circuit_block = tag ( hea ( n_qubits , depth = 2 ), "Circuit block" )
qc_with_state_prep = QuantumCircuit ( n_qubits , state_prep_block , circuit_block )
%3
cluster_106a0701258244b48ca7c84ae8d1ac27
Circuit block
cluster_6625fe09b869473eae9bc0ec64ba38df
Prep block
e9337dc72e9a4e9693643f0ca7c30fa1
0
f7f48c86ca02410abab2b005998bf74a
e9337dc72e9a4e9693643f0ca7c30fa1--f7f48c86ca02410abab2b005998bf74a
0e8d1aacdab148999772dde9804bcd1b
1
ea8b91f231a949e0b274df0bbfe374f6
RX(theta₀)
f7f48c86ca02410abab2b005998bf74a--ea8b91f231a949e0b274df0bbfe374f6
f9f5fd2740834abea6858995f95537b9
RY(theta₄)
ea8b91f231a949e0b274df0bbfe374f6--f9f5fd2740834abea6858995f95537b9
f2d1daebea3249909dfd8b4778458355
RX(theta₈)
f9f5fd2740834abea6858995f95537b9--f2d1daebea3249909dfd8b4778458355
692875b345184fefafcdbbdff0b79baf
f2d1daebea3249909dfd8b4778458355--692875b345184fefafcdbbdff0b79baf
c91ff8e79b1447589685fa8d1e2ec527
692875b345184fefafcdbbdff0b79baf--c91ff8e79b1447589685fa8d1e2ec527
c8c650f2ff044889a3817645fe7b1db3
RX(theta₁₂)
c91ff8e79b1447589685fa8d1e2ec527--c8c650f2ff044889a3817645fe7b1db3
f5cfb6dc89944bc8be33edad18eb262d
RY(theta₁₆)
c8c650f2ff044889a3817645fe7b1db3--f5cfb6dc89944bc8be33edad18eb262d
4c757e3e3f0a4e23b786c737100adb50
RX(theta₂₀)
f5cfb6dc89944bc8be33edad18eb262d--4c757e3e3f0a4e23b786c737100adb50
7b0dab3b65a34b62bcc14210ce435d88
4c757e3e3f0a4e23b786c737100adb50--7b0dab3b65a34b62bcc14210ce435d88
b6d8511cc8894226a8b4cd7a263a9cbc
7b0dab3b65a34b62bcc14210ce435d88--b6d8511cc8894226a8b4cd7a263a9cbc
15e7dd7b09cf47c4a0fc9648422d8de6
b6d8511cc8894226a8b4cd7a263a9cbc--15e7dd7b09cf47c4a0fc9648422d8de6
30c5731c85f44f3cb6022536f5316e43
2abf8579e2c94a0fb374ba7c20210f7f
0e8d1aacdab148999772dde9804bcd1b--2abf8579e2c94a0fb374ba7c20210f7f
3159117f7e954df9b9726ec0331cfe89
2
f6416644d85d43a5a3dedd45c8ba4ae1
RX(theta₁)
2abf8579e2c94a0fb374ba7c20210f7f--f6416644d85d43a5a3dedd45c8ba4ae1
c28a6048fb25466f997871df8e85c882
RY(theta₅)
f6416644d85d43a5a3dedd45c8ba4ae1--c28a6048fb25466f997871df8e85c882
a7aab4dfe0f2460f85708bd18d4626b9
RX(theta₉)
c28a6048fb25466f997871df8e85c882--a7aab4dfe0f2460f85708bd18d4626b9
07a2884dff2d4dd99403e1c7e07650ae
X
a7aab4dfe0f2460f85708bd18d4626b9--07a2884dff2d4dd99403e1c7e07650ae
07a2884dff2d4dd99403e1c7e07650ae--692875b345184fefafcdbbdff0b79baf
e6d84a2e31a44324bf47f0b6d3f783a9
07a2884dff2d4dd99403e1c7e07650ae--e6d84a2e31a44324bf47f0b6d3f783a9
aced877cacfc45ff95d4c8f754db4b8c
RX(theta₁₃)
e6d84a2e31a44324bf47f0b6d3f783a9--aced877cacfc45ff95d4c8f754db4b8c
b8ac1300ae0f41dd979d993ab0cf04f1
RY(theta₁₇)
aced877cacfc45ff95d4c8f754db4b8c--b8ac1300ae0f41dd979d993ab0cf04f1
8748b993a6c34262b0c7e3d1c418b08d
RX(theta₂₁)
b8ac1300ae0f41dd979d993ab0cf04f1--8748b993a6c34262b0c7e3d1c418b08d
3023dcf86d014106b3890ef8edc9c79a
X
8748b993a6c34262b0c7e3d1c418b08d--3023dcf86d014106b3890ef8edc9c79a
3023dcf86d014106b3890ef8edc9c79a--7b0dab3b65a34b62bcc14210ce435d88
3daa71f3231b454cbb8a29f0761a9f91
3023dcf86d014106b3890ef8edc9c79a--3daa71f3231b454cbb8a29f0761a9f91
3daa71f3231b454cbb8a29f0761a9f91--30c5731c85f44f3cb6022536f5316e43
36e2f7b5444b45a18e1b1d8ed9bcff9a
41792b8f38a049bb850fd8df93900f80
3159117f7e954df9b9726ec0331cfe89--41792b8f38a049bb850fd8df93900f80
0bf0e56e921e4b68ad3382f222ad86b0
3
34c39bf8830b44f4b4073296b064e64a
RX(theta₂)
41792b8f38a049bb850fd8df93900f80--34c39bf8830b44f4b4073296b064e64a
1c2f9c994f9b42b3a973761c3aa2255c
RY(theta₆)
34c39bf8830b44f4b4073296b064e64a--1c2f9c994f9b42b3a973761c3aa2255c
5a6f3325935149fca6b6872d3e13dc0c
RX(theta₁₀)
1c2f9c994f9b42b3a973761c3aa2255c--5a6f3325935149fca6b6872d3e13dc0c
d920cd4a11cf4dc3805127ba3d1bfd8b
5a6f3325935149fca6b6872d3e13dc0c--d920cd4a11cf4dc3805127ba3d1bfd8b
917ef4b618d14d32befc427ba92f747e
X
d920cd4a11cf4dc3805127ba3d1bfd8b--917ef4b618d14d32befc427ba92f747e
917ef4b618d14d32befc427ba92f747e--e6d84a2e31a44324bf47f0b6d3f783a9
f8612a74563c49138333f0a555c363d3
RX(theta₁₄)
917ef4b618d14d32befc427ba92f747e--f8612a74563c49138333f0a555c363d3
034de624e3b34d56b32e892a922b82b1
RY(theta₁₈)
f8612a74563c49138333f0a555c363d3--034de624e3b34d56b32e892a922b82b1
71ac2377a81e4f20a47888289f27d797
RX(theta₂₂)
034de624e3b34d56b32e892a922b82b1--71ac2377a81e4f20a47888289f27d797
9fee2dc5e6614258be025cceaa5f6e67
71ac2377a81e4f20a47888289f27d797--9fee2dc5e6614258be025cceaa5f6e67
b4d5237e39eb4fa1a9068322941a5f99
X
9fee2dc5e6614258be025cceaa5f6e67--b4d5237e39eb4fa1a9068322941a5f99
b4d5237e39eb4fa1a9068322941a5f99--3daa71f3231b454cbb8a29f0761a9f91
b4d5237e39eb4fa1a9068322941a5f99--36e2f7b5444b45a18e1b1d8ed9bcff9a
1586e50e822f48948f5e7bfec9199619
52cff28c003345a2a5fb6ee04852e231
X
0bf0e56e921e4b68ad3382f222ad86b0--52cff28c003345a2a5fb6ee04852e231
7eada622819645148fe1f63cc3534c86
RX(theta₃)
52cff28c003345a2a5fb6ee04852e231--7eada622819645148fe1f63cc3534c86
a1e1c575176c4f6f9e0907a499920b7d
RY(theta₇)
7eada622819645148fe1f63cc3534c86--a1e1c575176c4f6f9e0907a499920b7d
f6a5162268d7451c970981fade4f9158
RX(theta₁₁)
a1e1c575176c4f6f9e0907a499920b7d--f6a5162268d7451c970981fade4f9158
e3b7b892acc9493d80826d686293de65
X
f6a5162268d7451c970981fade4f9158--e3b7b892acc9493d80826d686293de65
e3b7b892acc9493d80826d686293de65--d920cd4a11cf4dc3805127ba3d1bfd8b
566065c3f2194659ae84ebb84c63fe74
e3b7b892acc9493d80826d686293de65--566065c3f2194659ae84ebb84c63fe74
a56459e5d1174328b5041cda8318cad5
RX(theta₁₅)
566065c3f2194659ae84ebb84c63fe74--a56459e5d1174328b5041cda8318cad5
92fce19e7b24440b8fa20e52b4206bbc
RY(theta₁₉)
a56459e5d1174328b5041cda8318cad5--92fce19e7b24440b8fa20e52b4206bbc
093a06862b464b128e69eaa1eca19958
RX(theta₂₃)
92fce19e7b24440b8fa20e52b4206bbc--093a06862b464b128e69eaa1eca19958
b6eaf966a1ad4b13997a5e4209eec8c0
X
093a06862b464b128e69eaa1eca19958--b6eaf966a1ad4b13997a5e4209eec8c0
b6eaf966a1ad4b13997a5e4209eec8c0--9fee2dc5e6614258be025cceaa5f6e67
4d657692bd38460ab90bc2980f46f78d
b6eaf966a1ad4b13997a5e4209eec8c0--4d657692bd38460ab90bc2980f46f78d
4d657692bd38460ab90bc2980f46f78d--1586e50e822f48948f5e7bfec9199619
Several standard quantum states can be conveniently initialized in Qadence, both in statevector form as well as in block form as shown in following.
State vector initialization
Qadence offers a number of constructor functions for state vector preparation.
from qadence import uniform_state , zero_state , one_state
n_qubits = 3
batch_size = 2
uniform_state = uniform_state ( n_qubits , batch_size )
zero_state = zero_state ( n_qubits , batch_size )
one_state = one_state ( n_qubits , batch_size )
U n i f orm s tate =
tens or( [[ 0.3536+0. j , 0.3536+0. j , 0.3536+0. j , 0.3536+0. j , 0.3536+0. j , 0.3536+0. j , 0.3536+0. j ,
0.3536+0. j ],
[ 0.3536+0. j , 0.3536+0. j , 0.3536+0. j , 0.3536+0. j , 0.3536+0. j , 0.3536+0. j , 0.3536+0. j ,
0.3536+0. j ]] )
Zero s tate =
tens or( [[ 1.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j ],
[ 1.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j ]] )
O ne s tate =
tens or( [[ 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 1.+0. j ],
[ 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 1.+0. j ]] )
As already seen, product states can be easily created, even in batches:
from qadence import product_state , rand_product_state
# From a bitsring "100"
prod_state = product_state ( "100" , batch_size )
# Or a random product state
rand_state = rand_product_state ( n_qubits , batch_size )
Produc t s tate =
tens or( [[ 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 1.+0. j , 0.+0. j , 0.+0. j , 0.+0. j ]] )
Ra n dom s tate =
tens or( [[ 0.+0. j , 1.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j ],
[ 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 1.+0. j , 0.+0. j , 0.+0. j ]] )
Creating a GHZ state:
from qadence import ghz_state
ghz = ghz_state ( n_qubits , batch_size )
GHZ s tate =
tens or( [[ 0.7071+0. j , 0.0000+0. j , 0.0000+0. j , 0.0000+0. j , 0.0000+0. j , 0.0000+0. j , 0.0000+0. j ,
0.7071+0. j ],
[ 0.7071+0. j , 0.0000+0. j , 0.0000+0. j , 0.0000+0. j , 0.0000+0. j , 0.0000+0. j , 0.0000+0. j ,
0.7071+0. j ]] )
Creating a random state uniformly sampled from a Haar measure:
from qadence import random_state
rand_haar_state = random_state ( n_qubits , batch_size )
Ra n dom s tate fr om Haar =
tens or( [[ 0.1175-0.1590 j , -0.0951+0.4807 j , 0.3795+0.1401 j , 0.0923-0.0757 j ,
-0.0139+0.0967 j , 0.2482-0.4274 j , 0.0270+0.0782 j , 0.1034-0.5211 j ],
[ 0.4179-0.0928 j , 0.0479+0.2284 j , 0.4056-0.1999 j , -0.0744+0.2450 j ,
0.3361+0.2284 j , 0.1638+0.4372 j , -0.3177+0.0341 j , -0.0824+0.0170 j ]] )
Custom initial states can then be passed to either run
, sample
and expectation
through the state
argument
from qadence import random_state , product_state , CNOT , run
init_state = product_state ( "10" )
final_state = run ( CNOT ( 0 , 1 ), state = init_state )
Fi nal s tate = tens or( [[ 0.+0. j , 0.+0. j , 0.+0. j , 1.+0. j ]] )
Block initialization
Not all backends support custom statevector initialization, however previous utility functions have their counterparts to initialize the respective blocks:
from qadence import uniform_block , one_block
n_qubits = 3
uniform_block = uniform_block ( n_qubits )
one_block = one_block ( n_qubits )
Kro n Block( 0 , 1 , 2 )
├── H( 0 )
├── H( 1 )
└── H( 2 )
Kro n Block( 0 , 1 , 2 )
├── X( 0 )
├── X( 1 )
└── X( 2 )
Similarly, for product states:
from qadence import product_block , rand_product_block
product_block = product_block ( "100" )
rand_product_block = rand_product_block ( n_qubits )
Kro n Block( 0 , 1 , 2 )
├── X( 0 )
├── I( 1 )
└── I( 2 )
Kro n Block( 0 , 1 , 2 )
├── X( 0 )
├── X( 1 )
└── I( 2 )
And GHZ states:
from qadence import ghz_block
ghz_block = ghz_block ( n_qubits )
Chai n Block( 0 , 1 , 2 )
├── H( 0 )
└── Chai n Block( 0 , 1 , 2 )
├── CNOT( 0 , 1 )
└── CNOT( 1 , 2 )
Initial state blocks can simply be chained at the start of a given circuit.
Utility functions
Some state vector utility functions are also available. We can easily create the probability mass function of a given statevector using torch.distributions.Categorical
from qadence import random_state , pmf
n_qubits = 3
state = random_state ( n_qubits )
distribution = pmf ( state )
Ca te gorical(probs : t orch.Size( [ 1 , 8 ] ))
We can also check if a state is normalized:
from qadence import random_state , is_normalized
state = random_state ( n_qubits )
print ( is_normalized ( state ))
Or normalize a state:
import torch
from qadence import normalize , is_normalized
state = torch . tensor ([[ 1 , 1 , 1 , 1 ]], dtype = torch . cdouble )
print ( normalize ( state ))
tens or( [[ 0.5000+0. j , 0.5000+0. j , 0.5000+0. j , 0.5000+0. j ]] )