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.95664017+0. j 0. -0.00752554 j 0.29116612+0. j
0. -0.0022905 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_7305264220b3471da02446a1cbbd19ae
Circuit block
cluster_932422c020144a0ba4163c2a8772a815
Prep block
be3925e9ffe94c5cb22f96c8f9b57127
0
dfeaf46a5e164c748651b468cb92d5f7
be3925e9ffe94c5cb22f96c8f9b57127--dfeaf46a5e164c748651b468cb92d5f7
3c8444756f4445859b3c4e5d12433749
1
54f2f108e6114f96992b7adf49ea432d
RX(theta₀)
dfeaf46a5e164c748651b468cb92d5f7--54f2f108e6114f96992b7adf49ea432d
93b2f10816fb4d7e9f209b7052132f82
RY(theta₄)
54f2f108e6114f96992b7adf49ea432d--93b2f10816fb4d7e9f209b7052132f82
ff462ff7156245658d93d845c838fc11
RX(theta₈)
93b2f10816fb4d7e9f209b7052132f82--ff462ff7156245658d93d845c838fc11
00bdf19df1eb475e8292df67bc77f1dd
ff462ff7156245658d93d845c838fc11--00bdf19df1eb475e8292df67bc77f1dd
de1adef0b8bb4f7f8f96b899a9cc72c0
00bdf19df1eb475e8292df67bc77f1dd--de1adef0b8bb4f7f8f96b899a9cc72c0
393166091f3f4edbaf4a71753a1cc96f
RX(theta₁₂)
de1adef0b8bb4f7f8f96b899a9cc72c0--393166091f3f4edbaf4a71753a1cc96f
af94045d0dec4c5b8fc42e7808b7a15e
RY(theta₁₆)
393166091f3f4edbaf4a71753a1cc96f--af94045d0dec4c5b8fc42e7808b7a15e
55a2bfcbee384542b47c2c8a06e8c93c
RX(theta₂₀)
af94045d0dec4c5b8fc42e7808b7a15e--55a2bfcbee384542b47c2c8a06e8c93c
7f3721784d4c4d2a82d060fd7ba2c9d5
55a2bfcbee384542b47c2c8a06e8c93c--7f3721784d4c4d2a82d060fd7ba2c9d5
6900dfaa1540404eb44d569154743e1c
7f3721784d4c4d2a82d060fd7ba2c9d5--6900dfaa1540404eb44d569154743e1c
efd5fc0422e74f009960cb175ac8fb99
6900dfaa1540404eb44d569154743e1c--efd5fc0422e74f009960cb175ac8fb99
2d58e333d87c4858a977b9d5277138c9
690979b378fc4cf394a1324c0fee9204
3c8444756f4445859b3c4e5d12433749--690979b378fc4cf394a1324c0fee9204
9bfbd9a879514f1685b47381437176ba
2
06464689a2c9436e80b3ce3d049be5b9
RX(theta₁)
690979b378fc4cf394a1324c0fee9204--06464689a2c9436e80b3ce3d049be5b9
82863bdd8a2f4ae9a35a1e6f17e3010e
RY(theta₅)
06464689a2c9436e80b3ce3d049be5b9--82863bdd8a2f4ae9a35a1e6f17e3010e
e0546681329343439d8833266273b968
RX(theta₉)
82863bdd8a2f4ae9a35a1e6f17e3010e--e0546681329343439d8833266273b968
0f1d27fdcd2e407aa5022e6d1b268915
X
e0546681329343439d8833266273b968--0f1d27fdcd2e407aa5022e6d1b268915
0f1d27fdcd2e407aa5022e6d1b268915--00bdf19df1eb475e8292df67bc77f1dd
8a978623409f44b2aa84b9744d203e75
0f1d27fdcd2e407aa5022e6d1b268915--8a978623409f44b2aa84b9744d203e75
b4f9160e328c43f898d5f65d0f816475
RX(theta₁₃)
8a978623409f44b2aa84b9744d203e75--b4f9160e328c43f898d5f65d0f816475
beff56f662b449f8b70d0f86bc625507
RY(theta₁₇)
b4f9160e328c43f898d5f65d0f816475--beff56f662b449f8b70d0f86bc625507
9b65a1b135ac4ca9a520f6e0e8c89aec
RX(theta₂₁)
beff56f662b449f8b70d0f86bc625507--9b65a1b135ac4ca9a520f6e0e8c89aec
2cb2c9358d924839a7666c22b11e08a5
X
9b65a1b135ac4ca9a520f6e0e8c89aec--2cb2c9358d924839a7666c22b11e08a5
2cb2c9358d924839a7666c22b11e08a5--7f3721784d4c4d2a82d060fd7ba2c9d5
5b333f1201b7414bb9997382032b3278
2cb2c9358d924839a7666c22b11e08a5--5b333f1201b7414bb9997382032b3278
5b333f1201b7414bb9997382032b3278--2d58e333d87c4858a977b9d5277138c9
93e3461c61794d869646bb384e834d90
0db1d4dcd8234e5cb49bf768160e1486
9bfbd9a879514f1685b47381437176ba--0db1d4dcd8234e5cb49bf768160e1486
78b79b172d6e4e45b424fbdf916bd6fe
3
35349f902aff412c81940875d8e62b15
RX(theta₂)
0db1d4dcd8234e5cb49bf768160e1486--35349f902aff412c81940875d8e62b15
17d04ae8d6334d37b6466b49ba8a0673
RY(theta₆)
35349f902aff412c81940875d8e62b15--17d04ae8d6334d37b6466b49ba8a0673
53198ce505984818b606584faf9e0945
RX(theta₁₀)
17d04ae8d6334d37b6466b49ba8a0673--53198ce505984818b606584faf9e0945
96f4a10755e541e6abcf95bd12f0d8de
53198ce505984818b606584faf9e0945--96f4a10755e541e6abcf95bd12f0d8de
230dd65e464f45fe808747ba202a64d7
X
96f4a10755e541e6abcf95bd12f0d8de--230dd65e464f45fe808747ba202a64d7
230dd65e464f45fe808747ba202a64d7--8a978623409f44b2aa84b9744d203e75
439b840f6d3d48c7be319796a2027645
RX(theta₁₄)
230dd65e464f45fe808747ba202a64d7--439b840f6d3d48c7be319796a2027645
44bb1595d1ee48339f9b6a6b72f0db2c
RY(theta₁₈)
439b840f6d3d48c7be319796a2027645--44bb1595d1ee48339f9b6a6b72f0db2c
e5f66dfddbde456c99f499fd016eb7fd
RX(theta₂₂)
44bb1595d1ee48339f9b6a6b72f0db2c--e5f66dfddbde456c99f499fd016eb7fd
587013b33b004df6b29b5b5ef40b884e
e5f66dfddbde456c99f499fd016eb7fd--587013b33b004df6b29b5b5ef40b884e
ef52ba9fa87d406e8fe6c2a891d26f36
X
587013b33b004df6b29b5b5ef40b884e--ef52ba9fa87d406e8fe6c2a891d26f36
ef52ba9fa87d406e8fe6c2a891d26f36--5b333f1201b7414bb9997382032b3278
ef52ba9fa87d406e8fe6c2a891d26f36--93e3461c61794d869646bb384e834d90
9909cdd538a24e11b8e3193747d6c00e
73605968200c474e8186e10fb5eeb65f
X
78b79b172d6e4e45b424fbdf916bd6fe--73605968200c474e8186e10fb5eeb65f
d10725737f4e4e6a9d406c43be317e5e
RX(theta₃)
73605968200c474e8186e10fb5eeb65f--d10725737f4e4e6a9d406c43be317e5e
91aad4b1b6be47edab24e751512c81bc
RY(theta₇)
d10725737f4e4e6a9d406c43be317e5e--91aad4b1b6be47edab24e751512c81bc
10518f3b900c480cb3b4d8c1f7ddc509
RX(theta₁₁)
91aad4b1b6be47edab24e751512c81bc--10518f3b900c480cb3b4d8c1f7ddc509
4f2e1c29b4474ad0ba794c1b17b6c1ab
X
10518f3b900c480cb3b4d8c1f7ddc509--4f2e1c29b4474ad0ba794c1b17b6c1ab
4f2e1c29b4474ad0ba794c1b17b6c1ab--96f4a10755e541e6abcf95bd12f0d8de
90eb1599b79046c3ab9e6df2ca1b191f
4f2e1c29b4474ad0ba794c1b17b6c1ab--90eb1599b79046c3ab9e6df2ca1b191f
800c72e312344f2a9ee222e52e4f3683
RX(theta₁₅)
90eb1599b79046c3ab9e6df2ca1b191f--800c72e312344f2a9ee222e52e4f3683
c487ca091a4842aebd0a4c5b61c44104
RY(theta₁₉)
800c72e312344f2a9ee222e52e4f3683--c487ca091a4842aebd0a4c5b61c44104
6c0038225a8f47339666bcaf7d1c450b
RX(theta₂₃)
c487ca091a4842aebd0a4c5b61c44104--6c0038225a8f47339666bcaf7d1c450b
ac89b4435ede48d6bf2b58601c671bbd
X
6c0038225a8f47339666bcaf7d1c450b--ac89b4435ede48d6bf2b58601c671bbd
ac89b4435ede48d6bf2b58601c671bbd--587013b33b004df6b29b5b5ef40b884e
cc66885dc52f440897d18842eb33a05e
ac89b4435ede48d6bf2b58601c671bbd--cc66885dc52f440897d18842eb33a05e
cc66885dc52f440897d18842eb33a05e--9909cdd538a24e11b8e3193747d6c00e
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 , 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 ]] )
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.4778-0.3032 j , -0.2188+0.0063 j , -0.5854+0.1054 j , -0.0209+0.1171 j ,
-0.1233+0.1146 j , 0.2949-0.1529 j , 0.2178+0.2514 j , 0.0053+0.1206 j ],
[ 0.0060+0.1147 j , 0.1033+0.1432 j , -0.2309+0.3088 j , -0.2681+0.2402 j ,
-0.2283-0.2065 j , -0.4066+0.1532 j , -0.5098-0.1379 j , 0.2512-0.2275 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 ]] )