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.4016671 + 0.43579074 j -0.54587946-0.59225467 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_44e977e45fc6438095b664519e147114
Circuit block
cluster_b90705f052af4126b68ca8df20d51860
Prep block
2bed3659cd7e425db6a74b059382b854
0
a80d21161cf44d7ba73467f91060fcc4
2bed3659cd7e425db6a74b059382b854--a80d21161cf44d7ba73467f91060fcc4
d5b75880cd8e4efabb515259652027de
1
76773ee0118645b6885a0fc08f10ecbb
RX(theta₀)
a80d21161cf44d7ba73467f91060fcc4--76773ee0118645b6885a0fc08f10ecbb
0cad3aadaf174d669222ada694b3bd26
RY(theta₄)
76773ee0118645b6885a0fc08f10ecbb--0cad3aadaf174d669222ada694b3bd26
172f4da7b77345d982edc99fc11b8669
RX(theta₈)
0cad3aadaf174d669222ada694b3bd26--172f4da7b77345d982edc99fc11b8669
eb924200a201486ca97655cc3cc63f0e
172f4da7b77345d982edc99fc11b8669--eb924200a201486ca97655cc3cc63f0e
42058d2c3ce546abaca9b88040fb631f
eb924200a201486ca97655cc3cc63f0e--42058d2c3ce546abaca9b88040fb631f
a51ef4c0d39847babc2d10c53c02acc2
RX(theta₁₂)
42058d2c3ce546abaca9b88040fb631f--a51ef4c0d39847babc2d10c53c02acc2
1c997fc185dc494b96703a1ed95f2a44
RY(theta₁₆)
a51ef4c0d39847babc2d10c53c02acc2--1c997fc185dc494b96703a1ed95f2a44
03d9038149d74818bf72d8c6cc2b9db5
RX(theta₂₀)
1c997fc185dc494b96703a1ed95f2a44--03d9038149d74818bf72d8c6cc2b9db5
2c7cd52b309040e6acfee6c6519fdd7e
03d9038149d74818bf72d8c6cc2b9db5--2c7cd52b309040e6acfee6c6519fdd7e
e62fc202152243929c1afae6ea0f7697
2c7cd52b309040e6acfee6c6519fdd7e--e62fc202152243929c1afae6ea0f7697
eb850f24d15d47809948360eb3ac1d94
e62fc202152243929c1afae6ea0f7697--eb850f24d15d47809948360eb3ac1d94
19d3fdb99d8047dcb479402cb9b7d096
e7b4444cb13c4f21b6737057a80932c3
d5b75880cd8e4efabb515259652027de--e7b4444cb13c4f21b6737057a80932c3
b4245318fad74e46b5e6af9040cc2a16
2
e4585e24d00844fb8f4e26ccde2c9052
RX(theta₁)
e7b4444cb13c4f21b6737057a80932c3--e4585e24d00844fb8f4e26ccde2c9052
e92ff0a135244aa59d85bbf99d67e929
RY(theta₅)
e4585e24d00844fb8f4e26ccde2c9052--e92ff0a135244aa59d85bbf99d67e929
c023274ccbb14907895c4a66de606e20
RX(theta₉)
e92ff0a135244aa59d85bbf99d67e929--c023274ccbb14907895c4a66de606e20
9a3a64faca544afa9bc9719dd666ba0d
X
c023274ccbb14907895c4a66de606e20--9a3a64faca544afa9bc9719dd666ba0d
9a3a64faca544afa9bc9719dd666ba0d--eb924200a201486ca97655cc3cc63f0e
f485ade02cbf453c818cd39d48c986fb
9a3a64faca544afa9bc9719dd666ba0d--f485ade02cbf453c818cd39d48c986fb
b377bd5a92a5475582410b66e930c0d3
RX(theta₁₃)
f485ade02cbf453c818cd39d48c986fb--b377bd5a92a5475582410b66e930c0d3
9500763df2264eb18848389c2c79f3e2
RY(theta₁₇)
b377bd5a92a5475582410b66e930c0d3--9500763df2264eb18848389c2c79f3e2
0681d571252140dc9f2a75609d581dd5
RX(theta₂₁)
9500763df2264eb18848389c2c79f3e2--0681d571252140dc9f2a75609d581dd5
6c9b0d12521b4133922338a8bb08bb92
X
0681d571252140dc9f2a75609d581dd5--6c9b0d12521b4133922338a8bb08bb92
6c9b0d12521b4133922338a8bb08bb92--2c7cd52b309040e6acfee6c6519fdd7e
7ed3279db9254daca4b0bb7075c39acd
6c9b0d12521b4133922338a8bb08bb92--7ed3279db9254daca4b0bb7075c39acd
7ed3279db9254daca4b0bb7075c39acd--19d3fdb99d8047dcb479402cb9b7d096
ea1354ad2c1447589fb9df7d7997835b
b579b547e0a3493890c3f43d25282728
b4245318fad74e46b5e6af9040cc2a16--b579b547e0a3493890c3f43d25282728
ef3629e643d94ebe99b306900bcaa9fd
3
f070d969fecb4c30853297536d3ddca3
RX(theta₂)
b579b547e0a3493890c3f43d25282728--f070d969fecb4c30853297536d3ddca3
3a15c3c0b34c45d1b0b9086d5dc91dfc
RY(theta₆)
f070d969fecb4c30853297536d3ddca3--3a15c3c0b34c45d1b0b9086d5dc91dfc
5c464b20fe4c4bdc8a341790bdac0568
RX(theta₁₀)
3a15c3c0b34c45d1b0b9086d5dc91dfc--5c464b20fe4c4bdc8a341790bdac0568
2ef39b6d00e74b449e177e55636b45f8
5c464b20fe4c4bdc8a341790bdac0568--2ef39b6d00e74b449e177e55636b45f8
4c5dff52e05f4f97b0762ab5e654f3e4
X
2ef39b6d00e74b449e177e55636b45f8--4c5dff52e05f4f97b0762ab5e654f3e4
4c5dff52e05f4f97b0762ab5e654f3e4--f485ade02cbf453c818cd39d48c986fb
3603eda4834640e88a9c359814b0da62
RX(theta₁₄)
4c5dff52e05f4f97b0762ab5e654f3e4--3603eda4834640e88a9c359814b0da62
6aef37e2594b490bbb714b949391c9f4
RY(theta₁₈)
3603eda4834640e88a9c359814b0da62--6aef37e2594b490bbb714b949391c9f4
ed789c6a682143278f02021b40ac9729
RX(theta₂₂)
6aef37e2594b490bbb714b949391c9f4--ed789c6a682143278f02021b40ac9729
e2153ac5471549d5bd0d1fd9877adbb0
ed789c6a682143278f02021b40ac9729--e2153ac5471549d5bd0d1fd9877adbb0
839e65e61b3f461698d50d9171e139ab
X
e2153ac5471549d5bd0d1fd9877adbb0--839e65e61b3f461698d50d9171e139ab
839e65e61b3f461698d50d9171e139ab--7ed3279db9254daca4b0bb7075c39acd
839e65e61b3f461698d50d9171e139ab--ea1354ad2c1447589fb9df7d7997835b
e881ccdc3d444a1681f80d26b8f3e8ea
443d0b1c841b434a9a546fafaf701a0e
X
ef3629e643d94ebe99b306900bcaa9fd--443d0b1c841b434a9a546fafaf701a0e
589c3530fca64a8185e0335008f8feb4
RX(theta₃)
443d0b1c841b434a9a546fafaf701a0e--589c3530fca64a8185e0335008f8feb4
94e260f846ef4ff9b83353c24b0dbb56
RY(theta₇)
589c3530fca64a8185e0335008f8feb4--94e260f846ef4ff9b83353c24b0dbb56
22692a1ffca34bb89108dc48d137dcb2
RX(theta₁₁)
94e260f846ef4ff9b83353c24b0dbb56--22692a1ffca34bb89108dc48d137dcb2
168fede553da44db9618493ccb84345b
X
22692a1ffca34bb89108dc48d137dcb2--168fede553da44db9618493ccb84345b
168fede553da44db9618493ccb84345b--2ef39b6d00e74b449e177e55636b45f8
6a26887d8ccf48788d6edb1c3d7483ea
168fede553da44db9618493ccb84345b--6a26887d8ccf48788d6edb1c3d7483ea
d0ff9ee9a5a34b219951572454734176
RX(theta₁₅)
6a26887d8ccf48788d6edb1c3d7483ea--d0ff9ee9a5a34b219951572454734176
f6a946e93751467a834847b08f546c70
RY(theta₁₉)
d0ff9ee9a5a34b219951572454734176--f6a946e93751467a834847b08f546c70
2e1495cd30f64d879564eff62e14c851
RX(theta₂₃)
f6a946e93751467a834847b08f546c70--2e1495cd30f64d879564eff62e14c851
7af6e13ba93440ba925f9e64604424b4
X
2e1495cd30f64d879564eff62e14c851--7af6e13ba93440ba925f9e64604424b4
7af6e13ba93440ba925f9e64604424b4--e2153ac5471549d5bd0d1fd9877adbb0
dae9c6d453d64c8191f80d698e87f77e
7af6e13ba93440ba925f9e64604424b4--dae9c6d453d64c8191f80d698e87f77e
dae9c6d453d64c8191f80d698e87f77e--e881ccdc3d444a1681f80d26b8f3e8ea
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 , 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 , 1.+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.2390-0.1881 j , 0.1646-0.0699 j , -0.4417-0.1439 j , -0.1631+0.1908 j ,
0.0305-0.2692 j , 0.2547+0.0842 j , 0.1633+0.2059 j , -0.2162-0.5792 j ],
[ 0.0061+0.1679 j , 0.1055+0.2131 j , -0.1951-0.0451 j , 0.0293+0.2837 j ,
-0.1773+0.3076 j , -0.0885+0.0918 j , 0.4380+0.4700 j , -0.3802+0.3070 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 )
└── 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 ]] )