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.50929534+0. j 0.24053405+0. j 0. -0.74715619 j
0. -0.35287286 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_8cf781b043394bc4a9817069d3456417
Circuit block
cluster_4692c63c275a4fa99d80957e5effb0da
Prep block
ad3d01f0f6984c3daed70002aee8b6f9
0
2f806f2fef714faf84a5d5f3622721e4
ad3d01f0f6984c3daed70002aee8b6f9--2f806f2fef714faf84a5d5f3622721e4
1667bdc0632f4bc2a460df354fa69445
1
d9bdd4a8b4154dbba0e61f8358199700
RX(theta₀)
2f806f2fef714faf84a5d5f3622721e4--d9bdd4a8b4154dbba0e61f8358199700
5f8e6212c93a42919ee6034c2ae3aea8
RY(theta₄)
d9bdd4a8b4154dbba0e61f8358199700--5f8e6212c93a42919ee6034c2ae3aea8
5d3fe7eae6aa44bdab78254ef4ef8413
RX(theta₈)
5f8e6212c93a42919ee6034c2ae3aea8--5d3fe7eae6aa44bdab78254ef4ef8413
5ff6d2d4121a44f29d311768e0f86c74
5d3fe7eae6aa44bdab78254ef4ef8413--5ff6d2d4121a44f29d311768e0f86c74
0479f480753843e5918db285d797f289
5ff6d2d4121a44f29d311768e0f86c74--0479f480753843e5918db285d797f289
45e932ceb1494e5080139291b818095f
RX(theta₁₂)
0479f480753843e5918db285d797f289--45e932ceb1494e5080139291b818095f
e77af8b454494927ade307b45851f19e
RY(theta₁₆)
45e932ceb1494e5080139291b818095f--e77af8b454494927ade307b45851f19e
88ef851599bc4a898b98f61b8f15c4cc
RX(theta₂₀)
e77af8b454494927ade307b45851f19e--88ef851599bc4a898b98f61b8f15c4cc
2d6a756dcdec4606b6668b0fc2384ffb
88ef851599bc4a898b98f61b8f15c4cc--2d6a756dcdec4606b6668b0fc2384ffb
bc2ff7703c84473592d678f1647e9945
2d6a756dcdec4606b6668b0fc2384ffb--bc2ff7703c84473592d678f1647e9945
9ab2c451e7b446e4898cf26a532fe841
bc2ff7703c84473592d678f1647e9945--9ab2c451e7b446e4898cf26a532fe841
df0aeb6ead904489a6a9b72d795058a9
03136a1aa67443869d2d66a4db123bac
1667bdc0632f4bc2a460df354fa69445--03136a1aa67443869d2d66a4db123bac
439e83f8727345569a635ac0f4aae484
2
a09a75df57ed44b7864b4d2e4d5f516c
RX(theta₁)
03136a1aa67443869d2d66a4db123bac--a09a75df57ed44b7864b4d2e4d5f516c
392e8f04310647a48c57139eb0a057a9
RY(theta₅)
a09a75df57ed44b7864b4d2e4d5f516c--392e8f04310647a48c57139eb0a057a9
3d0fa604d9cc4d3f931eef934593f6d8
RX(theta₉)
392e8f04310647a48c57139eb0a057a9--3d0fa604d9cc4d3f931eef934593f6d8
c5c863368a304abaa6898db3d0d8c7f2
X
3d0fa604d9cc4d3f931eef934593f6d8--c5c863368a304abaa6898db3d0d8c7f2
c5c863368a304abaa6898db3d0d8c7f2--5ff6d2d4121a44f29d311768e0f86c74
2babfd31adc44b398c51a03581af048e
c5c863368a304abaa6898db3d0d8c7f2--2babfd31adc44b398c51a03581af048e
7b2f3b23e5b44d958faa3b29d60cecef
RX(theta₁₃)
2babfd31adc44b398c51a03581af048e--7b2f3b23e5b44d958faa3b29d60cecef
39b698b635784e68bc4b8e44471f6bd7
RY(theta₁₇)
7b2f3b23e5b44d958faa3b29d60cecef--39b698b635784e68bc4b8e44471f6bd7
bf8e50fd74fe49f8954080029dac13f0
RX(theta₂₁)
39b698b635784e68bc4b8e44471f6bd7--bf8e50fd74fe49f8954080029dac13f0
20d6bff8e8b4411db931215b833b3ce7
X
bf8e50fd74fe49f8954080029dac13f0--20d6bff8e8b4411db931215b833b3ce7
20d6bff8e8b4411db931215b833b3ce7--2d6a756dcdec4606b6668b0fc2384ffb
fbf941b3c574403cacd81a26cf120c22
20d6bff8e8b4411db931215b833b3ce7--fbf941b3c574403cacd81a26cf120c22
fbf941b3c574403cacd81a26cf120c22--df0aeb6ead904489a6a9b72d795058a9
b51abd2f715048cd9a8f54a368e46aee
347696d4b5374af38c0f5bf7c71b85a2
439e83f8727345569a635ac0f4aae484--347696d4b5374af38c0f5bf7c71b85a2
9da50bb4fde842918bc3c49700b9e2ac
3
c9f3865d14264722a53c78824f3294a0
RX(theta₂)
347696d4b5374af38c0f5bf7c71b85a2--c9f3865d14264722a53c78824f3294a0
46422b39d250425d83cdac9c25edac7c
RY(theta₆)
c9f3865d14264722a53c78824f3294a0--46422b39d250425d83cdac9c25edac7c
4f2674a9482a48b3a37a4f0cb2cc5317
RX(theta₁₀)
46422b39d250425d83cdac9c25edac7c--4f2674a9482a48b3a37a4f0cb2cc5317
4d04cc969804421bb96568462b2369b5
4f2674a9482a48b3a37a4f0cb2cc5317--4d04cc969804421bb96568462b2369b5
9e368c867bfb4a188afc62fdcf766098
X
4d04cc969804421bb96568462b2369b5--9e368c867bfb4a188afc62fdcf766098
9e368c867bfb4a188afc62fdcf766098--2babfd31adc44b398c51a03581af048e
3b2f52be388b499cb5590af54575e5c1
RX(theta₁₄)
9e368c867bfb4a188afc62fdcf766098--3b2f52be388b499cb5590af54575e5c1
3c42e1a7c2eb4cf78d4ef9ce2a231e8c
RY(theta₁₈)
3b2f52be388b499cb5590af54575e5c1--3c42e1a7c2eb4cf78d4ef9ce2a231e8c
78076661e4a743c29cbc854803815ad5
RX(theta₂₂)
3c42e1a7c2eb4cf78d4ef9ce2a231e8c--78076661e4a743c29cbc854803815ad5
e5fd5d5f34c7458ca552c003fdb51b9d
78076661e4a743c29cbc854803815ad5--e5fd5d5f34c7458ca552c003fdb51b9d
bc2a69b72407455cb80bb63d1bc07c3f
X
e5fd5d5f34c7458ca552c003fdb51b9d--bc2a69b72407455cb80bb63d1bc07c3f
bc2a69b72407455cb80bb63d1bc07c3f--fbf941b3c574403cacd81a26cf120c22
bc2a69b72407455cb80bb63d1bc07c3f--b51abd2f715048cd9a8f54a368e46aee
38a293e3d00f4ab987f606e015cfe37a
b5cb09f7aea2417cbafa06e1220542fa
X
9da50bb4fde842918bc3c49700b9e2ac--b5cb09f7aea2417cbafa06e1220542fa
5054c9cca39846d8b5a8954ee0866f03
RX(theta₃)
b5cb09f7aea2417cbafa06e1220542fa--5054c9cca39846d8b5a8954ee0866f03
5adf2e117f3e477eaaeaf3832d5d29a2
RY(theta₇)
5054c9cca39846d8b5a8954ee0866f03--5adf2e117f3e477eaaeaf3832d5d29a2
55a3577f84d74acd8f43f082509f9430
RX(theta₁₁)
5adf2e117f3e477eaaeaf3832d5d29a2--55a3577f84d74acd8f43f082509f9430
6e23baa66f164b13bb86b996d60274a7
X
55a3577f84d74acd8f43f082509f9430--6e23baa66f164b13bb86b996d60274a7
6e23baa66f164b13bb86b996d60274a7--4d04cc969804421bb96568462b2369b5
b0aa8e7b6258405ca5e9e69bf7369fe8
6e23baa66f164b13bb86b996d60274a7--b0aa8e7b6258405ca5e9e69bf7369fe8
22ad0bafe5cb4411830e921aa5a4dad6
RX(theta₁₅)
b0aa8e7b6258405ca5e9e69bf7369fe8--22ad0bafe5cb4411830e921aa5a4dad6
dbd9ad62a95643d381912d06463adbef
RY(theta₁₉)
22ad0bafe5cb4411830e921aa5a4dad6--dbd9ad62a95643d381912d06463adbef
ea877ac23cd94035b79dd553eadd045e
RX(theta₂₃)
dbd9ad62a95643d381912d06463adbef--ea877ac23cd94035b79dd553eadd045e
9a316c0d1bd0417db37cd4c5355ae8d7
X
ea877ac23cd94035b79dd553eadd045e--9a316c0d1bd0417db37cd4c5355ae8d7
9a316c0d1bd0417db37cd4c5355ae8d7--e5fd5d5f34c7458ca552c003fdb51b9d
193f172278b946ecb5ae314a6ce61817
9a316c0d1bd0417db37cd4c5355ae8d7--193f172278b946ecb5ae314a6ce61817
193f172278b946ecb5ae314a6ce61817--38a293e3d00f4ab987f606e015cfe37a
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 , 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 , 0.+0. j , 1.+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.1907-0.2530 j , -0.1918-0.0710 j , 0.3923-0.3315 j , -0.0455-0.1129 j ,
0.1975-0.0792 j , 0.5236+0.0577 j , 0.2448-0.1669 j , -0.4084+0.0428 j ],
[ -0.0952-0.1626 j , 0.1650+0.0488 j , 0.0936-0.3226 j , 0.1072+0.4489 j ,
0.0674-0.1573 j , -0.1308+0.6493 j , -0.2529-0.1209 j , -0.1880+0.1647 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 ]] )