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.89749838+0. j 0. -0.13125579 j 0. -0.4166012 j
-0.06092637+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_e2803fae6898455d9cd1ae005f4b48fc
Circuit block
cluster_964b7db6102645d8af879e04c87b0fc9
Prep block
a04a36afe12c4a4ba24593fee087d09b
0
f248ca72dd9546fbba936c968cac486d
a04a36afe12c4a4ba24593fee087d09b--f248ca72dd9546fbba936c968cac486d
c35622bbf737427f8cec94b4dd88a82b
1
75e6ddb0d7b7446d911f4911cce611e7
RX(theta₀)
f248ca72dd9546fbba936c968cac486d--75e6ddb0d7b7446d911f4911cce611e7
aab525261d364c8b8f6d1877e6440307
RY(theta₄)
75e6ddb0d7b7446d911f4911cce611e7--aab525261d364c8b8f6d1877e6440307
bf99ed9a58384af8ba1ca3f8d1bdbf97
RX(theta₈)
aab525261d364c8b8f6d1877e6440307--bf99ed9a58384af8ba1ca3f8d1bdbf97
8f654ff6792541e8b2370801224633e4
bf99ed9a58384af8ba1ca3f8d1bdbf97--8f654ff6792541e8b2370801224633e4
ffe5a9b02eca4fb394612a98e58cdb0a
8f654ff6792541e8b2370801224633e4--ffe5a9b02eca4fb394612a98e58cdb0a
f4e13f7dbdd7418eb181d010bf989346
RX(theta₁₂)
ffe5a9b02eca4fb394612a98e58cdb0a--f4e13f7dbdd7418eb181d010bf989346
37881bcc6de54448849d5e6e4b9ec4f1
RY(theta₁₆)
f4e13f7dbdd7418eb181d010bf989346--37881bcc6de54448849d5e6e4b9ec4f1
b6fba4394e59473b8c51351b2906cb60
RX(theta₂₀)
37881bcc6de54448849d5e6e4b9ec4f1--b6fba4394e59473b8c51351b2906cb60
1bbad0dd201341a08cdcfebb5e594d88
b6fba4394e59473b8c51351b2906cb60--1bbad0dd201341a08cdcfebb5e594d88
bf7585315368476981c8113b454fa531
1bbad0dd201341a08cdcfebb5e594d88--bf7585315368476981c8113b454fa531
6f597ba0776646c29b4806f42c5544f6
bf7585315368476981c8113b454fa531--6f597ba0776646c29b4806f42c5544f6
a00dab95ad104552991c8c1cb9c46b96
6194579f32a14c9f9df30b172543f5fa
c35622bbf737427f8cec94b4dd88a82b--6194579f32a14c9f9df30b172543f5fa
279edcdb1e8241ffab6a47df370437a3
2
e8eec732b8754e4b9878d180a5d23fa3
RX(theta₁)
6194579f32a14c9f9df30b172543f5fa--e8eec732b8754e4b9878d180a5d23fa3
80955f3c7b0945ecbbcff5ad9b5a4044
RY(theta₅)
e8eec732b8754e4b9878d180a5d23fa3--80955f3c7b0945ecbbcff5ad9b5a4044
b82c4ba608f545b482813cd0601af985
RX(theta₉)
80955f3c7b0945ecbbcff5ad9b5a4044--b82c4ba608f545b482813cd0601af985
1815421e7c7641328024903cac061150
X
b82c4ba608f545b482813cd0601af985--1815421e7c7641328024903cac061150
1815421e7c7641328024903cac061150--8f654ff6792541e8b2370801224633e4
362ac87efca244469a8fe85ad220689b
1815421e7c7641328024903cac061150--362ac87efca244469a8fe85ad220689b
a73706b89d08476fb96dd909bb371fa3
RX(theta₁₃)
362ac87efca244469a8fe85ad220689b--a73706b89d08476fb96dd909bb371fa3
6feda130ebf54fa28b2eca7f562a9af4
RY(theta₁₇)
a73706b89d08476fb96dd909bb371fa3--6feda130ebf54fa28b2eca7f562a9af4
acef2f7dfd2547398fddfa555460738f
RX(theta₂₁)
6feda130ebf54fa28b2eca7f562a9af4--acef2f7dfd2547398fddfa555460738f
fbca7055b3824b4e8dda029d060b9787
X
acef2f7dfd2547398fddfa555460738f--fbca7055b3824b4e8dda029d060b9787
fbca7055b3824b4e8dda029d060b9787--1bbad0dd201341a08cdcfebb5e594d88
2838ee50ec524f75babd4217fd280710
fbca7055b3824b4e8dda029d060b9787--2838ee50ec524f75babd4217fd280710
2838ee50ec524f75babd4217fd280710--a00dab95ad104552991c8c1cb9c46b96
c8440ae402c54665a97220ee72660b6e
4ba6e41d28144de3bede8a779a9241d0
279edcdb1e8241ffab6a47df370437a3--4ba6e41d28144de3bede8a779a9241d0
2d48cc40b69f40968993f0e1403e905c
3
5c58f3473fe542e3a2377fe871e61f00
RX(theta₂)
4ba6e41d28144de3bede8a779a9241d0--5c58f3473fe542e3a2377fe871e61f00
6dcfcc4f59ce42069bc828e328c4f224
RY(theta₆)
5c58f3473fe542e3a2377fe871e61f00--6dcfcc4f59ce42069bc828e328c4f224
339c97d134244db7ab3a022fbfada8ec
RX(theta₁₀)
6dcfcc4f59ce42069bc828e328c4f224--339c97d134244db7ab3a022fbfada8ec
0b551fb04a8a4d398762b59036f01f2e
339c97d134244db7ab3a022fbfada8ec--0b551fb04a8a4d398762b59036f01f2e
8d5dd138a1b44e47b6f1351b9300ec09
X
0b551fb04a8a4d398762b59036f01f2e--8d5dd138a1b44e47b6f1351b9300ec09
8d5dd138a1b44e47b6f1351b9300ec09--362ac87efca244469a8fe85ad220689b
a94f932a8e3c458fb3f1130588881afa
RX(theta₁₄)
8d5dd138a1b44e47b6f1351b9300ec09--a94f932a8e3c458fb3f1130588881afa
9829cc4d112c4f549fdcf7dfa63c8b29
RY(theta₁₈)
a94f932a8e3c458fb3f1130588881afa--9829cc4d112c4f549fdcf7dfa63c8b29
dc77ca294bd64a3baa87377ab4d16868
RX(theta₂₂)
9829cc4d112c4f549fdcf7dfa63c8b29--dc77ca294bd64a3baa87377ab4d16868
6ab7b750f8f64123b406710de53312f9
dc77ca294bd64a3baa87377ab4d16868--6ab7b750f8f64123b406710de53312f9
67bb26e979eb473ea5917a2d5ac03738
X
6ab7b750f8f64123b406710de53312f9--67bb26e979eb473ea5917a2d5ac03738
67bb26e979eb473ea5917a2d5ac03738--2838ee50ec524f75babd4217fd280710
67bb26e979eb473ea5917a2d5ac03738--c8440ae402c54665a97220ee72660b6e
64775ad8d61842fe87a0c85082a373c2
6c0cc88bc6834b578fddf8cf573a03e9
X
2d48cc40b69f40968993f0e1403e905c--6c0cc88bc6834b578fddf8cf573a03e9
117bff62d3ff4c75b45e19c867f5e3af
RX(theta₃)
6c0cc88bc6834b578fddf8cf573a03e9--117bff62d3ff4c75b45e19c867f5e3af
1c774a5413fe499a8b5eb02b2a7881c6
RY(theta₇)
117bff62d3ff4c75b45e19c867f5e3af--1c774a5413fe499a8b5eb02b2a7881c6
c378b8c4e4744ac89c8c368ff419235f
RX(theta₁₁)
1c774a5413fe499a8b5eb02b2a7881c6--c378b8c4e4744ac89c8c368ff419235f
939126a168cc4504b055911983d34b89
X
c378b8c4e4744ac89c8c368ff419235f--939126a168cc4504b055911983d34b89
939126a168cc4504b055911983d34b89--0b551fb04a8a4d398762b59036f01f2e
7724d4318f6a42a9ba65a45a2db005bd
939126a168cc4504b055911983d34b89--7724d4318f6a42a9ba65a45a2db005bd
0acd742827a6418498fcdd51ef273aec
RX(theta₁₅)
7724d4318f6a42a9ba65a45a2db005bd--0acd742827a6418498fcdd51ef273aec
73fae0447b854d41b9b0ea501813e88e
RY(theta₁₉)
0acd742827a6418498fcdd51ef273aec--73fae0447b854d41b9b0ea501813e88e
e66fc9b85fb4486b85070202b803db54
RX(theta₂₃)
73fae0447b854d41b9b0ea501813e88e--e66fc9b85fb4486b85070202b803db54
2c059cddc32e4fdbb836acc7d3b4e79d
X
e66fc9b85fb4486b85070202b803db54--2c059cddc32e4fdbb836acc7d3b4e79d
2c059cddc32e4fdbb836acc7d3b4e79d--6ab7b750f8f64123b406710de53312f9
e8d447887d314b4e9bdd8bea85ee3338
2c059cddc32e4fdbb836acc7d3b4e79d--e8d447887d314b4e9bdd8bea85ee3338
e8d447887d314b4e9bdd8bea85ee3338--64775ad8d61842fe87a0c85082a373c2
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 ],
[ 1.+0. j , 0.+0. j , 0.+0. j , 0.+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.3917+0.3284 j , 0.2472-0.2105 j , 0.0093-0.0121 j , 0.0861+0.2614 j ,
-0.3026+0.4079 j , -0.0945+0.2842 j , 0.1811+0.1354 j , -0.3108-0.2488 j ],
[ -0.0030+0.1188 j , 0.6237+0.3131 j , -0.0163-0.1548 j , 0.2488+0.0077 j ,
0.1992-0.0109 j , 0.2398+0.3233 j , -0.0816-0.1897 j , 0.3764-0.1628 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 )
├── I( 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 ]] )