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.58729291+0. j 0. + 0.04520839 j 0.80572725+0. j
0. + 0.06202294 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_a309924e874e4a51882a2a3c76cd3c62
Circuit block
cluster_153faf85c16e47b98907d57b7e9cf033
Prep block
37749086c3624f6b8b88ef331da322d9
0
1bbcf20c30c54dc788b7e7ce1f36553f
37749086c3624f6b8b88ef331da322d9--1bbcf20c30c54dc788b7e7ce1f36553f
2c23699454ec481989b79fc60cfa3199
1
c0e193a641f548328ca6771f4698d7ea
RX(theta₀)
1bbcf20c30c54dc788b7e7ce1f36553f--c0e193a641f548328ca6771f4698d7ea
27d4908deb5f403496c9fd37326eb2bb
RY(theta₄)
c0e193a641f548328ca6771f4698d7ea--27d4908deb5f403496c9fd37326eb2bb
aaa0832408a14e7c8b2beb4ddbfe8e6d
RX(theta₈)
27d4908deb5f403496c9fd37326eb2bb--aaa0832408a14e7c8b2beb4ddbfe8e6d
12bb8312f66d4bf082e762ed1250b8bb
aaa0832408a14e7c8b2beb4ddbfe8e6d--12bb8312f66d4bf082e762ed1250b8bb
c8761a5c38b44279a11a229b2f77795d
12bb8312f66d4bf082e762ed1250b8bb--c8761a5c38b44279a11a229b2f77795d
a64d99e1e2dd48ff89d247321f0c55a5
RX(theta₁₂)
c8761a5c38b44279a11a229b2f77795d--a64d99e1e2dd48ff89d247321f0c55a5
21a1a0280f1340dd9ea09e8b08c168e4
RY(theta₁₆)
a64d99e1e2dd48ff89d247321f0c55a5--21a1a0280f1340dd9ea09e8b08c168e4
c711177803cf45488bfb7e4ea2658c58
RX(theta₂₀)
21a1a0280f1340dd9ea09e8b08c168e4--c711177803cf45488bfb7e4ea2658c58
9d560866f28a4a888c96325bbaaad82f
c711177803cf45488bfb7e4ea2658c58--9d560866f28a4a888c96325bbaaad82f
3b94d68b194e497e84390e75773e8d89
9d560866f28a4a888c96325bbaaad82f--3b94d68b194e497e84390e75773e8d89
103075b3e92e4fabb860fdc8474bd52c
3b94d68b194e497e84390e75773e8d89--103075b3e92e4fabb860fdc8474bd52c
01cfcd17be50431c9995f8dc741210f4
5f225d2bf1ef4daba7220e1ee94e2c6c
2c23699454ec481989b79fc60cfa3199--5f225d2bf1ef4daba7220e1ee94e2c6c
aa8b6e3636e143048d96c6885d5234d0
2
e59f8933a7514e27add0709f95ad37bb
RX(theta₁)
5f225d2bf1ef4daba7220e1ee94e2c6c--e59f8933a7514e27add0709f95ad37bb
eccf6a0e31084b468512864d7860817d
RY(theta₅)
e59f8933a7514e27add0709f95ad37bb--eccf6a0e31084b468512864d7860817d
b0e40febbc2f4cc69b1045c5039e4857
RX(theta₉)
eccf6a0e31084b468512864d7860817d--b0e40febbc2f4cc69b1045c5039e4857
1957443d32044ebcb7baae4beaad5520
X
b0e40febbc2f4cc69b1045c5039e4857--1957443d32044ebcb7baae4beaad5520
1957443d32044ebcb7baae4beaad5520--12bb8312f66d4bf082e762ed1250b8bb
482aa206068d486f9439d313f28b545e
1957443d32044ebcb7baae4beaad5520--482aa206068d486f9439d313f28b545e
acfb50a5a5214d678522bcee1a745163
RX(theta₁₃)
482aa206068d486f9439d313f28b545e--acfb50a5a5214d678522bcee1a745163
c1d2ca743fa847529dcb12f31d9bdcfd
RY(theta₁₇)
acfb50a5a5214d678522bcee1a745163--c1d2ca743fa847529dcb12f31d9bdcfd
1b9c7fb8abf249ad93fd741f4f52e8d2
RX(theta₂₁)
c1d2ca743fa847529dcb12f31d9bdcfd--1b9c7fb8abf249ad93fd741f4f52e8d2
79f7eb61aac8421b9226764c1fad05b1
X
1b9c7fb8abf249ad93fd741f4f52e8d2--79f7eb61aac8421b9226764c1fad05b1
79f7eb61aac8421b9226764c1fad05b1--9d560866f28a4a888c96325bbaaad82f
282ac4a76711421babd30404f27252da
79f7eb61aac8421b9226764c1fad05b1--282ac4a76711421babd30404f27252da
282ac4a76711421babd30404f27252da--01cfcd17be50431c9995f8dc741210f4
0687b978f354459f9afb68d761bf41dc
caaac81c892e49c8a8aa21d324427b6b
aa8b6e3636e143048d96c6885d5234d0--caaac81c892e49c8a8aa21d324427b6b
a6bc7d7b15c6416ebd0558d70b981332
3
613f65bad9ac45b0b6fc48cfbb5f998d
RX(theta₂)
caaac81c892e49c8a8aa21d324427b6b--613f65bad9ac45b0b6fc48cfbb5f998d
14b23220cd51499e833a1e885cc8f5bd
RY(theta₆)
613f65bad9ac45b0b6fc48cfbb5f998d--14b23220cd51499e833a1e885cc8f5bd
caa980504eb34d829846d8f9e1d38f9a
RX(theta₁₀)
14b23220cd51499e833a1e885cc8f5bd--caa980504eb34d829846d8f9e1d38f9a
5096f8d50e1f40988bdc544a54d37ca3
caa980504eb34d829846d8f9e1d38f9a--5096f8d50e1f40988bdc544a54d37ca3
9a654c54775648188a946ba0fc9868cc
X
5096f8d50e1f40988bdc544a54d37ca3--9a654c54775648188a946ba0fc9868cc
9a654c54775648188a946ba0fc9868cc--482aa206068d486f9439d313f28b545e
7950f071934340d08cc64283ae6a91bf
RX(theta₁₄)
9a654c54775648188a946ba0fc9868cc--7950f071934340d08cc64283ae6a91bf
93e63d4990424f1c9b3db1135b3819cb
RY(theta₁₈)
7950f071934340d08cc64283ae6a91bf--93e63d4990424f1c9b3db1135b3819cb
4d61d1ef333b4572b87bd143c29e91b4
RX(theta₂₂)
93e63d4990424f1c9b3db1135b3819cb--4d61d1ef333b4572b87bd143c29e91b4
7f73f20175f04b30afacc39f9336b9d6
4d61d1ef333b4572b87bd143c29e91b4--7f73f20175f04b30afacc39f9336b9d6
2e144c6b6d614781bbc98ee5c0d7036f
X
7f73f20175f04b30afacc39f9336b9d6--2e144c6b6d614781bbc98ee5c0d7036f
2e144c6b6d614781bbc98ee5c0d7036f--282ac4a76711421babd30404f27252da
2e144c6b6d614781bbc98ee5c0d7036f--0687b978f354459f9afb68d761bf41dc
a0ce6d818a084e88ac5aa822092fa93b
0706a99062d64115914d74742af5cdd2
X
a6bc7d7b15c6416ebd0558d70b981332--0706a99062d64115914d74742af5cdd2
0d2688006a8443389014f32c639ad034
RX(theta₃)
0706a99062d64115914d74742af5cdd2--0d2688006a8443389014f32c639ad034
8569c30243244d728901a11043e01082
RY(theta₇)
0d2688006a8443389014f32c639ad034--8569c30243244d728901a11043e01082
fbae3d493b7241539c9003fa181e53e6
RX(theta₁₁)
8569c30243244d728901a11043e01082--fbae3d493b7241539c9003fa181e53e6
3da3cd6a706a4bf190342d67bf21078f
X
fbae3d493b7241539c9003fa181e53e6--3da3cd6a706a4bf190342d67bf21078f
3da3cd6a706a4bf190342d67bf21078f--5096f8d50e1f40988bdc544a54d37ca3
7d3d1a57b976455db859f799e1df4c79
3da3cd6a706a4bf190342d67bf21078f--7d3d1a57b976455db859f799e1df4c79
2453b3722b5e4deba2c0aafdec209902
RX(theta₁₅)
7d3d1a57b976455db859f799e1df4c79--2453b3722b5e4deba2c0aafdec209902
fc174861b71744aab7d994343493ca4e
RY(theta₁₉)
2453b3722b5e4deba2c0aafdec209902--fc174861b71744aab7d994343493ca4e
dedf12fb455d447eaeebcf3516179a2e
RX(theta₂₃)
fc174861b71744aab7d994343493ca4e--dedf12fb455d447eaeebcf3516179a2e
de076c2e4b4f48b1a14b2a1df914ccf4
X
dedf12fb455d447eaeebcf3516179a2e--de076c2e4b4f48b1a14b2a1df914ccf4
de076c2e4b4f48b1a14b2a1df914ccf4--7f73f20175f04b30afacc39f9336b9d6
010ff3bf92fb4a9ead8091d861f9ffc9
de076c2e4b4f48b1a14b2a1df914ccf4--010ff3bf92fb4a9ead8091d861f9ffc9
010ff3bf92fb4a9ead8091d861f9ffc9--a0ce6d818a084e88ac5aa822092fa93b
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 , 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 ]] )
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.3367+0.1492 j , -0.2387-0.4529 j , -0.0397+0.1336 j , -0.1125+0.5659 j ,
-0.0703-0.0669 j , -0.0778+0.2793 j , 0.3534-0.1424 j , 0.0682+0.0811 j ],
[ 0.3436+0.2393 j , 0.0505-0.0122 j , -0.0484-0.1730 j , -0.0440+0.2970 j ,
0.3615+0.2362 j , 0.2817-0.0456 j , 0.2953+0.4642 j , -0.2217+0.2824 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 )
├── X( 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 ]] )