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.85139706+0. j 0. + 0.49866638 j 0. + 0.14034828 j
-0.0822025 + 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_3934ac68c4ae41b99faf90d704f6bd32
Circuit block
cluster_8355210bd6ab4ca6b1c87500d9304bb8
Prep block
cfd4e96c60454606b57c4fc66dae18c8
0
5439b9e43de34b53b112f90c5fb0abd6
cfd4e96c60454606b57c4fc66dae18c8--5439b9e43de34b53b112f90c5fb0abd6
2cacda3403ed47caa4e94b1faa747c34
1
ddee1d03f6014f34962b56aaf514c0dd
RX(theta₀)
5439b9e43de34b53b112f90c5fb0abd6--ddee1d03f6014f34962b56aaf514c0dd
c0b927e657f14d18907dddb3bdba1f59
RY(theta₄)
ddee1d03f6014f34962b56aaf514c0dd--c0b927e657f14d18907dddb3bdba1f59
20d063099b794782bae311565880f972
RX(theta₈)
c0b927e657f14d18907dddb3bdba1f59--20d063099b794782bae311565880f972
baddd71052cf471eb99ea42813ea07bf
20d063099b794782bae311565880f972--baddd71052cf471eb99ea42813ea07bf
88a7804c4dcf495eb2a1fefd83337cc9
baddd71052cf471eb99ea42813ea07bf--88a7804c4dcf495eb2a1fefd83337cc9
0458df360bc842729b312ffdc31243b9
RX(theta₁₂)
88a7804c4dcf495eb2a1fefd83337cc9--0458df360bc842729b312ffdc31243b9
0b25b56ff2044f929447391b71e6d3b1
RY(theta₁₆)
0458df360bc842729b312ffdc31243b9--0b25b56ff2044f929447391b71e6d3b1
ada7aba0d84f47dba2fa8a62450c928e
RX(theta₂₀)
0b25b56ff2044f929447391b71e6d3b1--ada7aba0d84f47dba2fa8a62450c928e
97765c84c5aa497d8a1fbb964a1e9f6d
ada7aba0d84f47dba2fa8a62450c928e--97765c84c5aa497d8a1fbb964a1e9f6d
23f5b41eb4ba4380a0c05cfa768f3ea9
97765c84c5aa497d8a1fbb964a1e9f6d--23f5b41eb4ba4380a0c05cfa768f3ea9
864e69dded2b4e39b5f487b1bd00dceb
23f5b41eb4ba4380a0c05cfa768f3ea9--864e69dded2b4e39b5f487b1bd00dceb
55655821e7764cfcafd4960f3fc714e4
3bfe2db109ef4bfcb7d479dbc45adee0
2cacda3403ed47caa4e94b1faa747c34--3bfe2db109ef4bfcb7d479dbc45adee0
c745fc6c8d61482fae8dd05e31c88148
2
2a1f4c8591174e0d9bfc364bc0e3f20a
RX(theta₁)
3bfe2db109ef4bfcb7d479dbc45adee0--2a1f4c8591174e0d9bfc364bc0e3f20a
4d16d01a1c20495ba060acd8c4436e71
RY(theta₅)
2a1f4c8591174e0d9bfc364bc0e3f20a--4d16d01a1c20495ba060acd8c4436e71
661c2ce281bd4467b6e0297a996418c1
RX(theta₉)
4d16d01a1c20495ba060acd8c4436e71--661c2ce281bd4467b6e0297a996418c1
d2404308d4114597a85d0e0bf796aa88
X
661c2ce281bd4467b6e0297a996418c1--d2404308d4114597a85d0e0bf796aa88
d2404308d4114597a85d0e0bf796aa88--baddd71052cf471eb99ea42813ea07bf
0f2569ce098449e28ce66129194f9a02
d2404308d4114597a85d0e0bf796aa88--0f2569ce098449e28ce66129194f9a02
d988cf5e1a18455999c10d66579c0269
RX(theta₁₃)
0f2569ce098449e28ce66129194f9a02--d988cf5e1a18455999c10d66579c0269
5a5f224da6444cb88c9c463b2e883a4b
RY(theta₁₇)
d988cf5e1a18455999c10d66579c0269--5a5f224da6444cb88c9c463b2e883a4b
24840e9b4ae549919e3b244113e60d28
RX(theta₂₁)
5a5f224da6444cb88c9c463b2e883a4b--24840e9b4ae549919e3b244113e60d28
e7a356803fb34764b7ff0b70f7b5b97e
X
24840e9b4ae549919e3b244113e60d28--e7a356803fb34764b7ff0b70f7b5b97e
e7a356803fb34764b7ff0b70f7b5b97e--97765c84c5aa497d8a1fbb964a1e9f6d
028f51b761a943caaea4bcddb569c804
e7a356803fb34764b7ff0b70f7b5b97e--028f51b761a943caaea4bcddb569c804
028f51b761a943caaea4bcddb569c804--55655821e7764cfcafd4960f3fc714e4
a101340f9fff429fa6c878ee2ea12607
d0cf92d5e9af4c00a41ed90f60c87212
c745fc6c8d61482fae8dd05e31c88148--d0cf92d5e9af4c00a41ed90f60c87212
75abf5197bbd4e979a642e0bd42fa138
3
db0200d09d9b4726973d174cf6f15b93
RX(theta₂)
d0cf92d5e9af4c00a41ed90f60c87212--db0200d09d9b4726973d174cf6f15b93
d064e403bfae482cacc7d7d4f9d32be0
RY(theta₆)
db0200d09d9b4726973d174cf6f15b93--d064e403bfae482cacc7d7d4f9d32be0
d446a35fb988474eb79b5a9ef20a1d18
RX(theta₁₀)
d064e403bfae482cacc7d7d4f9d32be0--d446a35fb988474eb79b5a9ef20a1d18
707a0f63a38c43fa8d8b0e52d0f53a08
d446a35fb988474eb79b5a9ef20a1d18--707a0f63a38c43fa8d8b0e52d0f53a08
cdc35221e76d439c9de946db0e6a3782
X
707a0f63a38c43fa8d8b0e52d0f53a08--cdc35221e76d439c9de946db0e6a3782
cdc35221e76d439c9de946db0e6a3782--0f2569ce098449e28ce66129194f9a02
18acaac294af45fab459c7c369ab087c
RX(theta₁₄)
cdc35221e76d439c9de946db0e6a3782--18acaac294af45fab459c7c369ab087c
52a8f304c6b1447d9fd06ff7da83a120
RY(theta₁₈)
18acaac294af45fab459c7c369ab087c--52a8f304c6b1447d9fd06ff7da83a120
a12d872ed5c8405794b79ad7ef165cce
RX(theta₂₂)
52a8f304c6b1447d9fd06ff7da83a120--a12d872ed5c8405794b79ad7ef165cce
d2fa75f75cc74c389fd77ee9eb9a8e8a
a12d872ed5c8405794b79ad7ef165cce--d2fa75f75cc74c389fd77ee9eb9a8e8a
c03bc8e9de7e4d5696519533a5831957
X
d2fa75f75cc74c389fd77ee9eb9a8e8a--c03bc8e9de7e4d5696519533a5831957
c03bc8e9de7e4d5696519533a5831957--028f51b761a943caaea4bcddb569c804
c03bc8e9de7e4d5696519533a5831957--a101340f9fff429fa6c878ee2ea12607
f98362f336374dedb4acac86d07cd997
e5e64b7fbb2f4fcda42e6296c717ead0
X
75abf5197bbd4e979a642e0bd42fa138--e5e64b7fbb2f4fcda42e6296c717ead0
70aa09a0998e4b96bb9467177b503bb1
RX(theta₃)
e5e64b7fbb2f4fcda42e6296c717ead0--70aa09a0998e4b96bb9467177b503bb1
49730a4027ed4699b2a24ebc31b7b23d
RY(theta₇)
70aa09a0998e4b96bb9467177b503bb1--49730a4027ed4699b2a24ebc31b7b23d
6a978faf41e14665b1e7b5b7cfe25cf7
RX(theta₁₁)
49730a4027ed4699b2a24ebc31b7b23d--6a978faf41e14665b1e7b5b7cfe25cf7
3df93b55231147a89bc5aa754bfe135a
X
6a978faf41e14665b1e7b5b7cfe25cf7--3df93b55231147a89bc5aa754bfe135a
3df93b55231147a89bc5aa754bfe135a--707a0f63a38c43fa8d8b0e52d0f53a08
d86ee0f188d748e086ba805f6e3852a0
3df93b55231147a89bc5aa754bfe135a--d86ee0f188d748e086ba805f6e3852a0
788f074b6a2142d596fdd0612d488b52
RX(theta₁₅)
d86ee0f188d748e086ba805f6e3852a0--788f074b6a2142d596fdd0612d488b52
d047abc2dc9942a0b93d60d75afcfa53
RY(theta₁₉)
788f074b6a2142d596fdd0612d488b52--d047abc2dc9942a0b93d60d75afcfa53
6897cdf0cd344c5faf17d6e0d3345269
RX(theta₂₃)
d047abc2dc9942a0b93d60d75afcfa53--6897cdf0cd344c5faf17d6e0d3345269
83f1187f3385478aa06542b0588ac576
X
6897cdf0cd344c5faf17d6e0d3345269--83f1187f3385478aa06542b0588ac576
83f1187f3385478aa06542b0588ac576--d2fa75f75cc74c389fd77ee9eb9a8e8a
5285e2e369934727bc1d405f33d82589
83f1187f3385478aa06542b0588ac576--5285e2e369934727bc1d405f33d82589
5285e2e369934727bc1d405f33d82589--f98362f336374dedb4acac86d07cd997
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 , 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 ]] )
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.1643-0.0622 j , -0.5407+0.1029 j , 0.1102-0.1265 j , -0.6922+0.0940 j ,
-0.1508-0.2266 j , -0.1701+0.0631 j , 0.1501-0.0578 j , -0.0811+0.1033 j ],
[ -0.0584-0.0556 j , -0.0646+0.2321 j , 0.2937-0.1183 j , 0.0567+0.0674 j ,
0.3735+0.2155 j , 0.2888-0.0695 j , -0.3494-0.3858 j , -0.0950+0.5228 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 )
├── 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 ]] )