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.83300843+0.55326029 j 0. + 0. 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_d31ab7486d7b441cb77e00a88521fd53
Circuit block
cluster_01a6ecac350c4faf9346ebfd214221c8
Prep block
391c02ae9cd249b19ca5eeb158c5244c
0
e398909da8ef4c73834aac9686ba5c80
391c02ae9cd249b19ca5eeb158c5244c--e398909da8ef4c73834aac9686ba5c80
53496836ade943d4b9067363410fb8e3
1
1ef774169b714ab9bae09717c09d08e6
RX(theta₀)
e398909da8ef4c73834aac9686ba5c80--1ef774169b714ab9bae09717c09d08e6
99b3b356733e46f4ad7e47a2aee562cd
RY(theta₄)
1ef774169b714ab9bae09717c09d08e6--99b3b356733e46f4ad7e47a2aee562cd
4d85a87ce08c43c7bc85954adbc755e3
RX(theta₈)
99b3b356733e46f4ad7e47a2aee562cd--4d85a87ce08c43c7bc85954adbc755e3
5cb5b5050e224c1aa56650911ee172ee
4d85a87ce08c43c7bc85954adbc755e3--5cb5b5050e224c1aa56650911ee172ee
2d08747f234e45188e833ba6f1992490
5cb5b5050e224c1aa56650911ee172ee--2d08747f234e45188e833ba6f1992490
866d00ef365c46b197d4166f1b19fa7d
RX(theta₁₂)
2d08747f234e45188e833ba6f1992490--866d00ef365c46b197d4166f1b19fa7d
5e820a5a27d645a2893a85440e5148ac
RY(theta₁₆)
866d00ef365c46b197d4166f1b19fa7d--5e820a5a27d645a2893a85440e5148ac
28103abf492745aa82649c24fd34ae11
RX(theta₂₀)
5e820a5a27d645a2893a85440e5148ac--28103abf492745aa82649c24fd34ae11
f4e176f871b346fe8ba369408b6d0d47
28103abf492745aa82649c24fd34ae11--f4e176f871b346fe8ba369408b6d0d47
002021072c5a4cacbb57be78081f9b43
f4e176f871b346fe8ba369408b6d0d47--002021072c5a4cacbb57be78081f9b43
f047e4c9a7c24e63b582f14a27aba55b
002021072c5a4cacbb57be78081f9b43--f047e4c9a7c24e63b582f14a27aba55b
691521a825764976b6c3d6e241cef878
9a128514f6614107b8b0dd7ce43d9d86
53496836ade943d4b9067363410fb8e3--9a128514f6614107b8b0dd7ce43d9d86
3109adeace314fc4927b8211eaf7261f
2
1420710c7e2e419d9c2f820c52db7426
RX(theta₁)
9a128514f6614107b8b0dd7ce43d9d86--1420710c7e2e419d9c2f820c52db7426
a84c68d2df9e4a8ca60e58511059837f
RY(theta₅)
1420710c7e2e419d9c2f820c52db7426--a84c68d2df9e4a8ca60e58511059837f
083c74d743bf49e393266df3e3873f65
RX(theta₉)
a84c68d2df9e4a8ca60e58511059837f--083c74d743bf49e393266df3e3873f65
3efec2fc19f845028ee86fdb4fa5051b
X
083c74d743bf49e393266df3e3873f65--3efec2fc19f845028ee86fdb4fa5051b
3efec2fc19f845028ee86fdb4fa5051b--5cb5b5050e224c1aa56650911ee172ee
efc4a11ae0654b51a7d9e51017549433
3efec2fc19f845028ee86fdb4fa5051b--efc4a11ae0654b51a7d9e51017549433
182db63b2f404b8bb2b6cfe955748ab0
RX(theta₁₃)
efc4a11ae0654b51a7d9e51017549433--182db63b2f404b8bb2b6cfe955748ab0
8d2e05a8db3b45e9a9c65a465a7949bb
RY(theta₁₇)
182db63b2f404b8bb2b6cfe955748ab0--8d2e05a8db3b45e9a9c65a465a7949bb
82cf6e6e156248c69ff8579bc8c9ce9c
RX(theta₂₁)
8d2e05a8db3b45e9a9c65a465a7949bb--82cf6e6e156248c69ff8579bc8c9ce9c
08ecbb2db27b43039756e26eaa259722
X
82cf6e6e156248c69ff8579bc8c9ce9c--08ecbb2db27b43039756e26eaa259722
08ecbb2db27b43039756e26eaa259722--f4e176f871b346fe8ba369408b6d0d47
68edca74172a4b36aa6e9bd15c90f9fd
08ecbb2db27b43039756e26eaa259722--68edca74172a4b36aa6e9bd15c90f9fd
68edca74172a4b36aa6e9bd15c90f9fd--691521a825764976b6c3d6e241cef878
19e964cfe6354f7d8559bbb8ca04e7f9
39521d370d044c999e47bce930f9df67
3109adeace314fc4927b8211eaf7261f--39521d370d044c999e47bce930f9df67
3b6f529525fd45a0b3187358319a4763
3
cf29b67a2e094ee49f1c43f3aa7d62e1
RX(theta₂)
39521d370d044c999e47bce930f9df67--cf29b67a2e094ee49f1c43f3aa7d62e1
428b060f62af40c2af25a5d8fa98bca9
RY(theta₆)
cf29b67a2e094ee49f1c43f3aa7d62e1--428b060f62af40c2af25a5d8fa98bca9
fca06176b40244c08780a9adde5739c1
RX(theta₁₀)
428b060f62af40c2af25a5d8fa98bca9--fca06176b40244c08780a9adde5739c1
48f8a9f3b5af48a1be82925e2b157950
fca06176b40244c08780a9adde5739c1--48f8a9f3b5af48a1be82925e2b157950
ce7648c1dcc446b9ba89f148435e1cfb
X
48f8a9f3b5af48a1be82925e2b157950--ce7648c1dcc446b9ba89f148435e1cfb
ce7648c1dcc446b9ba89f148435e1cfb--efc4a11ae0654b51a7d9e51017549433
8c2400260e52444684bdd48f21f0c7cd
RX(theta₁₄)
ce7648c1dcc446b9ba89f148435e1cfb--8c2400260e52444684bdd48f21f0c7cd
716d566aa50d4fada9794bc062863dd3
RY(theta₁₈)
8c2400260e52444684bdd48f21f0c7cd--716d566aa50d4fada9794bc062863dd3
30488e25e2a14181a54f6b83d2fb9d2c
RX(theta₂₂)
716d566aa50d4fada9794bc062863dd3--30488e25e2a14181a54f6b83d2fb9d2c
a79f36beef3447faa98a85260012c8eb
30488e25e2a14181a54f6b83d2fb9d2c--a79f36beef3447faa98a85260012c8eb
6835c40f82ef4d5b86e5f23f1146bed8
X
a79f36beef3447faa98a85260012c8eb--6835c40f82ef4d5b86e5f23f1146bed8
6835c40f82ef4d5b86e5f23f1146bed8--68edca74172a4b36aa6e9bd15c90f9fd
6835c40f82ef4d5b86e5f23f1146bed8--19e964cfe6354f7d8559bbb8ca04e7f9
fa3314338a0f44bea2c8019b1d713e54
1c4afdfbd2294818b4d42cce26e0635c
X
3b6f529525fd45a0b3187358319a4763--1c4afdfbd2294818b4d42cce26e0635c
3af788b200e1460695e8dc38512cfe85
RX(theta₃)
1c4afdfbd2294818b4d42cce26e0635c--3af788b200e1460695e8dc38512cfe85
8356d2b57c79485795466718fdd8d0e3
RY(theta₇)
3af788b200e1460695e8dc38512cfe85--8356d2b57c79485795466718fdd8d0e3
566e4512d3a5498f8dd61c9f18f9a186
RX(theta₁₁)
8356d2b57c79485795466718fdd8d0e3--566e4512d3a5498f8dd61c9f18f9a186
265299cd986b476cb75d16f83776071c
X
566e4512d3a5498f8dd61c9f18f9a186--265299cd986b476cb75d16f83776071c
265299cd986b476cb75d16f83776071c--48f8a9f3b5af48a1be82925e2b157950
604bc14d686c4bacb26c37a08655c4f0
265299cd986b476cb75d16f83776071c--604bc14d686c4bacb26c37a08655c4f0
451301126b3a48e5b304bb08cf23b349
RX(theta₁₅)
604bc14d686c4bacb26c37a08655c4f0--451301126b3a48e5b304bb08cf23b349
8649c3669d134a8984022a85596a4057
RY(theta₁₉)
451301126b3a48e5b304bb08cf23b349--8649c3669d134a8984022a85596a4057
c5f479ee4fe44bf8a3f512256ebadf2b
RX(theta₂₃)
8649c3669d134a8984022a85596a4057--c5f479ee4fe44bf8a3f512256ebadf2b
b9b0486ab589441ba85312a0f5a6ca68
X
c5f479ee4fe44bf8a3f512256ebadf2b--b9b0486ab589441ba85312a0f5a6ca68
b9b0486ab589441ba85312a0f5a6ca68--a79f36beef3447faa98a85260012c8eb
3ee92655224e4619aa665c16980822cf
b9b0486ab589441ba85312a0f5a6ca68--3ee92655224e4619aa665c16980822cf
3ee92655224e4619aa665c16980822cf--fa3314338a0f44bea2c8019b1d713e54
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 , 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.4778-0.3032 j , -0.2188+0.0063 j , -0.5854+0.1054 j , -0.0209+0.1171 j ,
-0.1233+0.1146 j , 0.2949-0.1529 j , 0.2178+0.2514 j , 0.0053+0.1206 j ],
[ 0.0060+0.1147 j , 0.1033+0.1432 j , -0.2309+0.3088 j , -0.2681+0.2402 j ,
-0.2283-0.2065 j , -0.4066+0.1532 j , -0.5098-0.1379 j , 0.2512-0.2275 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 )
├── I( 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 ]] )