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.89529433+0.33257402 j 0.10320625-0.27783278 j 0. + 0. 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_c6e3d92a428c4d56b6481f1926fc0dec
Circuit block
cluster_f37fe3e7a62d4269a2bafb39e3b67b72
Prep block
3ba56a1b3b294fcc89834314ad1068d7
0
eaa8c1006bd44622b3e2dcccbe2ebbb7
3ba56a1b3b294fcc89834314ad1068d7--eaa8c1006bd44622b3e2dcccbe2ebbb7
bbab1633be104ecba0db3b14c334999d
1
4ea81152a7e3479eb2b56f5b9ec87a35
RX(theta₀)
eaa8c1006bd44622b3e2dcccbe2ebbb7--4ea81152a7e3479eb2b56f5b9ec87a35
e196f9d88c3f46a4ba80ed4878ed05bd
RY(theta₄)
4ea81152a7e3479eb2b56f5b9ec87a35--e196f9d88c3f46a4ba80ed4878ed05bd
57390375b81b4d43a5788590be49edf2
RX(theta₈)
e196f9d88c3f46a4ba80ed4878ed05bd--57390375b81b4d43a5788590be49edf2
8401ac79550b45e9bcc8ecb50fcd440b
57390375b81b4d43a5788590be49edf2--8401ac79550b45e9bcc8ecb50fcd440b
c229a8c831b043c5b4ffd74e56c25bfb
8401ac79550b45e9bcc8ecb50fcd440b--c229a8c831b043c5b4ffd74e56c25bfb
4f103a809d004984a8c8ae271d21efe6
RX(theta₁₂)
c229a8c831b043c5b4ffd74e56c25bfb--4f103a809d004984a8c8ae271d21efe6
3dea88a50caf48beacb6de940b95f6ea
RY(theta₁₆)
4f103a809d004984a8c8ae271d21efe6--3dea88a50caf48beacb6de940b95f6ea
2e57c68de40246759a49401973ee39ae
RX(theta₂₀)
3dea88a50caf48beacb6de940b95f6ea--2e57c68de40246759a49401973ee39ae
4ef6fdda9bec4305811e94eedcf1db82
2e57c68de40246759a49401973ee39ae--4ef6fdda9bec4305811e94eedcf1db82
5ac0a13558f64e9dad8358e4019cb5e9
4ef6fdda9bec4305811e94eedcf1db82--5ac0a13558f64e9dad8358e4019cb5e9
1bdf2c04e5704802be801facead05510
5ac0a13558f64e9dad8358e4019cb5e9--1bdf2c04e5704802be801facead05510
261b6373776c46a2884d481df5ef664a
0f2a64550608432b9e05d0da929941bd
bbab1633be104ecba0db3b14c334999d--0f2a64550608432b9e05d0da929941bd
a7fd7bfba5a643b7820d35bc345013cd
2
07fbe7fbbaf540638cb82f091cb16ebd
RX(theta₁)
0f2a64550608432b9e05d0da929941bd--07fbe7fbbaf540638cb82f091cb16ebd
1ad9c0fa876340a59cfcd571e0560359
RY(theta₅)
07fbe7fbbaf540638cb82f091cb16ebd--1ad9c0fa876340a59cfcd571e0560359
fc0094f8709d4dbfb9b0f538449c6d22
RX(theta₉)
1ad9c0fa876340a59cfcd571e0560359--fc0094f8709d4dbfb9b0f538449c6d22
c221dccb773a4afaaabbe613c126305e
X
fc0094f8709d4dbfb9b0f538449c6d22--c221dccb773a4afaaabbe613c126305e
c221dccb773a4afaaabbe613c126305e--8401ac79550b45e9bcc8ecb50fcd440b
3e2b7fe4d486438baa79b733d5d226a3
c221dccb773a4afaaabbe613c126305e--3e2b7fe4d486438baa79b733d5d226a3
85b073a8df784cffb0d35eb2e13a6cb1
RX(theta₁₃)
3e2b7fe4d486438baa79b733d5d226a3--85b073a8df784cffb0d35eb2e13a6cb1
35cd634b77c441828048768a72c8f3e6
RY(theta₁₇)
85b073a8df784cffb0d35eb2e13a6cb1--35cd634b77c441828048768a72c8f3e6
6e035472dfad4f84a5dda612c71fa5d0
RX(theta₂₁)
35cd634b77c441828048768a72c8f3e6--6e035472dfad4f84a5dda612c71fa5d0
8fe20ddd22eb40bdba4721a96195a0bc
X
6e035472dfad4f84a5dda612c71fa5d0--8fe20ddd22eb40bdba4721a96195a0bc
8fe20ddd22eb40bdba4721a96195a0bc--4ef6fdda9bec4305811e94eedcf1db82
54ace213bed74eaf9fc26c45452a3cf0
8fe20ddd22eb40bdba4721a96195a0bc--54ace213bed74eaf9fc26c45452a3cf0
54ace213bed74eaf9fc26c45452a3cf0--261b6373776c46a2884d481df5ef664a
cf76aa06b6c44dbaa6e12e0dfcfbf188
63d9cc8f71e94af08c19f4132f587955
a7fd7bfba5a643b7820d35bc345013cd--63d9cc8f71e94af08c19f4132f587955
5a408b691bcd4af1830850629a7edfba
3
2a36b9ca00d8439e893bd263e0b598e7
RX(theta₂)
63d9cc8f71e94af08c19f4132f587955--2a36b9ca00d8439e893bd263e0b598e7
183febb7cc434a4fbcfc8b4433a5d81b
RY(theta₆)
2a36b9ca00d8439e893bd263e0b598e7--183febb7cc434a4fbcfc8b4433a5d81b
b71e451c09504b3ea226b8792d50ba2c
RX(theta₁₀)
183febb7cc434a4fbcfc8b4433a5d81b--b71e451c09504b3ea226b8792d50ba2c
18ff83dc2fad41cf886470277a32461a
b71e451c09504b3ea226b8792d50ba2c--18ff83dc2fad41cf886470277a32461a
bbb41dd3276248eda2d1059aebd02395
X
18ff83dc2fad41cf886470277a32461a--bbb41dd3276248eda2d1059aebd02395
bbb41dd3276248eda2d1059aebd02395--3e2b7fe4d486438baa79b733d5d226a3
1fa55d3af5b64d0eb96f3d181e325515
RX(theta₁₄)
bbb41dd3276248eda2d1059aebd02395--1fa55d3af5b64d0eb96f3d181e325515
b3c08827b18848d5a959f8f00a91f1fc
RY(theta₁₈)
1fa55d3af5b64d0eb96f3d181e325515--b3c08827b18848d5a959f8f00a91f1fc
9b876644176b4fe590012c200b8b4ff8
RX(theta₂₂)
b3c08827b18848d5a959f8f00a91f1fc--9b876644176b4fe590012c200b8b4ff8
6a6e014fed964e0d85d5d16ca631309b
9b876644176b4fe590012c200b8b4ff8--6a6e014fed964e0d85d5d16ca631309b
73453fcf3d98488ba0cc4cfccd16c66a
X
6a6e014fed964e0d85d5d16ca631309b--73453fcf3d98488ba0cc4cfccd16c66a
73453fcf3d98488ba0cc4cfccd16c66a--54ace213bed74eaf9fc26c45452a3cf0
73453fcf3d98488ba0cc4cfccd16c66a--cf76aa06b6c44dbaa6e12e0dfcfbf188
526c12ae59444b0aaafc2efa8e536a8a
5522c16a739242a7a6594ae9493c2a25
X
5a408b691bcd4af1830850629a7edfba--5522c16a739242a7a6594ae9493c2a25
f1ff059629ce4f8cb921af7c3f747fab
RX(theta₃)
5522c16a739242a7a6594ae9493c2a25--f1ff059629ce4f8cb921af7c3f747fab
be8074aa56174efc92adc934dc638625
RY(theta₇)
f1ff059629ce4f8cb921af7c3f747fab--be8074aa56174efc92adc934dc638625
d237be3dde094f278414953667cfbbc6
RX(theta₁₁)
be8074aa56174efc92adc934dc638625--d237be3dde094f278414953667cfbbc6
14ac4c22757e4b78b7204b471cdcffbe
X
d237be3dde094f278414953667cfbbc6--14ac4c22757e4b78b7204b471cdcffbe
14ac4c22757e4b78b7204b471cdcffbe--18ff83dc2fad41cf886470277a32461a
bde2eb7e3cff47239e8835cb9e3d0bd8
14ac4c22757e4b78b7204b471cdcffbe--bde2eb7e3cff47239e8835cb9e3d0bd8
a759e6d806954247a3d28f81df203599
RX(theta₁₅)
bde2eb7e3cff47239e8835cb9e3d0bd8--a759e6d806954247a3d28f81df203599
86337e3702c64a979c31762d695e0a8e
RY(theta₁₉)
a759e6d806954247a3d28f81df203599--86337e3702c64a979c31762d695e0a8e
c17ecece75a24510a47e853f8ae0105e
RX(theta₂₃)
86337e3702c64a979c31762d695e0a8e--c17ecece75a24510a47e853f8ae0105e
42e4874bd64c41c7a8c71bc084a72e71
X
c17ecece75a24510a47e853f8ae0105e--42e4874bd64c41c7a8c71bc084a72e71
42e4874bd64c41c7a8c71bc084a72e71--6a6e014fed964e0d85d5d16ca631309b
f5661f5ae8984ef99d5ceee8f367908d
42e4874bd64c41c7a8c71bc084a72e71--f5661f5ae8984ef99d5ceee8f367908d
f5661f5ae8984ef99d5ceee8f367908d--526c12ae59444b0aaafc2efa8e536a8a
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 , 1.+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 ]] )
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.1413-0.0314 j , 0.4271+0.0558 j , 0.1211-0.0650 j , -0.2887-0.3458 j ,
0.1520-0.5908 j , -0.2196-0.1824 j , 0.0992-0.2272 j , 0.2243+0.0795 j ],
[ 0.3506+0.1673 j , 0.0850-0.2147 j , -0.0631+0.6737 j , 0.0306+0.2123 j ,
0.3492+0.2833 j , 0.0531-0.1610 j , 0.1590-0.0134 j , 0.1670+0.0875 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 )
├── X( 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 ]] )