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.79208433+0. j 0. -0.60645514 j 0.05509328+0. j
0. -0.04218188 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_4343d04be70f4add8fa3709e7f611342
Circuit block
cluster_7c12db6761a84231b842f335b93ffacc
Prep block
0fd4f2abc2474a5aae9f452c4a51b68e
0
f1a0652c0c134d8e996bdb8326f534fb
0fd4f2abc2474a5aae9f452c4a51b68e--f1a0652c0c134d8e996bdb8326f534fb
a4f45ca72e7d4e5881edbad69e9a832f
1
5d9adc1aa2f7491993f1c43650e6c370
RX(theta₀)
f1a0652c0c134d8e996bdb8326f534fb--5d9adc1aa2f7491993f1c43650e6c370
b4cdae3d90a64b1f92a1c16d7052001d
RY(theta₄)
5d9adc1aa2f7491993f1c43650e6c370--b4cdae3d90a64b1f92a1c16d7052001d
5455ba37f94247fc84fabaf1ac93c881
RX(theta₈)
b4cdae3d90a64b1f92a1c16d7052001d--5455ba37f94247fc84fabaf1ac93c881
781eba2f774c4ecea27c9ec68754256e
5455ba37f94247fc84fabaf1ac93c881--781eba2f774c4ecea27c9ec68754256e
44cdec9e3bb543188c8c053589634a02
781eba2f774c4ecea27c9ec68754256e--44cdec9e3bb543188c8c053589634a02
2760852f9e8d4536903940578f388772
RX(theta₁₂)
44cdec9e3bb543188c8c053589634a02--2760852f9e8d4536903940578f388772
8fd850c0e19b42c28f07a357feb446fd
RY(theta₁₆)
2760852f9e8d4536903940578f388772--8fd850c0e19b42c28f07a357feb446fd
913363912c254860817af199a097f6b8
RX(theta₂₀)
8fd850c0e19b42c28f07a357feb446fd--913363912c254860817af199a097f6b8
4c36659680e0496aaa7b65fb85f0958b
913363912c254860817af199a097f6b8--4c36659680e0496aaa7b65fb85f0958b
18cd7ae382524431ae6f8db06bc69e3e
4c36659680e0496aaa7b65fb85f0958b--18cd7ae382524431ae6f8db06bc69e3e
567ac9bf057c487fbd00d217acbaccba
18cd7ae382524431ae6f8db06bc69e3e--567ac9bf057c487fbd00d217acbaccba
8814984c711041879b8731559839f0f1
391afb18319d4363896f03ae67939bb3
a4f45ca72e7d4e5881edbad69e9a832f--391afb18319d4363896f03ae67939bb3
b29abbe6129744cf9e5b8c1bb316ebba
2
43e0d7b742bf4448a5c16e9e67f6940a
RX(theta₁)
391afb18319d4363896f03ae67939bb3--43e0d7b742bf4448a5c16e9e67f6940a
f3b71a687a1c41e5be2558e48541617c
RY(theta₅)
43e0d7b742bf4448a5c16e9e67f6940a--f3b71a687a1c41e5be2558e48541617c
165d6632bd2340a5b21156106a054c60
RX(theta₉)
f3b71a687a1c41e5be2558e48541617c--165d6632bd2340a5b21156106a054c60
9384720532fb41c8bff6d66c437ce9c0
X
165d6632bd2340a5b21156106a054c60--9384720532fb41c8bff6d66c437ce9c0
9384720532fb41c8bff6d66c437ce9c0--781eba2f774c4ecea27c9ec68754256e
b2805ac0b9a04b93bb8edf87b5e0cf14
9384720532fb41c8bff6d66c437ce9c0--b2805ac0b9a04b93bb8edf87b5e0cf14
67055bc259ac4ba19eb694b78528a203
RX(theta₁₃)
b2805ac0b9a04b93bb8edf87b5e0cf14--67055bc259ac4ba19eb694b78528a203
a6f26acc7b7d47aa8feee183901bd43d
RY(theta₁₇)
67055bc259ac4ba19eb694b78528a203--a6f26acc7b7d47aa8feee183901bd43d
3efd9287bfa642ddae82801f347a0eb8
RX(theta₂₁)
a6f26acc7b7d47aa8feee183901bd43d--3efd9287bfa642ddae82801f347a0eb8
3a2814b8fd2748559626f2884c33955b
X
3efd9287bfa642ddae82801f347a0eb8--3a2814b8fd2748559626f2884c33955b
3a2814b8fd2748559626f2884c33955b--4c36659680e0496aaa7b65fb85f0958b
c981c157f47f4458a181fcd33afb9e8d
3a2814b8fd2748559626f2884c33955b--c981c157f47f4458a181fcd33afb9e8d
c981c157f47f4458a181fcd33afb9e8d--8814984c711041879b8731559839f0f1
4d8945db3e04447bbf2956d741439fbe
ecae63b7fd054b3f945f342053ed6303
b29abbe6129744cf9e5b8c1bb316ebba--ecae63b7fd054b3f945f342053ed6303
20ab3b165a87404793813b4099042080
3
03c9efec996544d894be913eed4f1ca9
RX(theta₂)
ecae63b7fd054b3f945f342053ed6303--03c9efec996544d894be913eed4f1ca9
8dae96c2314a4ef29a937c140ff9291d
RY(theta₆)
03c9efec996544d894be913eed4f1ca9--8dae96c2314a4ef29a937c140ff9291d
c006839f2bc940648bc04229108ac252
RX(theta₁₀)
8dae96c2314a4ef29a937c140ff9291d--c006839f2bc940648bc04229108ac252
e848b8369b944eb0876fb5829968675b
c006839f2bc940648bc04229108ac252--e848b8369b944eb0876fb5829968675b
fea3f910556c4af582c0fbafaf485b25
X
e848b8369b944eb0876fb5829968675b--fea3f910556c4af582c0fbafaf485b25
fea3f910556c4af582c0fbafaf485b25--b2805ac0b9a04b93bb8edf87b5e0cf14
786e8c75943d4e69bba1621ec3f32dd4
RX(theta₁₄)
fea3f910556c4af582c0fbafaf485b25--786e8c75943d4e69bba1621ec3f32dd4
5da338df919a4ff49a4c1b35e92af7ed
RY(theta₁₈)
786e8c75943d4e69bba1621ec3f32dd4--5da338df919a4ff49a4c1b35e92af7ed
a50efbcdafe74177b2b8a2466191a6c9
RX(theta₂₂)
5da338df919a4ff49a4c1b35e92af7ed--a50efbcdafe74177b2b8a2466191a6c9
6de93a0046d84a67a715216ffd1d8070
a50efbcdafe74177b2b8a2466191a6c9--6de93a0046d84a67a715216ffd1d8070
32b410d4d0554c78afe149660cf9f93d
X
6de93a0046d84a67a715216ffd1d8070--32b410d4d0554c78afe149660cf9f93d
32b410d4d0554c78afe149660cf9f93d--c981c157f47f4458a181fcd33afb9e8d
32b410d4d0554c78afe149660cf9f93d--4d8945db3e04447bbf2956d741439fbe
748146fe0c3a4dd190d6bb746e85c147
b53c5f0b22c74a51a2e06140f393ae1c
X
20ab3b165a87404793813b4099042080--b53c5f0b22c74a51a2e06140f393ae1c
a2e076e3b1224cb296465c3bb87b483d
RX(theta₃)
b53c5f0b22c74a51a2e06140f393ae1c--a2e076e3b1224cb296465c3bb87b483d
79a4e8ec70c94bc3bbff97ced73aa14f
RY(theta₇)
a2e076e3b1224cb296465c3bb87b483d--79a4e8ec70c94bc3bbff97ced73aa14f
79a0c1e16326418a937596bd62ece4bc
RX(theta₁₁)
79a4e8ec70c94bc3bbff97ced73aa14f--79a0c1e16326418a937596bd62ece4bc
f76cae0798b847b0ba1915d260747602
X
79a0c1e16326418a937596bd62ece4bc--f76cae0798b847b0ba1915d260747602
f76cae0798b847b0ba1915d260747602--e848b8369b944eb0876fb5829968675b
17346c9da73145b7bf34d1b3ed8cceb8
f76cae0798b847b0ba1915d260747602--17346c9da73145b7bf34d1b3ed8cceb8
1e8282159b804c4e9aabf1cc8a65fe7b
RX(theta₁₅)
17346c9da73145b7bf34d1b3ed8cceb8--1e8282159b804c4e9aabf1cc8a65fe7b
345517e529564299bb7fa435dda7ab0b
RY(theta₁₉)
1e8282159b804c4e9aabf1cc8a65fe7b--345517e529564299bb7fa435dda7ab0b
9e9f78c50b4e47c29febfcd874baa04c
RX(theta₂₃)
345517e529564299bb7fa435dda7ab0b--9e9f78c50b4e47c29febfcd874baa04c
8a6a85946df14a25962b7350fe6c6ddf
X
9e9f78c50b4e47c29febfcd874baa04c--8a6a85946df14a25962b7350fe6c6ddf
8a6a85946df14a25962b7350fe6c6ddf--6de93a0046d84a67a715216ffd1d8070
3ea9155c021749dab5ece55901af8211
8a6a85946df14a25962b7350fe6c6ddf--3ea9155c021749dab5ece55901af8211
3ea9155c021749dab5ece55901af8211--748146fe0c3a4dd190d6bb746e85c147
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 , 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 ]] )
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.0072+0.1317 j , -0.1315+0.0093 j , 0.4393-0.0518 j , 0.2144-0.0019 j ,
-0.4913+0.3684 j , -0.0079-0.3988 j , -0.0065-0.0633 j , -0.2841+0.3202 j ],
[ -0.2017-0.2458 j , 0.3581-0.0040 j , -0.0432+0.3556 j , -0.0084-0.1461 j ,
0.2217+0.1800 j , 0.5418+0.0416 j , -0.3747-0.3151 j , 0.0661+0.0052 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 ]] )