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.71347553-0.58459751 j 0. + 0. j 0.29877691-0.24480761 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_47cd3c7fcacb4ae48e7427389cd3def6
Circuit block
cluster_cbc479d0ea4443d4bb04808fff2b2dec
Prep block
708fce5cbc5a4871ac3c815852f91261
0
bd0050a1457542fe80b70cfe6184d04c
708fce5cbc5a4871ac3c815852f91261--bd0050a1457542fe80b70cfe6184d04c
1fe996c41c214730b1362a51b6ed2762
1
d24a18af2c2c4225be7db3bd32d8e2c7
RX(theta₀)
bd0050a1457542fe80b70cfe6184d04c--d24a18af2c2c4225be7db3bd32d8e2c7
249d380cc0754c38a8baf5137b2cf566
RY(theta₄)
d24a18af2c2c4225be7db3bd32d8e2c7--249d380cc0754c38a8baf5137b2cf566
e8a2a9ecd385428d91f43a5f59b0a669
RX(theta₈)
249d380cc0754c38a8baf5137b2cf566--e8a2a9ecd385428d91f43a5f59b0a669
769d3b08447a43ac9c15edd523fe0afb
e8a2a9ecd385428d91f43a5f59b0a669--769d3b08447a43ac9c15edd523fe0afb
5710f59e881a432fa85c7cf16e5df0c4
769d3b08447a43ac9c15edd523fe0afb--5710f59e881a432fa85c7cf16e5df0c4
b61529445e5245c1af744c31bca65007
RX(theta₁₂)
5710f59e881a432fa85c7cf16e5df0c4--b61529445e5245c1af744c31bca65007
54ba1f96088d49d2894c520aca38336e
RY(theta₁₆)
b61529445e5245c1af744c31bca65007--54ba1f96088d49d2894c520aca38336e
8bce27203a4f47f2b56156877c5e102f
RX(theta₂₀)
54ba1f96088d49d2894c520aca38336e--8bce27203a4f47f2b56156877c5e102f
69ce68e9954349cdb7b7349147f1939d
8bce27203a4f47f2b56156877c5e102f--69ce68e9954349cdb7b7349147f1939d
d106d71dd0824d449cd875f0427812db
69ce68e9954349cdb7b7349147f1939d--d106d71dd0824d449cd875f0427812db
ef47da833443470c885aefd4faa0ca9a
d106d71dd0824d449cd875f0427812db--ef47da833443470c885aefd4faa0ca9a
d3b9e97f30594023903b02ec6619bc78
759d29cec9394cada2d63de1ae1c4797
1fe996c41c214730b1362a51b6ed2762--759d29cec9394cada2d63de1ae1c4797
04fa3c9469f84395847cd0dcceb63eab
2
7e1a8d0dc23240f384f83b0b16eee13d
RX(theta₁)
759d29cec9394cada2d63de1ae1c4797--7e1a8d0dc23240f384f83b0b16eee13d
32711a67f2de48a6b1dee820489b80ec
RY(theta₅)
7e1a8d0dc23240f384f83b0b16eee13d--32711a67f2de48a6b1dee820489b80ec
4d2e3eab95bc4119a29ac0289ee60996
RX(theta₉)
32711a67f2de48a6b1dee820489b80ec--4d2e3eab95bc4119a29ac0289ee60996
0c3122669dd84092b8b38881e5717ce7
X
4d2e3eab95bc4119a29ac0289ee60996--0c3122669dd84092b8b38881e5717ce7
0c3122669dd84092b8b38881e5717ce7--769d3b08447a43ac9c15edd523fe0afb
0fbf9e41e03348d78652e286f7bfae37
0c3122669dd84092b8b38881e5717ce7--0fbf9e41e03348d78652e286f7bfae37
bd46e2a2f7764579944376d7d58181b3
RX(theta₁₃)
0fbf9e41e03348d78652e286f7bfae37--bd46e2a2f7764579944376d7d58181b3
38e3e13148ce469582610931405124e5
RY(theta₁₇)
bd46e2a2f7764579944376d7d58181b3--38e3e13148ce469582610931405124e5
492ca8df17774cb5ba91452c5f1ed3b7
RX(theta₂₁)
38e3e13148ce469582610931405124e5--492ca8df17774cb5ba91452c5f1ed3b7
fd98e1791c6141a6a6059cb17c36b3b2
X
492ca8df17774cb5ba91452c5f1ed3b7--fd98e1791c6141a6a6059cb17c36b3b2
fd98e1791c6141a6a6059cb17c36b3b2--69ce68e9954349cdb7b7349147f1939d
d13a90009bd34210a7f8486aec101c9a
fd98e1791c6141a6a6059cb17c36b3b2--d13a90009bd34210a7f8486aec101c9a
d13a90009bd34210a7f8486aec101c9a--d3b9e97f30594023903b02ec6619bc78
018e6d7ebf4c4dbb9f015d707600512d
94cc3f73a32941b395854d72c2f94157
04fa3c9469f84395847cd0dcceb63eab--94cc3f73a32941b395854d72c2f94157
a12d4805c9c14f1cbf7f8b7ec466b973
3
553f111c5e9544e1a0fb10a49a4bfe00
RX(theta₂)
94cc3f73a32941b395854d72c2f94157--553f111c5e9544e1a0fb10a49a4bfe00
52911733ae6f43029e71041d064542b3
RY(theta₆)
553f111c5e9544e1a0fb10a49a4bfe00--52911733ae6f43029e71041d064542b3
0ceba898d4fa419fa8d55b8c90aa8376
RX(theta₁₀)
52911733ae6f43029e71041d064542b3--0ceba898d4fa419fa8d55b8c90aa8376
00a3642d290047daa2edd23f323036b1
0ceba898d4fa419fa8d55b8c90aa8376--00a3642d290047daa2edd23f323036b1
dd0dabacc9c143a08cc822159e2b1969
X
00a3642d290047daa2edd23f323036b1--dd0dabacc9c143a08cc822159e2b1969
dd0dabacc9c143a08cc822159e2b1969--0fbf9e41e03348d78652e286f7bfae37
95a3ef89cba048eaaaa902012a10cbf2
RX(theta₁₄)
dd0dabacc9c143a08cc822159e2b1969--95a3ef89cba048eaaaa902012a10cbf2
273f986544b445e48aa6206c845b01ec
RY(theta₁₈)
95a3ef89cba048eaaaa902012a10cbf2--273f986544b445e48aa6206c845b01ec
6f7cc16f064e4c2e8fe76063aa537831
RX(theta₂₂)
273f986544b445e48aa6206c845b01ec--6f7cc16f064e4c2e8fe76063aa537831
a9ae34712048490fa8f0d6aecac6b499
6f7cc16f064e4c2e8fe76063aa537831--a9ae34712048490fa8f0d6aecac6b499
1f1eb1dc9f1943a6b909f6a1ddd9dc87
X
a9ae34712048490fa8f0d6aecac6b499--1f1eb1dc9f1943a6b909f6a1ddd9dc87
1f1eb1dc9f1943a6b909f6a1ddd9dc87--d13a90009bd34210a7f8486aec101c9a
1f1eb1dc9f1943a6b909f6a1ddd9dc87--018e6d7ebf4c4dbb9f015d707600512d
3b8135f367444fe0bc0e16ec877e0a3b
27514f51de4448728701728f7500dfb0
X
a12d4805c9c14f1cbf7f8b7ec466b973--27514f51de4448728701728f7500dfb0
b8e0e70b8ba5485ea11f9b41e8afcc5e
RX(theta₃)
27514f51de4448728701728f7500dfb0--b8e0e70b8ba5485ea11f9b41e8afcc5e
adf8bdfdf215484f8f1e8cb0b24f7e1f
RY(theta₇)
b8e0e70b8ba5485ea11f9b41e8afcc5e--adf8bdfdf215484f8f1e8cb0b24f7e1f
e49b3f85038a4a96988bfb01679415f3
RX(theta₁₁)
adf8bdfdf215484f8f1e8cb0b24f7e1f--e49b3f85038a4a96988bfb01679415f3
c0b3f8fb30a54fb6b89935fcea3bd4ef
X
e49b3f85038a4a96988bfb01679415f3--c0b3f8fb30a54fb6b89935fcea3bd4ef
c0b3f8fb30a54fb6b89935fcea3bd4ef--00a3642d290047daa2edd23f323036b1
47d63a05b9cb480c88eb770df1fccd58
c0b3f8fb30a54fb6b89935fcea3bd4ef--47d63a05b9cb480c88eb770df1fccd58
69a77766d19e49e79b9eadc8282cb3be
RX(theta₁₅)
47d63a05b9cb480c88eb770df1fccd58--69a77766d19e49e79b9eadc8282cb3be
1a6723c0b2fe452eabfa378fc5f82b9d
RY(theta₁₉)
69a77766d19e49e79b9eadc8282cb3be--1a6723c0b2fe452eabfa378fc5f82b9d
aac5bd1d880e48aeabc614073a90e661
RX(theta₂₃)
1a6723c0b2fe452eabfa378fc5f82b9d--aac5bd1d880e48aeabc614073a90e661
ae02238819984f62bb885c2f685f317e
X
aac5bd1d880e48aeabc614073a90e661--ae02238819984f62bb885c2f685f317e
ae02238819984f62bb885c2f685f317e--a9ae34712048490fa8f0d6aecac6b499
808ef8bfe0104fbb820c4bb9c8d704e2
ae02238819984f62bb885c2f685f317e--808ef8bfe0104fbb820c4bb9c8d704e2
808ef8bfe0104fbb820c4bb9c8d704e2--3b8135f367444fe0bc0e16ec877e0a3b
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 , 1.+0. j , 0.+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.2561-0.1032 j , 0.0494+0.0587 j , 0.3258+0.1880 j , 0.2518-0.0606 j ,
-0.3047-0.3365 j , -0.0829+0.4560 j , 0.2562+0.1226 j , -0.1817+0.4180 j ],
[ 0.3139+0.4935 j , -0.2357+0.3002 j , 0.4257+0.0696 j , 0.0326+0.0448 j ,
0.1226-0.1125 j , -0.2873+0.1443 j , -0.1797-0.3972 j , -0.0041-0.0452 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 )
├── 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 ]] )