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.60466101+0.58392443 j 0. + 0. j 0.37628597-0.3896488 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_f54224870bd04f7f87572fcf5c078fa3
Circuit block
cluster_9c1a63de8e9f47c0b1e73b710ed3f5ee
Prep block
d91c43f637b645af8e5d201857cb9444
0
84e34534809145479dc83a0c13e9c470
d91c43f637b645af8e5d201857cb9444--84e34534809145479dc83a0c13e9c470
e8ddd97055d84827a1a04531fb3fc6c4
1
e401cbe58a1642ac8b758ec224d315c8
RX(theta₀)
84e34534809145479dc83a0c13e9c470--e401cbe58a1642ac8b758ec224d315c8
97800fd73efc44b8a19c00dcdeb252bc
RY(theta₄)
e401cbe58a1642ac8b758ec224d315c8--97800fd73efc44b8a19c00dcdeb252bc
069dc93bbee542a9a83007726f9c9068
RX(theta₈)
97800fd73efc44b8a19c00dcdeb252bc--069dc93bbee542a9a83007726f9c9068
693edc30e3dd49b98644a97c1175eadb
069dc93bbee542a9a83007726f9c9068--693edc30e3dd49b98644a97c1175eadb
68989a7f628941e290c290659af58732
693edc30e3dd49b98644a97c1175eadb--68989a7f628941e290c290659af58732
c786c66871a242399ad52ff1c4b3a0ce
RX(theta₁₂)
68989a7f628941e290c290659af58732--c786c66871a242399ad52ff1c4b3a0ce
be52efadc13341a6bd9b5b133760ad42
RY(theta₁₆)
c786c66871a242399ad52ff1c4b3a0ce--be52efadc13341a6bd9b5b133760ad42
a44494efaf554c9582fab7bf83ab6523
RX(theta₂₀)
be52efadc13341a6bd9b5b133760ad42--a44494efaf554c9582fab7bf83ab6523
dbe4e4f26eb3442b96964bf934ce1009
a44494efaf554c9582fab7bf83ab6523--dbe4e4f26eb3442b96964bf934ce1009
f4fe0a8ad0c34e209be787a6f31aab9d
dbe4e4f26eb3442b96964bf934ce1009--f4fe0a8ad0c34e209be787a6f31aab9d
2105a2dba9214f008a9390ae4030366e
f4fe0a8ad0c34e209be787a6f31aab9d--2105a2dba9214f008a9390ae4030366e
ef9ee374eeac41e293528da19a8fd39b
f4888afd8b85453e925a4004767a98a1
e8ddd97055d84827a1a04531fb3fc6c4--f4888afd8b85453e925a4004767a98a1
922017bfc3a849fab1738893c8169596
2
7d4ecc189f93445799bb5670e6ea079d
RX(theta₁)
f4888afd8b85453e925a4004767a98a1--7d4ecc189f93445799bb5670e6ea079d
d8193a4aa5d947b29b1230ffc991a387
RY(theta₅)
7d4ecc189f93445799bb5670e6ea079d--d8193a4aa5d947b29b1230ffc991a387
834c0299476241f9a99d40e181cfcc53
RX(theta₉)
d8193a4aa5d947b29b1230ffc991a387--834c0299476241f9a99d40e181cfcc53
1e9521dfeb2c41a0b28023aa0d0a2bea
X
834c0299476241f9a99d40e181cfcc53--1e9521dfeb2c41a0b28023aa0d0a2bea
1e9521dfeb2c41a0b28023aa0d0a2bea--693edc30e3dd49b98644a97c1175eadb
6f32e04c735747c5adf91c52e5d73f13
1e9521dfeb2c41a0b28023aa0d0a2bea--6f32e04c735747c5adf91c52e5d73f13
3f4c497a57084c81acf0cdffaee0c042
RX(theta₁₃)
6f32e04c735747c5adf91c52e5d73f13--3f4c497a57084c81acf0cdffaee0c042
fa73e4ff37224824a862928617c0db5b
RY(theta₁₇)
3f4c497a57084c81acf0cdffaee0c042--fa73e4ff37224824a862928617c0db5b
7e6ec6eb3670488aa1d34a3ae61f7bec
RX(theta₂₁)
fa73e4ff37224824a862928617c0db5b--7e6ec6eb3670488aa1d34a3ae61f7bec
75ce104e7e434d4abc7d72cd1498c442
X
7e6ec6eb3670488aa1d34a3ae61f7bec--75ce104e7e434d4abc7d72cd1498c442
75ce104e7e434d4abc7d72cd1498c442--dbe4e4f26eb3442b96964bf934ce1009
29a9b1104a8f4265b5d613181b3c7206
75ce104e7e434d4abc7d72cd1498c442--29a9b1104a8f4265b5d613181b3c7206
29a9b1104a8f4265b5d613181b3c7206--ef9ee374eeac41e293528da19a8fd39b
29d1b959ed7b464986dcd0f68c7f83f2
4e525f2915124b73bb5b6a6778ba05b0
922017bfc3a849fab1738893c8169596--4e525f2915124b73bb5b6a6778ba05b0
3cf7b2c73cf54462acfbfd2521c5aa80
3
51ed73c2345c45c6a238b0e0b1ef2d3a
RX(theta₂)
4e525f2915124b73bb5b6a6778ba05b0--51ed73c2345c45c6a238b0e0b1ef2d3a
b34eb7cf3a4e484697829ae9b0877781
RY(theta₆)
51ed73c2345c45c6a238b0e0b1ef2d3a--b34eb7cf3a4e484697829ae9b0877781
5f65a54657834dafa3b7d1c2f96fb80d
RX(theta₁₀)
b34eb7cf3a4e484697829ae9b0877781--5f65a54657834dafa3b7d1c2f96fb80d
1dca8ecaecd243dc8c225d9266091169
5f65a54657834dafa3b7d1c2f96fb80d--1dca8ecaecd243dc8c225d9266091169
e310ab78af0f434384b6bbc15baa4d5b
X
1dca8ecaecd243dc8c225d9266091169--e310ab78af0f434384b6bbc15baa4d5b
e310ab78af0f434384b6bbc15baa4d5b--6f32e04c735747c5adf91c52e5d73f13
8fb8655b1b4d4555ae3b7e155151c684
RX(theta₁₄)
e310ab78af0f434384b6bbc15baa4d5b--8fb8655b1b4d4555ae3b7e155151c684
af5ee18a03f641b99d12e777a00c2caf
RY(theta₁₈)
8fb8655b1b4d4555ae3b7e155151c684--af5ee18a03f641b99d12e777a00c2caf
3982992647354d44b21b1dcf5cb73ea3
RX(theta₂₂)
af5ee18a03f641b99d12e777a00c2caf--3982992647354d44b21b1dcf5cb73ea3
b91305b1b4494960afc6811432962f2c
3982992647354d44b21b1dcf5cb73ea3--b91305b1b4494960afc6811432962f2c
e589b979ebef43f18e9957cbe659e2bc
X
b91305b1b4494960afc6811432962f2c--e589b979ebef43f18e9957cbe659e2bc
e589b979ebef43f18e9957cbe659e2bc--29a9b1104a8f4265b5d613181b3c7206
e589b979ebef43f18e9957cbe659e2bc--29d1b959ed7b464986dcd0f68c7f83f2
58fcbc54229e427280c639cca1827244
33dbd89185e848f6972d4bfef948a3d5
X
3cf7b2c73cf54462acfbfd2521c5aa80--33dbd89185e848f6972d4bfef948a3d5
66f79e6a2c524ae6a8a92500566ff7d7
RX(theta₃)
33dbd89185e848f6972d4bfef948a3d5--66f79e6a2c524ae6a8a92500566ff7d7
8823849a2b07474ebac332d08d0114ce
RY(theta₇)
66f79e6a2c524ae6a8a92500566ff7d7--8823849a2b07474ebac332d08d0114ce
2c28f7e81a46438d94f6a20db83dc1b0
RX(theta₁₁)
8823849a2b07474ebac332d08d0114ce--2c28f7e81a46438d94f6a20db83dc1b0
897b00eedaed4ee7b98cbb761cbee288
X
2c28f7e81a46438d94f6a20db83dc1b0--897b00eedaed4ee7b98cbb761cbee288
897b00eedaed4ee7b98cbb761cbee288--1dca8ecaecd243dc8c225d9266091169
3ba696b82c4740f9a20a5c8d650e2ec6
897b00eedaed4ee7b98cbb761cbee288--3ba696b82c4740f9a20a5c8d650e2ec6
12494a9cc02e49ff9f8e177fd998e30a
RX(theta₁₅)
3ba696b82c4740f9a20a5c8d650e2ec6--12494a9cc02e49ff9f8e177fd998e30a
efeb296cf7db42bfa09366b784063df7
RY(theta₁₉)
12494a9cc02e49ff9f8e177fd998e30a--efeb296cf7db42bfa09366b784063df7
893d9379973041c381e2d0021a6aefc4
RX(theta₂₃)
efeb296cf7db42bfa09366b784063df7--893d9379973041c381e2d0021a6aefc4
0726e73ced9f432d85ecac2bed1bc20a
X
893d9379973041c381e2d0021a6aefc4--0726e73ced9f432d85ecac2bed1bc20a
0726e73ced9f432d85ecac2bed1bc20a--b91305b1b4494960afc6811432962f2c
5156b2a222974b3b8465ae75f40f95ef
0726e73ced9f432d85ecac2bed1bc20a--5156b2a222974b3b8465ae75f40f95ef
5156b2a222974b3b8465ae75f40f95ef--58fcbc54229e427280c639cca1827244
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 , 1.+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 ]] )
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.2561-0.1032 j , 0.0494+0.0587 j , 0.3258+0.1880 j , 0.2518-0.0606 j ,
-0.3047-0.3365 j , -0.0829+0.4560 j , 0.2562+0.1226 j , -0.1817+0.4180 j ],
[ 0.3139+0.4935 j , -0.2357+0.3002 j , 0.4257+0.0696 j , 0.0326+0.0448 j ,
0.1226-0.1125 j , -0.2873+0.1443 j , -0.1797-0.3972 j , -0.0041-0.0452 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 )
├── I( 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 ]] )