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.56230754+0. j -0.06783009+0. j 0.81821011+0. j -0.09869913+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 )
cluster_e879252ef2c8498eaeddcec621b7ed57
Circuit block
cluster_f27612b5626d473f8d8a34d3cb0d5589
Prep block
0f6ca2a940a647809008a9dc3fcdcfa1
0
fce42e0c13074984832123bf65f5f4eb
0f6ca2a940a647809008a9dc3fcdcfa1--fce42e0c13074984832123bf65f5f4eb
1724ebecbc7742629d08bd15bc93de46
1
5d980613b9094b8fba978a54adcbf425
RX(theta₀)
fce42e0c13074984832123bf65f5f4eb--5d980613b9094b8fba978a54adcbf425
b35ad5f435ef439eb8135caa8edc10a3
RY(theta₄)
5d980613b9094b8fba978a54adcbf425--b35ad5f435ef439eb8135caa8edc10a3
38c08e53cb2c4cc3bc9ab883baf098dc
RX(theta₈)
b35ad5f435ef439eb8135caa8edc10a3--38c08e53cb2c4cc3bc9ab883baf098dc
19a2964ca754456eb625a0edf622a7c8
38c08e53cb2c4cc3bc9ab883baf098dc--19a2964ca754456eb625a0edf622a7c8
acd958717ffb44d89e31f4cce68f1cc1
19a2964ca754456eb625a0edf622a7c8--acd958717ffb44d89e31f4cce68f1cc1
b4052cff16b54e0b8a3332902203abb9
RX(theta₁₂)
acd958717ffb44d89e31f4cce68f1cc1--b4052cff16b54e0b8a3332902203abb9
f4f9f4a8d68f474cb4fe0288a3b5be0c
RY(theta₁₆)
b4052cff16b54e0b8a3332902203abb9--f4f9f4a8d68f474cb4fe0288a3b5be0c
f2827e67a5564b39ad83a567619e6c64
RX(theta₂₀)
f4f9f4a8d68f474cb4fe0288a3b5be0c--f2827e67a5564b39ad83a567619e6c64
586ae13cce8947b0904f210c34c0e9a9
f2827e67a5564b39ad83a567619e6c64--586ae13cce8947b0904f210c34c0e9a9
c0990c02054c48c9b668b5c9f54f2076
586ae13cce8947b0904f210c34c0e9a9--c0990c02054c48c9b668b5c9f54f2076
069bc5d3ddc84b4fab6bddda90dcb114
c0990c02054c48c9b668b5c9f54f2076--069bc5d3ddc84b4fab6bddda90dcb114
465c7505c09a49c9891de8848fd77453
1d8f4009c38c443dab1a2a1ffa8fc34e
1724ebecbc7742629d08bd15bc93de46--1d8f4009c38c443dab1a2a1ffa8fc34e
45b4c5f2f60a4f3aa9c6b6cb76638357
2
2e26fa41513f47cd9ea9c189932baea8
RX(theta₁)
1d8f4009c38c443dab1a2a1ffa8fc34e--2e26fa41513f47cd9ea9c189932baea8
abe3353262c04bc38ba37e592864191d
RY(theta₅)
2e26fa41513f47cd9ea9c189932baea8--abe3353262c04bc38ba37e592864191d
165c0c7416424bb69e5f7eb654f2e4d1
RX(theta₉)
abe3353262c04bc38ba37e592864191d--165c0c7416424bb69e5f7eb654f2e4d1
8f90d4cd99d0439ab5566e089247844d
X
165c0c7416424bb69e5f7eb654f2e4d1--8f90d4cd99d0439ab5566e089247844d
8f90d4cd99d0439ab5566e089247844d--19a2964ca754456eb625a0edf622a7c8
b26a031824b24ff5bf7595a8c58b656c
8f90d4cd99d0439ab5566e089247844d--b26a031824b24ff5bf7595a8c58b656c
7c149a1b4de94ae79d69515fd214fba3
RX(theta₁₃)
b26a031824b24ff5bf7595a8c58b656c--7c149a1b4de94ae79d69515fd214fba3
2258549b1a684fd78d252ee6984ebb0f
RY(theta₁₇)
7c149a1b4de94ae79d69515fd214fba3--2258549b1a684fd78d252ee6984ebb0f
0d0f2777bb5541f48a776cbf81be9c70
RX(theta₂₁)
2258549b1a684fd78d252ee6984ebb0f--0d0f2777bb5541f48a776cbf81be9c70
58a1dea87c2b45c6bbad71dc3bc0924e
X
0d0f2777bb5541f48a776cbf81be9c70--58a1dea87c2b45c6bbad71dc3bc0924e
58a1dea87c2b45c6bbad71dc3bc0924e--586ae13cce8947b0904f210c34c0e9a9
30e84fef62104603b95b59f7db423e5f
58a1dea87c2b45c6bbad71dc3bc0924e--30e84fef62104603b95b59f7db423e5f
30e84fef62104603b95b59f7db423e5f--465c7505c09a49c9891de8848fd77453
42f2b62e7e704d0292d1f20114c8713b
e302b9db5e7e4ea8a7135cedcd38e3d1
45b4c5f2f60a4f3aa9c6b6cb76638357--e302b9db5e7e4ea8a7135cedcd38e3d1
e3094f04a71c466dbdf22e9c41ea076f
3
5b8abb3091354e32be348d00fd44336b
RX(theta₂)
e302b9db5e7e4ea8a7135cedcd38e3d1--5b8abb3091354e32be348d00fd44336b
d21e1f6ae13f41fd87d2a1162e574edb
RY(theta₆)
5b8abb3091354e32be348d00fd44336b--d21e1f6ae13f41fd87d2a1162e574edb
769db2c48e83418b97d703fadfb3df68
RX(theta₁₀)
d21e1f6ae13f41fd87d2a1162e574edb--769db2c48e83418b97d703fadfb3df68
84a1b9ca835943f785a039bfa71ae5ae
769db2c48e83418b97d703fadfb3df68--84a1b9ca835943f785a039bfa71ae5ae
895535506ba143be8b8b39bd1f7532d4
X
84a1b9ca835943f785a039bfa71ae5ae--895535506ba143be8b8b39bd1f7532d4
895535506ba143be8b8b39bd1f7532d4--b26a031824b24ff5bf7595a8c58b656c
3414e208d7b94bcba27734a294259bb2
RX(theta₁₄)
895535506ba143be8b8b39bd1f7532d4--3414e208d7b94bcba27734a294259bb2
33ebe6dc4093493cbfdd06dcaff65f82
RY(theta₁₈)
3414e208d7b94bcba27734a294259bb2--33ebe6dc4093493cbfdd06dcaff65f82
981a2e5fe2394d19b71e6c7342dcd712
RX(theta₂₂)
33ebe6dc4093493cbfdd06dcaff65f82--981a2e5fe2394d19b71e6c7342dcd712
8e49b9af9159401bbb8e7a251b6ced00
981a2e5fe2394d19b71e6c7342dcd712--8e49b9af9159401bbb8e7a251b6ced00
e4ab9425859b4207a115a30161b544b6
X
8e49b9af9159401bbb8e7a251b6ced00--e4ab9425859b4207a115a30161b544b6
e4ab9425859b4207a115a30161b544b6--30e84fef62104603b95b59f7db423e5f
e4ab9425859b4207a115a30161b544b6--42f2b62e7e704d0292d1f20114c8713b
9edb0ee9b91645d29b55c0203b42a9d1
6e6be4729f8548fe986bfa9338d94597
X
e3094f04a71c466dbdf22e9c41ea076f--6e6be4729f8548fe986bfa9338d94597
77afa7ae4b1b4f37b79eff779791275a
RX(theta₃)
6e6be4729f8548fe986bfa9338d94597--77afa7ae4b1b4f37b79eff779791275a
f11a6fe2ecae4692ab9a1c22665874a8
RY(theta₇)
77afa7ae4b1b4f37b79eff779791275a--f11a6fe2ecae4692ab9a1c22665874a8
f08f7a5c7570435288b165857e362051
RX(theta₁₁)
f11a6fe2ecae4692ab9a1c22665874a8--f08f7a5c7570435288b165857e362051
171d38941b544b9a9a79de51de2d7ac0
X
f08f7a5c7570435288b165857e362051--171d38941b544b9a9a79de51de2d7ac0
171d38941b544b9a9a79de51de2d7ac0--84a1b9ca835943f785a039bfa71ae5ae
5ef96144384b4323910b742910c2c629
171d38941b544b9a9a79de51de2d7ac0--5ef96144384b4323910b742910c2c629
b0d68868e17842309fcc9608d17e7631
RX(theta₁₅)
5ef96144384b4323910b742910c2c629--b0d68868e17842309fcc9608d17e7631
e717191dd8c241859aeb76d74f585114
RY(theta₁₉)
b0d68868e17842309fcc9608d17e7631--e717191dd8c241859aeb76d74f585114
b11bb0fe6e6b4522ba29b96dd3e7c8d4
RX(theta₂₃)
e717191dd8c241859aeb76d74f585114--b11bb0fe6e6b4522ba29b96dd3e7c8d4
e33670f5657c4e5db8a7a0571003962f
X
b11bb0fe6e6b4522ba29b96dd3e7c8d4--e33670f5657c4e5db8a7a0571003962f
e33670f5657c4e5db8a7a0571003962f--8e49b9af9159401bbb8e7a251b6ced00
79ce0a8b4e6b4e659b37d6053e5539a0
e33670f5657c4e5db8a7a0571003962f--79ce0a8b4e6b4e659b37d6053e5539a0
79ce0a8b4e6b4e659b37d6053e5539a0--9edb0ee9b91645d29b55c0203b42a9d1
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 ],
[ 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 , 1.+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.4733+0.0588 j , -0.3286+0.0288 j , -0.0680+0.3754 j , -0.3299-0.1679 j ,
0.0818+0.2296 j , -0.2771-0.2593 j , -0.0508+0.0349 j , 0.1995-0.3662 j ],
[ -0.2293+0.0824 j , -0.0980-0.0311 j , -0.0049-0.1667 j , 0.5866+0.3335 j ,
0.1787+0.1656 j , 0.0792-0.1512 j , -0.5753+0.0789 j , 0.1434-0.0244 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 ]] )