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.21959765+0.97559053 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_b2a6c26dbdf64fd4b00e5380f93930c2
Circuit block
cluster_d8e287e3976b4f438f18262ef93e45d5
Prep block
820d31832a9d4dbaa66f146d8b403984
0
11d8281b3b214d3abd66b8d29f311a56
820d31832a9d4dbaa66f146d8b403984--11d8281b3b214d3abd66b8d29f311a56
eb706d54fffa41ee9add246cee12959d
1
4ebfe6b7664f48939c3626a36f4d166b
RX(theta₀)
11d8281b3b214d3abd66b8d29f311a56--4ebfe6b7664f48939c3626a36f4d166b
9221bb8a2f5f43309f2fd47d52e3822d
RY(theta₄)
4ebfe6b7664f48939c3626a36f4d166b--9221bb8a2f5f43309f2fd47d52e3822d
fda12a8edc334e29bcf83ddc0d7bb22c
RX(theta₈)
9221bb8a2f5f43309f2fd47d52e3822d--fda12a8edc334e29bcf83ddc0d7bb22c
d94f4ea30c624235bccf5b13f7a8caf0
fda12a8edc334e29bcf83ddc0d7bb22c--d94f4ea30c624235bccf5b13f7a8caf0
d47f0bd5374e4930bb227d60034aa7e0
d94f4ea30c624235bccf5b13f7a8caf0--d47f0bd5374e4930bb227d60034aa7e0
ed3260f1ccd34ecb9fd3ec2ad3a02050
RX(theta₁₂)
d47f0bd5374e4930bb227d60034aa7e0--ed3260f1ccd34ecb9fd3ec2ad3a02050
759f0f9c50ae4e31aea38e0b7f01052c
RY(theta₁₆)
ed3260f1ccd34ecb9fd3ec2ad3a02050--759f0f9c50ae4e31aea38e0b7f01052c
8942fab441354249abe85742f1ed7454
RX(theta₂₀)
759f0f9c50ae4e31aea38e0b7f01052c--8942fab441354249abe85742f1ed7454
d0acce4b19d64b4abe3b7b77fd4723d4
8942fab441354249abe85742f1ed7454--d0acce4b19d64b4abe3b7b77fd4723d4
472b3ff838844ffa997717a553ecf0e2
d0acce4b19d64b4abe3b7b77fd4723d4--472b3ff838844ffa997717a553ecf0e2
0d6c771d7d5b430e811f9e65e9444d6c
472b3ff838844ffa997717a553ecf0e2--0d6c771d7d5b430e811f9e65e9444d6c
d8bedd372c234d0ba6c97ef82f7aa375
49a521e7ef584d4a8aa5ccabd5c7b716
eb706d54fffa41ee9add246cee12959d--49a521e7ef584d4a8aa5ccabd5c7b716
c2ae9ce2f50f47d3886257ac8b91a14f
2
1e7951661dca41959214b137634c074c
RX(theta₁)
49a521e7ef584d4a8aa5ccabd5c7b716--1e7951661dca41959214b137634c074c
a46e750a9dbf4dceaaee95606936ca85
RY(theta₅)
1e7951661dca41959214b137634c074c--a46e750a9dbf4dceaaee95606936ca85
7c5636755ce94dfd8430e78df1bac95a
RX(theta₉)
a46e750a9dbf4dceaaee95606936ca85--7c5636755ce94dfd8430e78df1bac95a
73716b629f004146ab9f84c204aea2b6
X
7c5636755ce94dfd8430e78df1bac95a--73716b629f004146ab9f84c204aea2b6
73716b629f004146ab9f84c204aea2b6--d94f4ea30c624235bccf5b13f7a8caf0
e3d55fffe1ab4184868a0e54b5b502d9
73716b629f004146ab9f84c204aea2b6--e3d55fffe1ab4184868a0e54b5b502d9
b19400da4f3f4fa4a2d4ca2de461d9d3
RX(theta₁₃)
e3d55fffe1ab4184868a0e54b5b502d9--b19400da4f3f4fa4a2d4ca2de461d9d3
14735dfcf5b5418b978f39dc9b407e3e
RY(theta₁₇)
b19400da4f3f4fa4a2d4ca2de461d9d3--14735dfcf5b5418b978f39dc9b407e3e
49ea3879139a4951af7144146bac57fd
RX(theta₂₁)
14735dfcf5b5418b978f39dc9b407e3e--49ea3879139a4951af7144146bac57fd
eeced7fd594a4d30a8312e53e2ebf126
X
49ea3879139a4951af7144146bac57fd--eeced7fd594a4d30a8312e53e2ebf126
eeced7fd594a4d30a8312e53e2ebf126--d0acce4b19d64b4abe3b7b77fd4723d4
f1c81b95af444298b8d0a88158696cb5
eeced7fd594a4d30a8312e53e2ebf126--f1c81b95af444298b8d0a88158696cb5
f1c81b95af444298b8d0a88158696cb5--d8bedd372c234d0ba6c97ef82f7aa375
786df64f6c20453f91709677b256e414
f1b53c8a2c8e4e30994a47decde9d3f0
c2ae9ce2f50f47d3886257ac8b91a14f--f1b53c8a2c8e4e30994a47decde9d3f0
6f99cd072e5f460f97f8f59fff6c3397
3
d0ccdbf02e58477ebfc60661f8a17a62
RX(theta₂)
f1b53c8a2c8e4e30994a47decde9d3f0--d0ccdbf02e58477ebfc60661f8a17a62
a4f701c367a74208943954fad096226c
RY(theta₆)
d0ccdbf02e58477ebfc60661f8a17a62--a4f701c367a74208943954fad096226c
194c551782ef46a4856cc04bb7a2f44c
RX(theta₁₀)
a4f701c367a74208943954fad096226c--194c551782ef46a4856cc04bb7a2f44c
f0e78c47dc3e4add8e9e206b54b524ff
194c551782ef46a4856cc04bb7a2f44c--f0e78c47dc3e4add8e9e206b54b524ff
a366e04f47aa43ef9b1b3cd3a31c3ced
X
f0e78c47dc3e4add8e9e206b54b524ff--a366e04f47aa43ef9b1b3cd3a31c3ced
a366e04f47aa43ef9b1b3cd3a31c3ced--e3d55fffe1ab4184868a0e54b5b502d9
0ae5b39cd42b4f3c984ce0973f78c193
RX(theta₁₄)
a366e04f47aa43ef9b1b3cd3a31c3ced--0ae5b39cd42b4f3c984ce0973f78c193
96918e3b7ed44b2b8812157423c1e35a
RY(theta₁₈)
0ae5b39cd42b4f3c984ce0973f78c193--96918e3b7ed44b2b8812157423c1e35a
2680b796edd6458aa1a182bf281695ff
RX(theta₂₂)
96918e3b7ed44b2b8812157423c1e35a--2680b796edd6458aa1a182bf281695ff
c2c60f096b534f24b77844209bf6377e
2680b796edd6458aa1a182bf281695ff--c2c60f096b534f24b77844209bf6377e
17be9f5cdbac4b57b46267b8d4e42e0e
X
c2c60f096b534f24b77844209bf6377e--17be9f5cdbac4b57b46267b8d4e42e0e
17be9f5cdbac4b57b46267b8d4e42e0e--f1c81b95af444298b8d0a88158696cb5
17be9f5cdbac4b57b46267b8d4e42e0e--786df64f6c20453f91709677b256e414
6a9ece07573a441e98eb9cc14a627aad
e3e6494842e04ac5b6fb54962270d56e
X
6f99cd072e5f460f97f8f59fff6c3397--e3e6494842e04ac5b6fb54962270d56e
06641eaa25c847308dcf0af1f52edc88
RX(theta₃)
e3e6494842e04ac5b6fb54962270d56e--06641eaa25c847308dcf0af1f52edc88
9b3bae6861ce4861aea521f3a1bfe6b6
RY(theta₇)
06641eaa25c847308dcf0af1f52edc88--9b3bae6861ce4861aea521f3a1bfe6b6
9f990fb106744f20a069947dd3e8ee9d
RX(theta₁₁)
9b3bae6861ce4861aea521f3a1bfe6b6--9f990fb106744f20a069947dd3e8ee9d
faf3e6e957614f31aea8a4ac3eeb0049
X
9f990fb106744f20a069947dd3e8ee9d--faf3e6e957614f31aea8a4ac3eeb0049
faf3e6e957614f31aea8a4ac3eeb0049--f0e78c47dc3e4add8e9e206b54b524ff
7273d4fc64874cef9409c742ccd3f70c
faf3e6e957614f31aea8a4ac3eeb0049--7273d4fc64874cef9409c742ccd3f70c
8dc81683fa1d4710a05a71152e3842cb
RX(theta₁₅)
7273d4fc64874cef9409c742ccd3f70c--8dc81683fa1d4710a05a71152e3842cb
308cb3ce5ecf49729bd39ef8866e4ce5
RY(theta₁₉)
8dc81683fa1d4710a05a71152e3842cb--308cb3ce5ecf49729bd39ef8866e4ce5
1ed05a6ba2e34b808a840a345232f761
RX(theta₂₃)
308cb3ce5ecf49729bd39ef8866e4ce5--1ed05a6ba2e34b808a840a345232f761
0af88a8da04243d9b50459d36385fcc1
X
1ed05a6ba2e34b808a840a345232f761--0af88a8da04243d9b50459d36385fcc1
0af88a8da04243d9b50459d36385fcc1--c2c60f096b534f24b77844209bf6377e
c4f28775f104493eafd4e253f91cc272
0af88a8da04243d9b50459d36385fcc1--c4f28775f104493eafd4e253f91cc272
c4f28775f104493eafd4e253f91cc272--6a9ece07573a441e98eb9cc14a627aad
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 )
├── 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 ]] )