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.91974994-0.39225289 j 0. + 0. j 0.01293391-0.00551603 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_0f9fcb94d683434383a934ca4a9f7001
Circuit block
cluster_8e51bb90dd5e4b89aa746888fb076fc4
Prep block
def83a9958444041934e667d6e040870
0
aefd04442cb343b1beb9d14332faf0a4
def83a9958444041934e667d6e040870--aefd04442cb343b1beb9d14332faf0a4
0af18f9eea43452aa51f6d728a6653f5
1
336cb2bf82374784ac9b5bc61ac4602f
RX(theta₀)
aefd04442cb343b1beb9d14332faf0a4--336cb2bf82374784ac9b5bc61ac4602f
ac04422a47044e7781d2a85f7980f26f
RY(theta₄)
336cb2bf82374784ac9b5bc61ac4602f--ac04422a47044e7781d2a85f7980f26f
f2f2d87051d648ff8ebc2e928343b4ad
RX(theta₈)
ac04422a47044e7781d2a85f7980f26f--f2f2d87051d648ff8ebc2e928343b4ad
05296305b30342b6a7e1042a9f315193
f2f2d87051d648ff8ebc2e928343b4ad--05296305b30342b6a7e1042a9f315193
2285ca5e91f9420cb6dd82f86a3900c5
05296305b30342b6a7e1042a9f315193--2285ca5e91f9420cb6dd82f86a3900c5
cd45c2f45e55490c82341829f29b29be
RX(theta₁₂)
2285ca5e91f9420cb6dd82f86a3900c5--cd45c2f45e55490c82341829f29b29be
a17e705596b4478cb30d3ad3b32df474
RY(theta₁₆)
cd45c2f45e55490c82341829f29b29be--a17e705596b4478cb30d3ad3b32df474
3242aefd2d8644df8dc383e84c97a742
RX(theta₂₀)
a17e705596b4478cb30d3ad3b32df474--3242aefd2d8644df8dc383e84c97a742
462b19fd00bb4795abaac184e33582cd
3242aefd2d8644df8dc383e84c97a742--462b19fd00bb4795abaac184e33582cd
66c5d4f05b6c47d9b7a0f7673d3c0599
462b19fd00bb4795abaac184e33582cd--66c5d4f05b6c47d9b7a0f7673d3c0599
673730a6b26c4ecfb618b787a511475e
66c5d4f05b6c47d9b7a0f7673d3c0599--673730a6b26c4ecfb618b787a511475e
9f540c8cb6be43b4ae68eff0bb58ef9d
10691efaa3f849f08e605c2b2fdc91aa
0af18f9eea43452aa51f6d728a6653f5--10691efaa3f849f08e605c2b2fdc91aa
ff761c52709b45588c89c64a71d1a1cc
2
e13dc3d61e6e428795b0931e59278aa3
RX(theta₁)
10691efaa3f849f08e605c2b2fdc91aa--e13dc3d61e6e428795b0931e59278aa3
b7a37caa504a493fba487b157213cc75
RY(theta₅)
e13dc3d61e6e428795b0931e59278aa3--b7a37caa504a493fba487b157213cc75
ca5fb5df364249138af514b3d6c9be47
RX(theta₉)
b7a37caa504a493fba487b157213cc75--ca5fb5df364249138af514b3d6c9be47
c2d46148f8484e448125340be715e32e
X
ca5fb5df364249138af514b3d6c9be47--c2d46148f8484e448125340be715e32e
c2d46148f8484e448125340be715e32e--05296305b30342b6a7e1042a9f315193
4d832d65f12844789a398485cbdefea7
c2d46148f8484e448125340be715e32e--4d832d65f12844789a398485cbdefea7
b14e48983e144ebea7c2bc14b27f0b7f
RX(theta₁₃)
4d832d65f12844789a398485cbdefea7--b14e48983e144ebea7c2bc14b27f0b7f
b4fda62301b440009f2bca586dd652fe
RY(theta₁₇)
b14e48983e144ebea7c2bc14b27f0b7f--b4fda62301b440009f2bca586dd652fe
8f1be86e94da45b28e5fc39db0f6d42d
RX(theta₂₁)
b4fda62301b440009f2bca586dd652fe--8f1be86e94da45b28e5fc39db0f6d42d
c908c0b10aba4ecc96670992a56de155
X
8f1be86e94da45b28e5fc39db0f6d42d--c908c0b10aba4ecc96670992a56de155
c908c0b10aba4ecc96670992a56de155--462b19fd00bb4795abaac184e33582cd
aed834dd3a384709afcebebc4da36481
c908c0b10aba4ecc96670992a56de155--aed834dd3a384709afcebebc4da36481
aed834dd3a384709afcebebc4da36481--9f540c8cb6be43b4ae68eff0bb58ef9d
ab626f3cf9d745c9a24aa553317a0b39
1c2c2b959f294be08668096e37995044
ff761c52709b45588c89c64a71d1a1cc--1c2c2b959f294be08668096e37995044
abb5e327f36f416baecdf2c9adaf623a
3
18838a6084834f01963615b7103fe548
RX(theta₂)
1c2c2b959f294be08668096e37995044--18838a6084834f01963615b7103fe548
0473525638954690a77e7153cc53fe11
RY(theta₆)
18838a6084834f01963615b7103fe548--0473525638954690a77e7153cc53fe11
c8af770009ba4017a979a8cc4de215b8
RX(theta₁₀)
0473525638954690a77e7153cc53fe11--c8af770009ba4017a979a8cc4de215b8
00aeead939aa4dc6ba9f1319586957ae
c8af770009ba4017a979a8cc4de215b8--00aeead939aa4dc6ba9f1319586957ae
5d0aec55d33b4369b6bbbff9d7766259
X
00aeead939aa4dc6ba9f1319586957ae--5d0aec55d33b4369b6bbbff9d7766259
5d0aec55d33b4369b6bbbff9d7766259--4d832d65f12844789a398485cbdefea7
08063425ae5249fb96d32f0cc501728b
RX(theta₁₄)
5d0aec55d33b4369b6bbbff9d7766259--08063425ae5249fb96d32f0cc501728b
f31317743cfe409ca215cae5def4f44d
RY(theta₁₈)
08063425ae5249fb96d32f0cc501728b--f31317743cfe409ca215cae5def4f44d
8db8d4cba26f4872b4db9396591fd713
RX(theta₂₂)
f31317743cfe409ca215cae5def4f44d--8db8d4cba26f4872b4db9396591fd713
25cbcacdede14669b89ec9d1f99cb58b
8db8d4cba26f4872b4db9396591fd713--25cbcacdede14669b89ec9d1f99cb58b
4f82c54156d14194be9c8c44b7bb7eda
X
25cbcacdede14669b89ec9d1f99cb58b--4f82c54156d14194be9c8c44b7bb7eda
4f82c54156d14194be9c8c44b7bb7eda--aed834dd3a384709afcebebc4da36481
4f82c54156d14194be9c8c44b7bb7eda--ab626f3cf9d745c9a24aa553317a0b39
aeaaf9d65dd342cda25dcd0402fb2b57
5b219d3ecdee4e35b9e0a43f45198f9f
X
abb5e327f36f416baecdf2c9adaf623a--5b219d3ecdee4e35b9e0a43f45198f9f
777ad85679b24c0298db177072d214b3
RX(theta₃)
5b219d3ecdee4e35b9e0a43f45198f9f--777ad85679b24c0298db177072d214b3
3d80ee8251d043538df5c3708c385735
RY(theta₇)
777ad85679b24c0298db177072d214b3--3d80ee8251d043538df5c3708c385735
dae3d5931f134b78a365d2ce991e2db5
RX(theta₁₁)
3d80ee8251d043538df5c3708c385735--dae3d5931f134b78a365d2ce991e2db5
914b8086b3a44850825039d3eefb645a
X
dae3d5931f134b78a365d2ce991e2db5--914b8086b3a44850825039d3eefb645a
914b8086b3a44850825039d3eefb645a--00aeead939aa4dc6ba9f1319586957ae
3250cd298581413eb04a0e4d4845ff07
914b8086b3a44850825039d3eefb645a--3250cd298581413eb04a0e4d4845ff07
9d2812ea6756483495beaf12f3516e78
RX(theta₁₅)
3250cd298581413eb04a0e4d4845ff07--9d2812ea6756483495beaf12f3516e78
8df048252da344dfa23c34f689af4b0d
RY(theta₁₉)
9d2812ea6756483495beaf12f3516e78--8df048252da344dfa23c34f689af4b0d
7a40583889044f2e8891534b2476af41
RX(theta₂₃)
8df048252da344dfa23c34f689af4b0d--7a40583889044f2e8891534b2476af41
d77a444144354e3e973455abc9c1dd7d
X
7a40583889044f2e8891534b2476af41--d77a444144354e3e973455abc9c1dd7d
d77a444144354e3e973455abc9c1dd7d--25cbcacdede14669b89ec9d1f99cb58b
c899f7f2b1bc4f4787b1540f19922818
d77a444144354e3e973455abc9c1dd7d--c899f7f2b1bc4f4787b1540f19922818
c899f7f2b1bc4f4787b1540f19922818--aeaaf9d65dd342cda25dcd0402fb2b57
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 , 0.+0. j , 0.+0. j , 1.+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.2942+0.3484 j , -0.1539-0.0542 j , 0.1777-0.0318 j , 0.0127+0.6092 j ,
-0.3757+0.0192 j , 0.1158-0.3238 j , -0.0533+0.0866 j , 0.2110-0.2165 j ],
[ 0.1984+0.3044 j , 0.2583-0.1425 j , 0.3276+0.0171 j , 0.4575+0.0635 j ,
-0.0397+0.1364 j , 0.0219-0.2100 j , -0.5043+0.1534 j , -0.1100+0.3245 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 ]] )