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.98170357+0.08698887 j 0. + 0. j 0.1687232 + 0.01495058 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_5d5137ea88c945609174d4b57b38e158
Circuit block
cluster_44145603f5744d6bacb0b968ce4306bc
Prep block
41811288d5e5457c8870e370b9087a4f
0
e546d14b248a4c7a929949c3526b5d91
41811288d5e5457c8870e370b9087a4f--e546d14b248a4c7a929949c3526b5d91
57775cc8925146dfacbd35e93865bcad
1
1c0a67be526349e5a199d0d899276cde
RX(theta₀)
e546d14b248a4c7a929949c3526b5d91--1c0a67be526349e5a199d0d899276cde
e5d3d09977e249b587f7629fcece5d8c
RY(theta₄)
1c0a67be526349e5a199d0d899276cde--e5d3d09977e249b587f7629fcece5d8c
6338565553f34ddfaebb0ccb2214f124
RX(theta₈)
e5d3d09977e249b587f7629fcece5d8c--6338565553f34ddfaebb0ccb2214f124
5251d2075ff84fc9a1aa8d6bc55bbed1
6338565553f34ddfaebb0ccb2214f124--5251d2075ff84fc9a1aa8d6bc55bbed1
7ece6703b1574c00929f66e3826f9eca
5251d2075ff84fc9a1aa8d6bc55bbed1--7ece6703b1574c00929f66e3826f9eca
4f43f216b3804f08b7e2c8e184fd9948
RX(theta₁₂)
7ece6703b1574c00929f66e3826f9eca--4f43f216b3804f08b7e2c8e184fd9948
ef9c7a38f8ab46478dfe946b1e7ba4c5
RY(theta₁₆)
4f43f216b3804f08b7e2c8e184fd9948--ef9c7a38f8ab46478dfe946b1e7ba4c5
e9412bf881fd4ffb846ddd070bdc2b1e
RX(theta₂₀)
ef9c7a38f8ab46478dfe946b1e7ba4c5--e9412bf881fd4ffb846ddd070bdc2b1e
58e4909119da4121929d7258dd8303b3
e9412bf881fd4ffb846ddd070bdc2b1e--58e4909119da4121929d7258dd8303b3
7b03e0881a62469ea7b0f40b5fec6b58
58e4909119da4121929d7258dd8303b3--7b03e0881a62469ea7b0f40b5fec6b58
0cd8284f2bed46e797d14eda8f6fd484
7b03e0881a62469ea7b0f40b5fec6b58--0cd8284f2bed46e797d14eda8f6fd484
f4798ab4f6354eafb48c675a122c0417
36f14122809d4476af30bdbb712d8834
57775cc8925146dfacbd35e93865bcad--36f14122809d4476af30bdbb712d8834
67e0447692d04c71ac987a064c0df2a1
2
92e5e097ef3147e8936da67100bdc877
RX(theta₁)
36f14122809d4476af30bdbb712d8834--92e5e097ef3147e8936da67100bdc877
d22e1081aa60427ca71fbf666f3e0b0d
RY(theta₅)
92e5e097ef3147e8936da67100bdc877--d22e1081aa60427ca71fbf666f3e0b0d
06ac25fa8db1461c9d8a0e706bd76934
RX(theta₉)
d22e1081aa60427ca71fbf666f3e0b0d--06ac25fa8db1461c9d8a0e706bd76934
c4597c76ca1f484a8c331fd86cd0fd11
X
06ac25fa8db1461c9d8a0e706bd76934--c4597c76ca1f484a8c331fd86cd0fd11
c4597c76ca1f484a8c331fd86cd0fd11--5251d2075ff84fc9a1aa8d6bc55bbed1
6c458c6c0f024c7ca764a3cdb623d132
c4597c76ca1f484a8c331fd86cd0fd11--6c458c6c0f024c7ca764a3cdb623d132
05c5da3b85ef4a1f8d48461098089211
RX(theta₁₃)
6c458c6c0f024c7ca764a3cdb623d132--05c5da3b85ef4a1f8d48461098089211
b6a25877a3ee42b1926ccdfd55e654e1
RY(theta₁₇)
05c5da3b85ef4a1f8d48461098089211--b6a25877a3ee42b1926ccdfd55e654e1
ad1cb920ea244036b50e085e35112b7b
RX(theta₂₁)
b6a25877a3ee42b1926ccdfd55e654e1--ad1cb920ea244036b50e085e35112b7b
a3e3262bbab9435688c040fa9b3d981f
X
ad1cb920ea244036b50e085e35112b7b--a3e3262bbab9435688c040fa9b3d981f
a3e3262bbab9435688c040fa9b3d981f--58e4909119da4121929d7258dd8303b3
1bad337e8e55418bb015f886fce87070
a3e3262bbab9435688c040fa9b3d981f--1bad337e8e55418bb015f886fce87070
1bad337e8e55418bb015f886fce87070--f4798ab4f6354eafb48c675a122c0417
913bd6c6a3b64022bca9d70c4c97a190
e8b9892f7118475a9fad60d13af4e95f
67e0447692d04c71ac987a064c0df2a1--e8b9892f7118475a9fad60d13af4e95f
a89eeca7738244d4b6ea58efe3ab1059
3
a0f7a3cad40f47ebbe3a5017763a3b51
RX(theta₂)
e8b9892f7118475a9fad60d13af4e95f--a0f7a3cad40f47ebbe3a5017763a3b51
4ab5ecde90694bd39336e7352ece0fd1
RY(theta₆)
a0f7a3cad40f47ebbe3a5017763a3b51--4ab5ecde90694bd39336e7352ece0fd1
08b6cf88a1504116a33a2cfd24da4dcc
RX(theta₁₀)
4ab5ecde90694bd39336e7352ece0fd1--08b6cf88a1504116a33a2cfd24da4dcc
f9d2ed3576cf40a1ac9df1fb09438748
08b6cf88a1504116a33a2cfd24da4dcc--f9d2ed3576cf40a1ac9df1fb09438748
e67453d656e24ec1aecec8e4484b9b05
X
f9d2ed3576cf40a1ac9df1fb09438748--e67453d656e24ec1aecec8e4484b9b05
e67453d656e24ec1aecec8e4484b9b05--6c458c6c0f024c7ca764a3cdb623d132
3bbb139c8cfd4cfe8b42fa45e4807ff3
RX(theta₁₄)
e67453d656e24ec1aecec8e4484b9b05--3bbb139c8cfd4cfe8b42fa45e4807ff3
130d65557d494ae5bf5876c55b3b79ce
RY(theta₁₈)
3bbb139c8cfd4cfe8b42fa45e4807ff3--130d65557d494ae5bf5876c55b3b79ce
04c15e674abf41dba8b989d93169636d
RX(theta₂₂)
130d65557d494ae5bf5876c55b3b79ce--04c15e674abf41dba8b989d93169636d
0f736a45a8794788b4676a83c3672ed0
04c15e674abf41dba8b989d93169636d--0f736a45a8794788b4676a83c3672ed0
e2beb9e61f824881a88387ebe46b1fc0
X
0f736a45a8794788b4676a83c3672ed0--e2beb9e61f824881a88387ebe46b1fc0
e2beb9e61f824881a88387ebe46b1fc0--1bad337e8e55418bb015f886fce87070
e2beb9e61f824881a88387ebe46b1fc0--913bd6c6a3b64022bca9d70c4c97a190
4b476347f82a47d98e266ca76b1b71de
8e460e875ac242938260b8bc4a7b4191
X
a89eeca7738244d4b6ea58efe3ab1059--8e460e875ac242938260b8bc4a7b4191
53eff2090f564851bfd0d7b72d6bbde1
RX(theta₃)
8e460e875ac242938260b8bc4a7b4191--53eff2090f564851bfd0d7b72d6bbde1
c3df0817cf944cfcb8ddeaa7c34aacc9
RY(theta₇)
53eff2090f564851bfd0d7b72d6bbde1--c3df0817cf944cfcb8ddeaa7c34aacc9
b7ae042fcbba43669b1b965479081295
RX(theta₁₁)
c3df0817cf944cfcb8ddeaa7c34aacc9--b7ae042fcbba43669b1b965479081295
0eb9219c84004489913d949a1ce3e038
X
b7ae042fcbba43669b1b965479081295--0eb9219c84004489913d949a1ce3e038
0eb9219c84004489913d949a1ce3e038--f9d2ed3576cf40a1ac9df1fb09438748
f7cff9b28c1f45219fbd805fbf6bc487
0eb9219c84004489913d949a1ce3e038--f7cff9b28c1f45219fbd805fbf6bc487
651ecc4ce50a41678a1d3e06671e803e
RX(theta₁₅)
f7cff9b28c1f45219fbd805fbf6bc487--651ecc4ce50a41678a1d3e06671e803e
81ce5d3b4e1f4d3aaace34f9a3cdfc12
RY(theta₁₉)
651ecc4ce50a41678a1d3e06671e803e--81ce5d3b4e1f4d3aaace34f9a3cdfc12
071d42f81610422fb04469e648b3d4f1
RX(theta₂₃)
81ce5d3b4e1f4d3aaace34f9a3cdfc12--071d42f81610422fb04469e648b3d4f1
f0c284a65392415aae605215fe845898
X
071d42f81610422fb04469e648b3d4f1--f0c284a65392415aae605215fe845898
f0c284a65392415aae605215fe845898--0f736a45a8794788b4676a83c3672ed0
565f6bf77bf34a6f939d76cb68855efd
f0c284a65392415aae605215fe845898--565f6bf77bf34a6f939d76cb68855efd
565f6bf77bf34a6f939d76cb68855efd--4b476347f82a47d98e266ca76b1b71de
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 , 0.+0. j , 1.+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.3367+0.1492 j , -0.2387-0.4529 j , -0.0397+0.1336 j , -0.1125+0.5659 j ,
-0.0703-0.0669 j , -0.0778+0.2793 j , 0.3534-0.1424 j , 0.0682+0.0811 j ],
[ 0.3436+0.2393 j , 0.0505-0.0122 j , -0.0484-0.1730 j , -0.0440+0.2970 j ,
0.3615+0.2362 j , 0.2817-0.0456 j , 0.2953+0.4642 j , -0.2217+0.2824 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 ]] )