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.64514427+0.70981379 j -0.20924619+0.19018224 j 0. + 0. 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_0262a26380cc46c7880bebdab792ce43
Circuit block
cluster_5c988ce19451420f8038cd76a7c864ad
Prep block
965fc9546493403abf342ec68590f433
0
cef9bbfc48034a679167c333a1d1f161
965fc9546493403abf342ec68590f433--cef9bbfc48034a679167c333a1d1f161
9c76f2db3e9447dbaeb3de04a309b5b3
1
f3d07d66d1444b07ae5e7e46389f8173
RX(theta₀)
cef9bbfc48034a679167c333a1d1f161--f3d07d66d1444b07ae5e7e46389f8173
cd28b27898304d6ea4ef872f8479a383
RY(theta₄)
f3d07d66d1444b07ae5e7e46389f8173--cd28b27898304d6ea4ef872f8479a383
1b001af3cc0e4d49ae9f72699211ea5c
RX(theta₈)
cd28b27898304d6ea4ef872f8479a383--1b001af3cc0e4d49ae9f72699211ea5c
f581baac90b04740b939aec6086d7242
1b001af3cc0e4d49ae9f72699211ea5c--f581baac90b04740b939aec6086d7242
6323847584ba484f9ae4296c33a76936
f581baac90b04740b939aec6086d7242--6323847584ba484f9ae4296c33a76936
a233eb9bfda64b1f9f6243367c6de050
RX(theta₁₂)
6323847584ba484f9ae4296c33a76936--a233eb9bfda64b1f9f6243367c6de050
85e58d1a218144d090dcc9142c87bcb3
RY(theta₁₆)
a233eb9bfda64b1f9f6243367c6de050--85e58d1a218144d090dcc9142c87bcb3
f8c4d3fd31fc48e5bb55b0da5bc5dbb1
RX(theta₂₀)
85e58d1a218144d090dcc9142c87bcb3--f8c4d3fd31fc48e5bb55b0da5bc5dbb1
694ab9cfdd0d4d758c9336dd10bc4cdb
f8c4d3fd31fc48e5bb55b0da5bc5dbb1--694ab9cfdd0d4d758c9336dd10bc4cdb
a54ba4ccd86d46bc84ff15099863d4da
694ab9cfdd0d4d758c9336dd10bc4cdb--a54ba4ccd86d46bc84ff15099863d4da
2fd3ae3eca454a2cb26db04c88e36879
a54ba4ccd86d46bc84ff15099863d4da--2fd3ae3eca454a2cb26db04c88e36879
7f168154be8e4ae2bb5c070991b1cd0c
6979535ad6ee4cb8b42605e41c71608e
9c76f2db3e9447dbaeb3de04a309b5b3--6979535ad6ee4cb8b42605e41c71608e
291b95f5553044448d482e01b2338b31
2
349c262069bd4bbe9fe4526b278aba33
RX(theta₁)
6979535ad6ee4cb8b42605e41c71608e--349c262069bd4bbe9fe4526b278aba33
963e3763093c4d3093c6ea90e4365c1b
RY(theta₅)
349c262069bd4bbe9fe4526b278aba33--963e3763093c4d3093c6ea90e4365c1b
30618c9d8e65456d818047388974207e
RX(theta₉)
963e3763093c4d3093c6ea90e4365c1b--30618c9d8e65456d818047388974207e
6b25ba3c4b574124b8ae4777b035eabf
X
30618c9d8e65456d818047388974207e--6b25ba3c4b574124b8ae4777b035eabf
6b25ba3c4b574124b8ae4777b035eabf--f581baac90b04740b939aec6086d7242
589f4adfb7ec4672a67156742943bae3
6b25ba3c4b574124b8ae4777b035eabf--589f4adfb7ec4672a67156742943bae3
991ef98bd2064cb3b35881aa200898a8
RX(theta₁₃)
589f4adfb7ec4672a67156742943bae3--991ef98bd2064cb3b35881aa200898a8
76e4767a24a6426bb1c1e971d4805a22
RY(theta₁₇)
991ef98bd2064cb3b35881aa200898a8--76e4767a24a6426bb1c1e971d4805a22
92d592c0d61442638840cb4d27c21281
RX(theta₂₁)
76e4767a24a6426bb1c1e971d4805a22--92d592c0d61442638840cb4d27c21281
523b2bc1b3c741e387ce56ce537cac7d
X
92d592c0d61442638840cb4d27c21281--523b2bc1b3c741e387ce56ce537cac7d
523b2bc1b3c741e387ce56ce537cac7d--694ab9cfdd0d4d758c9336dd10bc4cdb
d5181bf61ea7495da4f121b387826005
523b2bc1b3c741e387ce56ce537cac7d--d5181bf61ea7495da4f121b387826005
d5181bf61ea7495da4f121b387826005--7f168154be8e4ae2bb5c070991b1cd0c
51f2b5fb4d6542048817f023fe2eab14
db5daf24071a455f982ede19e1d9f30c
291b95f5553044448d482e01b2338b31--db5daf24071a455f982ede19e1d9f30c
e6fed0f4ea4548d4b0f519ad736e70a0
3
08eac6f9372643adafd8f4b975cc9244
RX(theta₂)
db5daf24071a455f982ede19e1d9f30c--08eac6f9372643adafd8f4b975cc9244
78929fb76ffb4fd89a1b0aca542f5f41
RY(theta₆)
08eac6f9372643adafd8f4b975cc9244--78929fb76ffb4fd89a1b0aca542f5f41
c7983985089d4ade8329e623499a9356
RX(theta₁₀)
78929fb76ffb4fd89a1b0aca542f5f41--c7983985089d4ade8329e623499a9356
1362c90afc0b472c9ac6c1fbcaff8bec
c7983985089d4ade8329e623499a9356--1362c90afc0b472c9ac6c1fbcaff8bec
cd3d0659dbd348e6a1f2b4a78a3b0b7d
X
1362c90afc0b472c9ac6c1fbcaff8bec--cd3d0659dbd348e6a1f2b4a78a3b0b7d
cd3d0659dbd348e6a1f2b4a78a3b0b7d--589f4adfb7ec4672a67156742943bae3
4f503255da42420aa0f1ca7f85cd51e7
RX(theta₁₄)
cd3d0659dbd348e6a1f2b4a78a3b0b7d--4f503255da42420aa0f1ca7f85cd51e7
709d03c26fab41ceb95aaf09fd5b3b65
RY(theta₁₈)
4f503255da42420aa0f1ca7f85cd51e7--709d03c26fab41ceb95aaf09fd5b3b65
1fd462da7b6f4507a8111de5d7f63788
RX(theta₂₂)
709d03c26fab41ceb95aaf09fd5b3b65--1fd462da7b6f4507a8111de5d7f63788
dc3b73bb4bec4cae9fca15c22a63cf91
1fd462da7b6f4507a8111de5d7f63788--dc3b73bb4bec4cae9fca15c22a63cf91
c4dd7e67620e48569c62ab9768c7aede
X
dc3b73bb4bec4cae9fca15c22a63cf91--c4dd7e67620e48569c62ab9768c7aede
c4dd7e67620e48569c62ab9768c7aede--d5181bf61ea7495da4f121b387826005
c4dd7e67620e48569c62ab9768c7aede--51f2b5fb4d6542048817f023fe2eab14
21210245c9b64d458db5d3aced626ffc
b72e49b981964701ad8c0bec2cf8c6be
X
e6fed0f4ea4548d4b0f519ad736e70a0--b72e49b981964701ad8c0bec2cf8c6be
665bb1420f694a9b9a6465aa30c7e184
RX(theta₃)
b72e49b981964701ad8c0bec2cf8c6be--665bb1420f694a9b9a6465aa30c7e184
a68238faf1b74db8855836abde648d3c
RY(theta₇)
665bb1420f694a9b9a6465aa30c7e184--a68238faf1b74db8855836abde648d3c
d4dd419afc3e464e97929ac09c33a3f7
RX(theta₁₁)
a68238faf1b74db8855836abde648d3c--d4dd419afc3e464e97929ac09c33a3f7
fc44057c79f94fdeaa4dd09e33e832d0
X
d4dd419afc3e464e97929ac09c33a3f7--fc44057c79f94fdeaa4dd09e33e832d0
fc44057c79f94fdeaa4dd09e33e832d0--1362c90afc0b472c9ac6c1fbcaff8bec
ebe54aee18ec4c60b0f4bb4a0d29d09f
fc44057c79f94fdeaa4dd09e33e832d0--ebe54aee18ec4c60b0f4bb4a0d29d09f
1f8b7d11d4df4aa393172427096cc4cb
RX(theta₁₅)
ebe54aee18ec4c60b0f4bb4a0d29d09f--1f8b7d11d4df4aa393172427096cc4cb
10acec576c534aa19fa9b48faf2f6c1c
RY(theta₁₉)
1f8b7d11d4df4aa393172427096cc4cb--10acec576c534aa19fa9b48faf2f6c1c
efd9cf6b31da4135830cb56064c29644
RX(theta₂₃)
10acec576c534aa19fa9b48faf2f6c1c--efd9cf6b31da4135830cb56064c29644
fadd39cee5c74f90aa200a2181a7cf15
X
efd9cf6b31da4135830cb56064c29644--fadd39cee5c74f90aa200a2181a7cf15
fadd39cee5c74f90aa200a2181a7cf15--dc3b73bb4bec4cae9fca15c22a63cf91
c242c73acfe647f8a63908e0737c26d9
fadd39cee5c74f90aa200a2181a7cf15--c242c73acfe647f8a63908e0737c26d9
c242c73acfe647f8a63908e0737c26d9--21210245c9b64d458db5d3aced626ffc
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 , 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 , 0.+0. j , 0.+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.2045-0.2269 j , 0.1438+0.5498 j , -0.2988-0.1390 j , 0.4756-0.2455 j ,
-0.1202-0.2038 j , 0.0159-0.2576 j , 0.1665+0.0168 j , -0.1088+0.1620 j ],
[ -0.2920-0.0203 j , 0.0644+0.0055 j , -0.1784-0.1456 j , -0.3402+0.0117 j ,
0.3525+0.4059 j , -0.4295-0.0742 j , 0.0256-0.3383 j , -0.3828-0.0263 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 )
└── X( 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 ]] )