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.58924015+0. j 0. -0.0426862 j 0. -0.80472075 j
-0.05829621+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_4371b66b571f4a0fa32624dfb13a681b
Circuit block
cluster_f53e550314d94f8b891451b86a8d33b1
Prep block
e6bd7fa9f3c1456db4de097910828292
0
0a0ff1590d4d4c4696a14b04b13caee7
e6bd7fa9f3c1456db4de097910828292--0a0ff1590d4d4c4696a14b04b13caee7
03a781df9b1b49b7a17796241258a264
1
55434fa14d5f4697b20ce34138b492e9
RX(theta₀)
0a0ff1590d4d4c4696a14b04b13caee7--55434fa14d5f4697b20ce34138b492e9
9ab694b570c54b95ae7188795976042a
RY(theta₄)
55434fa14d5f4697b20ce34138b492e9--9ab694b570c54b95ae7188795976042a
f1edc04159e64c26aa9b7295e6a5ef4c
RX(theta₈)
9ab694b570c54b95ae7188795976042a--f1edc04159e64c26aa9b7295e6a5ef4c
30f659f47efa4ebd9fb30d46d6038916
f1edc04159e64c26aa9b7295e6a5ef4c--30f659f47efa4ebd9fb30d46d6038916
96dec0507cc241818a36c936093c478f
30f659f47efa4ebd9fb30d46d6038916--96dec0507cc241818a36c936093c478f
915db6578b8c4cc28d3f2f1771d16c6f
RX(theta₁₂)
96dec0507cc241818a36c936093c478f--915db6578b8c4cc28d3f2f1771d16c6f
5bfc0329f03346dfb0b1998f6ecc8c63
RY(theta₁₆)
915db6578b8c4cc28d3f2f1771d16c6f--5bfc0329f03346dfb0b1998f6ecc8c63
b1d9562f144c43c5b5b7bd702cd692cf
RX(theta₂₀)
5bfc0329f03346dfb0b1998f6ecc8c63--b1d9562f144c43c5b5b7bd702cd692cf
b264521002914d72a6d0e58a06344c0f
b1d9562f144c43c5b5b7bd702cd692cf--b264521002914d72a6d0e58a06344c0f
2eed1b06b9d74658b2f8044b99b6076e
b264521002914d72a6d0e58a06344c0f--2eed1b06b9d74658b2f8044b99b6076e
cccd94736b274bd7960b7c162a9261a1
2eed1b06b9d74658b2f8044b99b6076e--cccd94736b274bd7960b7c162a9261a1
e363a2695c39471d95fa9251ab736008
217c4ae19dbe4aa2bf091fb4dff8a301
03a781df9b1b49b7a17796241258a264--217c4ae19dbe4aa2bf091fb4dff8a301
a563bb0cfda74f5b9b0de2c732888d29
2
993d4da1806046db82714345716f34be
RX(theta₁)
217c4ae19dbe4aa2bf091fb4dff8a301--993d4da1806046db82714345716f34be
2499c952b2624850b99018725eb016b4
RY(theta₅)
993d4da1806046db82714345716f34be--2499c952b2624850b99018725eb016b4
59a4eee851e943c9974b2cf9ef7ee151
RX(theta₉)
2499c952b2624850b99018725eb016b4--59a4eee851e943c9974b2cf9ef7ee151
a9fec30b378544c0a462bd01ca509fcd
X
59a4eee851e943c9974b2cf9ef7ee151--a9fec30b378544c0a462bd01ca509fcd
a9fec30b378544c0a462bd01ca509fcd--30f659f47efa4ebd9fb30d46d6038916
4cf2855b23fe4d42a9f66ceaa76046a4
a9fec30b378544c0a462bd01ca509fcd--4cf2855b23fe4d42a9f66ceaa76046a4
898f68360380448b994cd51f04e83463
RX(theta₁₃)
4cf2855b23fe4d42a9f66ceaa76046a4--898f68360380448b994cd51f04e83463
2b82fb9daf2b444a9d49b7923308ba59
RY(theta₁₇)
898f68360380448b994cd51f04e83463--2b82fb9daf2b444a9d49b7923308ba59
9027bf8b38bf4e6c834a2e71c1b45b6e
RX(theta₂₁)
2b82fb9daf2b444a9d49b7923308ba59--9027bf8b38bf4e6c834a2e71c1b45b6e
0395b231ac424588b35a8f7fa06aa8de
X
9027bf8b38bf4e6c834a2e71c1b45b6e--0395b231ac424588b35a8f7fa06aa8de
0395b231ac424588b35a8f7fa06aa8de--b264521002914d72a6d0e58a06344c0f
0e9f00cb16764e50a8169faaa393f789
0395b231ac424588b35a8f7fa06aa8de--0e9f00cb16764e50a8169faaa393f789
0e9f00cb16764e50a8169faaa393f789--e363a2695c39471d95fa9251ab736008
2fc6aec3961e45f4a19f17112580a235
1ff8627ae73d4daa8ef97b7fd5413445
a563bb0cfda74f5b9b0de2c732888d29--1ff8627ae73d4daa8ef97b7fd5413445
d8fc1b1188fb40299aef6e3f6679331d
3
0a13694d268649e3b6e5a991a8b0b151
RX(theta₂)
1ff8627ae73d4daa8ef97b7fd5413445--0a13694d268649e3b6e5a991a8b0b151
10dae30ce6ef4a2d879f20210cda28c8
RY(theta₆)
0a13694d268649e3b6e5a991a8b0b151--10dae30ce6ef4a2d879f20210cda28c8
05d3c9a7ab2242c0970238d0c987f26b
RX(theta₁₀)
10dae30ce6ef4a2d879f20210cda28c8--05d3c9a7ab2242c0970238d0c987f26b
83f4b21207ee481a92b883647a3f22f6
05d3c9a7ab2242c0970238d0c987f26b--83f4b21207ee481a92b883647a3f22f6
c71f958469f944a984dafb224e779398
X
83f4b21207ee481a92b883647a3f22f6--c71f958469f944a984dafb224e779398
c71f958469f944a984dafb224e779398--4cf2855b23fe4d42a9f66ceaa76046a4
55b651b1c4a54cf791f32131e24e616f
RX(theta₁₄)
c71f958469f944a984dafb224e779398--55b651b1c4a54cf791f32131e24e616f
a050786800984d1b8ba48f797b5ef111
RY(theta₁₈)
55b651b1c4a54cf791f32131e24e616f--a050786800984d1b8ba48f797b5ef111
d8496713dea249e89da60c47d67b1c5d
RX(theta₂₂)
a050786800984d1b8ba48f797b5ef111--d8496713dea249e89da60c47d67b1c5d
1dec7cde1dd94cad952f0782cc0cee5b
d8496713dea249e89da60c47d67b1c5d--1dec7cde1dd94cad952f0782cc0cee5b
29c3a5f3b81f463a976515ca74362825
X
1dec7cde1dd94cad952f0782cc0cee5b--29c3a5f3b81f463a976515ca74362825
29c3a5f3b81f463a976515ca74362825--0e9f00cb16764e50a8169faaa393f789
29c3a5f3b81f463a976515ca74362825--2fc6aec3961e45f4a19f17112580a235
cf84e52736b447158aedc289a35dfccc
915cbd73e2e848a0b2f36adf61bc1d5b
X
d8fc1b1188fb40299aef6e3f6679331d--915cbd73e2e848a0b2f36adf61bc1d5b
8748963e84f04011a861e53f09da032c
RX(theta₃)
915cbd73e2e848a0b2f36adf61bc1d5b--8748963e84f04011a861e53f09da032c
f4bdc3cf384946388489677884046e7a
RY(theta₇)
8748963e84f04011a861e53f09da032c--f4bdc3cf384946388489677884046e7a
0d95ce9b839041059829021ceabab932
RX(theta₁₁)
f4bdc3cf384946388489677884046e7a--0d95ce9b839041059829021ceabab932
a2584959d1324c17bd37a7ecdf6702df
X
0d95ce9b839041059829021ceabab932--a2584959d1324c17bd37a7ecdf6702df
a2584959d1324c17bd37a7ecdf6702df--83f4b21207ee481a92b883647a3f22f6
13d4c85b32c547a7ba604a3fb4260b4b
a2584959d1324c17bd37a7ecdf6702df--13d4c85b32c547a7ba604a3fb4260b4b
683b4d14df5d45ae8306b885f4739cca
RX(theta₁₅)
13d4c85b32c547a7ba604a3fb4260b4b--683b4d14df5d45ae8306b885f4739cca
ecd8bebd76db4942bcc02eef82ac018f
RY(theta₁₉)
683b4d14df5d45ae8306b885f4739cca--ecd8bebd76db4942bcc02eef82ac018f
f337cc8373e24817af6a1d530da62e5d
RX(theta₂₃)
ecd8bebd76db4942bcc02eef82ac018f--f337cc8373e24817af6a1d530da62e5d
20d510c941e342b2a0ae0b9c299d5443
X
f337cc8373e24817af6a1d530da62e5d--20d510c941e342b2a0ae0b9c299d5443
20d510c941e342b2a0ae0b9c299d5443--1dec7cde1dd94cad952f0782cc0cee5b
8d190481b36f4578a37392a24fac397a
20d510c941e342b2a0ae0b9c299d5443--8d190481b36f4578a37392a24fac397a
8d190481b36f4578a37392a24fac397a--cf84e52736b447158aedc289a35dfccc
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 , 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.2081+0.2344 j , -0.1377-0.1414 j , 0.0648+0.0879 j , 0.2784+0.3919 j ,
-0.3448-0.2388 j , 0.1042-0.0920 j , 0.1097-0.3815 j , 0.5086+0.0908 j ],
[ 0.1926-0.1005 j , 0.1366-0.2113 j , 0.3341+0.0283 j , 0.4666-0.0519 j ,
-0.0352-0.1661 j , 0.1113-0.1136 j , -0.5330+0.3841 j , 0.1875+0.1890 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 )
└── 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 ]] )