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.94952497+0. j 0. -0.05645406 j -0.30802578+0. j
0. + 0.01831369 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_18e344f5490c4261ade95796f0c09bb8
Circuit block
cluster_03826e9360634e078c0e051d48080aa1
Prep block
f0c732dc8eee4cfa9a11e4e480f1fe8b
0
3dbae2f7e8834e9ea45741d0307f94e5
f0c732dc8eee4cfa9a11e4e480f1fe8b--3dbae2f7e8834e9ea45741d0307f94e5
5224847b5b6e4c01b344d238046a7a4b
1
d46dce2d1eb64b8fb22e9f82c9d2630b
RX(theta₀)
3dbae2f7e8834e9ea45741d0307f94e5--d46dce2d1eb64b8fb22e9f82c9d2630b
b63f046386b049d8a86e043bcf09b457
RY(theta₄)
d46dce2d1eb64b8fb22e9f82c9d2630b--b63f046386b049d8a86e043bcf09b457
8bb8c4141837469ca66f88179fbd7a93
RX(theta₈)
b63f046386b049d8a86e043bcf09b457--8bb8c4141837469ca66f88179fbd7a93
d9db305898e44b3dadd9769a7f2de14b
8bb8c4141837469ca66f88179fbd7a93--d9db305898e44b3dadd9769a7f2de14b
6d1109fd14ab49a29a2c85fae518b619
d9db305898e44b3dadd9769a7f2de14b--6d1109fd14ab49a29a2c85fae518b619
30e78f4017024f9b81dfc4846eb77fa3
RX(theta₁₂)
6d1109fd14ab49a29a2c85fae518b619--30e78f4017024f9b81dfc4846eb77fa3
6a99063ab0c6482b95ea235ee9528fe4
RY(theta₁₆)
30e78f4017024f9b81dfc4846eb77fa3--6a99063ab0c6482b95ea235ee9528fe4
bc5205c8124c431f9495858cbc8def0b
RX(theta₂₀)
6a99063ab0c6482b95ea235ee9528fe4--bc5205c8124c431f9495858cbc8def0b
dae01062d9fa44359de947e8dbc23776
bc5205c8124c431f9495858cbc8def0b--dae01062d9fa44359de947e8dbc23776
9770962b0eb241afb458482b10a7347c
dae01062d9fa44359de947e8dbc23776--9770962b0eb241afb458482b10a7347c
5891c9ed63f148e6bb71cb55c0207017
9770962b0eb241afb458482b10a7347c--5891c9ed63f148e6bb71cb55c0207017
a758d3f4aeeb454aaca30458330a4b51
0a8392ab951d486499637d730939fdaa
5224847b5b6e4c01b344d238046a7a4b--0a8392ab951d486499637d730939fdaa
5de67b97407f4603a822b751f789f82b
2
529b13691f2742dd9f61dab6b805b4a5
RX(theta₁)
0a8392ab951d486499637d730939fdaa--529b13691f2742dd9f61dab6b805b4a5
6c2e961678d34a8fbf94521689b96d2b
RY(theta₅)
529b13691f2742dd9f61dab6b805b4a5--6c2e961678d34a8fbf94521689b96d2b
60c90fcc13664aa29460a131e506cdb8
RX(theta₉)
6c2e961678d34a8fbf94521689b96d2b--60c90fcc13664aa29460a131e506cdb8
5c27a5fe0fdc4131bf9f1dad4cb31973
X
60c90fcc13664aa29460a131e506cdb8--5c27a5fe0fdc4131bf9f1dad4cb31973
5c27a5fe0fdc4131bf9f1dad4cb31973--d9db305898e44b3dadd9769a7f2de14b
caa967d58c3745c5b302321008590f44
5c27a5fe0fdc4131bf9f1dad4cb31973--caa967d58c3745c5b302321008590f44
fde2a49e5b1d44a8bf40e3ef8da6f314
RX(theta₁₃)
caa967d58c3745c5b302321008590f44--fde2a49e5b1d44a8bf40e3ef8da6f314
1a0c7c367ae044c2ba21100e99813e16
RY(theta₁₇)
fde2a49e5b1d44a8bf40e3ef8da6f314--1a0c7c367ae044c2ba21100e99813e16
942a3b04809d4031a4154c33b9961f35
RX(theta₂₁)
1a0c7c367ae044c2ba21100e99813e16--942a3b04809d4031a4154c33b9961f35
76871c3707cd48788712e6805c52d7ca
X
942a3b04809d4031a4154c33b9961f35--76871c3707cd48788712e6805c52d7ca
76871c3707cd48788712e6805c52d7ca--dae01062d9fa44359de947e8dbc23776
336a85c074884492af69d0688e86a559
76871c3707cd48788712e6805c52d7ca--336a85c074884492af69d0688e86a559
336a85c074884492af69d0688e86a559--a758d3f4aeeb454aaca30458330a4b51
2a3a09842cd646d3a1dfb5288d8214be
92ce7cb9d2eb426a88b850a512736cb0
5de67b97407f4603a822b751f789f82b--92ce7cb9d2eb426a88b850a512736cb0
787ef060eec44c04b98d7dd4d97b0ebf
3
bc1b08e73a514e89adf713981ffc8aaa
RX(theta₂)
92ce7cb9d2eb426a88b850a512736cb0--bc1b08e73a514e89adf713981ffc8aaa
2f321f1d562442cd9f4fad9005ce051c
RY(theta₆)
bc1b08e73a514e89adf713981ffc8aaa--2f321f1d562442cd9f4fad9005ce051c
5883404eb8d74bec83ffa976adf5aa87
RX(theta₁₀)
2f321f1d562442cd9f4fad9005ce051c--5883404eb8d74bec83ffa976adf5aa87
8437f6aa6be749a8856383653ed6532e
5883404eb8d74bec83ffa976adf5aa87--8437f6aa6be749a8856383653ed6532e
b75d3f0f55cc4be18288ad4b40d9623e
X
8437f6aa6be749a8856383653ed6532e--b75d3f0f55cc4be18288ad4b40d9623e
b75d3f0f55cc4be18288ad4b40d9623e--caa967d58c3745c5b302321008590f44
04b6006441dc42f9a6a0f78883fe86fb
RX(theta₁₄)
b75d3f0f55cc4be18288ad4b40d9623e--04b6006441dc42f9a6a0f78883fe86fb
67cb231913334836872d18d9df5daf76
RY(theta₁₈)
04b6006441dc42f9a6a0f78883fe86fb--67cb231913334836872d18d9df5daf76
014a19df83904660b3aad751fe825213
RX(theta₂₂)
67cb231913334836872d18d9df5daf76--014a19df83904660b3aad751fe825213
d42fb2d245ec43bc893d27f7e05f91cc
014a19df83904660b3aad751fe825213--d42fb2d245ec43bc893d27f7e05f91cc
04097396190c4ae8899769c74f155b5e
X
d42fb2d245ec43bc893d27f7e05f91cc--04097396190c4ae8899769c74f155b5e
04097396190c4ae8899769c74f155b5e--336a85c074884492af69d0688e86a559
04097396190c4ae8899769c74f155b5e--2a3a09842cd646d3a1dfb5288d8214be
395247cf30f14ac9b71a8d716a4c2e6e
dadabe79da9e4f06a3fce829af416f20
X
787ef060eec44c04b98d7dd4d97b0ebf--dadabe79da9e4f06a3fce829af416f20
1c31f00477d54edab29cd60c24604cb6
RX(theta₃)
dadabe79da9e4f06a3fce829af416f20--1c31f00477d54edab29cd60c24604cb6
83c212998ff247a181256f491eb0340c
RY(theta₇)
1c31f00477d54edab29cd60c24604cb6--83c212998ff247a181256f491eb0340c
43a463e712804e80b2670a4940f01ed6
RX(theta₁₁)
83c212998ff247a181256f491eb0340c--43a463e712804e80b2670a4940f01ed6
93f866e3e3b44f8aa99955920a6ec9c8
X
43a463e712804e80b2670a4940f01ed6--93f866e3e3b44f8aa99955920a6ec9c8
93f866e3e3b44f8aa99955920a6ec9c8--8437f6aa6be749a8856383653ed6532e
1dd57c74cfe8496cac3d366eee8fac90
93f866e3e3b44f8aa99955920a6ec9c8--1dd57c74cfe8496cac3d366eee8fac90
47f5066827e940948878dcb5dd60ef35
RX(theta₁₅)
1dd57c74cfe8496cac3d366eee8fac90--47f5066827e940948878dcb5dd60ef35
a383f5268b454ea4bc2c44e179a9c062
RY(theta₁₉)
47f5066827e940948878dcb5dd60ef35--a383f5268b454ea4bc2c44e179a9c062
97cb38251919435e9793c0ea1d312c02
RX(theta₂₃)
a383f5268b454ea4bc2c44e179a9c062--97cb38251919435e9793c0ea1d312c02
de7859ca8ad3461dbb85487f88021034
X
97cb38251919435e9793c0ea1d312c02--de7859ca8ad3461dbb85487f88021034
de7859ca8ad3461dbb85487f88021034--d42fb2d245ec43bc893d27f7e05f91cc
811b3edc53a7469999686ff8aff28c14
de7859ca8ad3461dbb85487f88021034--811b3edc53a7469999686ff8aff28c14
811b3edc53a7469999686ff8aff28c14--395247cf30f14ac9b71a8d716a4c2e6e
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( [[ 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 , 0.+0. j , 0.+0. j , 0.+0. j , 1.+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.4069-0.3345 j , 0.0557-0.0508 j , 0.1071-0.1038 j , -0.3884-0.1071 j ,
0.0203+0.4458 j , -0.1258-0.1760 j , 0.1835+0.1160 j , 0.1922-0.4498 j ],
[ -0.2344-0.2973 j , -0.0724+0.4345 j , -0.1511+0.1684 j , -0.2234-0.3202 j ,
0.2596+0.3974 j , 0.0339-0.4034 j , -0.1082+0.0345 j , 0.2104+0.1127 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 )
├── I( 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 ]] )