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.09573453-0.9954069 j 0. + 0. 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_3de77a67644d4105ac98fa64342a15a3
Circuit block
cluster_67a64a38358c47079cab219d209041b4
Prep block
d4b7821d6f5b4e7db6edc0155868df25
0
33c9d7a12eab4260adbbdfe51a4347c0
d4b7821d6f5b4e7db6edc0155868df25--33c9d7a12eab4260adbbdfe51a4347c0
8b7eb1f9bcad446a95adb09988cec23c
1
5779ab83efac4bc9b5a6345cf2f43fcc
RX(theta₀)
33c9d7a12eab4260adbbdfe51a4347c0--5779ab83efac4bc9b5a6345cf2f43fcc
bb2448fadc06461292079f367da45cc7
RY(theta₄)
5779ab83efac4bc9b5a6345cf2f43fcc--bb2448fadc06461292079f367da45cc7
71750456dcef470f90f46a729808637c
RX(theta₈)
bb2448fadc06461292079f367da45cc7--71750456dcef470f90f46a729808637c
53e46d67d383428fb0a8e7d5d9b1a534
71750456dcef470f90f46a729808637c--53e46d67d383428fb0a8e7d5d9b1a534
4104fa1a69874264b36bb02eba801eb0
53e46d67d383428fb0a8e7d5d9b1a534--4104fa1a69874264b36bb02eba801eb0
df41fa98f8ca4161b05b72cc5b016cc4
RX(theta₁₂)
4104fa1a69874264b36bb02eba801eb0--df41fa98f8ca4161b05b72cc5b016cc4
800f7c32646e439cac571738f233bc6b
RY(theta₁₆)
df41fa98f8ca4161b05b72cc5b016cc4--800f7c32646e439cac571738f233bc6b
542f24b3fd1d443c94300ac196b093ca
RX(theta₂₀)
800f7c32646e439cac571738f233bc6b--542f24b3fd1d443c94300ac196b093ca
dbdd71b338af4a1bb89b12b90c0ba4e5
542f24b3fd1d443c94300ac196b093ca--dbdd71b338af4a1bb89b12b90c0ba4e5
3c3c496516d84e9db60a201de4838e6a
dbdd71b338af4a1bb89b12b90c0ba4e5--3c3c496516d84e9db60a201de4838e6a
66699e4525444a18a5c878f5f4941bca
3c3c496516d84e9db60a201de4838e6a--66699e4525444a18a5c878f5f4941bca
0be9a1d4569f4d2a9e2058b7460f3f08
77d6419237664f37a357af2fbd5daa8a
8b7eb1f9bcad446a95adb09988cec23c--77d6419237664f37a357af2fbd5daa8a
c07f563c93d34bc7be0777d30a8a44d3
2
701affa5f20f4d63844a474e69a63f23
RX(theta₁)
77d6419237664f37a357af2fbd5daa8a--701affa5f20f4d63844a474e69a63f23
c7ee152c3a4e45cc81161584906f0c16
RY(theta₅)
701affa5f20f4d63844a474e69a63f23--c7ee152c3a4e45cc81161584906f0c16
897012ca02ae4e24b41ae30edadf42a2
RX(theta₉)
c7ee152c3a4e45cc81161584906f0c16--897012ca02ae4e24b41ae30edadf42a2
2a22edec0c0947269571b77b2062d867
X
897012ca02ae4e24b41ae30edadf42a2--2a22edec0c0947269571b77b2062d867
2a22edec0c0947269571b77b2062d867--53e46d67d383428fb0a8e7d5d9b1a534
747920d2c1a147969916b1ae299cb0f3
2a22edec0c0947269571b77b2062d867--747920d2c1a147969916b1ae299cb0f3
57060540824142e08c2dbfea962b6466
RX(theta₁₃)
747920d2c1a147969916b1ae299cb0f3--57060540824142e08c2dbfea962b6466
9a5fabe90695421b8ed6e87e602f8a08
RY(theta₁₇)
57060540824142e08c2dbfea962b6466--9a5fabe90695421b8ed6e87e602f8a08
9218f12971254f0f9080d5a819b52e83
RX(theta₂₁)
9a5fabe90695421b8ed6e87e602f8a08--9218f12971254f0f9080d5a819b52e83
666ed3e8167c4731adf980da73cedd05
X
9218f12971254f0f9080d5a819b52e83--666ed3e8167c4731adf980da73cedd05
666ed3e8167c4731adf980da73cedd05--dbdd71b338af4a1bb89b12b90c0ba4e5
446e99050f5548cc94f1824ca6f981df
666ed3e8167c4731adf980da73cedd05--446e99050f5548cc94f1824ca6f981df
446e99050f5548cc94f1824ca6f981df--0be9a1d4569f4d2a9e2058b7460f3f08
3ca2235bdfbd4177a614c71c58196701
309da3c4756b4cbcba2f8bb0c25fc69c
c07f563c93d34bc7be0777d30a8a44d3--309da3c4756b4cbcba2f8bb0c25fc69c
03c1eb036a044425ba6b7f21cbbc4765
3
69c3cebef3954af3b38f323022d6a643
RX(theta₂)
309da3c4756b4cbcba2f8bb0c25fc69c--69c3cebef3954af3b38f323022d6a643
2090c9c347c740e8a333f3d528cc1288
RY(theta₆)
69c3cebef3954af3b38f323022d6a643--2090c9c347c740e8a333f3d528cc1288
c318b607f62f447681e2a0ab0d9ab2d4
RX(theta₁₀)
2090c9c347c740e8a333f3d528cc1288--c318b607f62f447681e2a0ab0d9ab2d4
6ca12fa3f3294cefab0abe2ceda6e785
c318b607f62f447681e2a0ab0d9ab2d4--6ca12fa3f3294cefab0abe2ceda6e785
055b00e778a3414dba840d5a667bba2d
X
6ca12fa3f3294cefab0abe2ceda6e785--055b00e778a3414dba840d5a667bba2d
055b00e778a3414dba840d5a667bba2d--747920d2c1a147969916b1ae299cb0f3
e9aae1dbe2f04190ba472685f46c386e
RX(theta₁₄)
055b00e778a3414dba840d5a667bba2d--e9aae1dbe2f04190ba472685f46c386e
c81313fe288340338abeb5749e182bcd
RY(theta₁₈)
e9aae1dbe2f04190ba472685f46c386e--c81313fe288340338abeb5749e182bcd
c5d341da95be48afa67052bc83be0507
RX(theta₂₂)
c81313fe288340338abeb5749e182bcd--c5d341da95be48afa67052bc83be0507
e260e1622e1b487fa29c77fb7d43adbb
c5d341da95be48afa67052bc83be0507--e260e1622e1b487fa29c77fb7d43adbb
ca213fd5be514beebf02cdbc854c39ac
X
e260e1622e1b487fa29c77fb7d43adbb--ca213fd5be514beebf02cdbc854c39ac
ca213fd5be514beebf02cdbc854c39ac--446e99050f5548cc94f1824ca6f981df
ca213fd5be514beebf02cdbc854c39ac--3ca2235bdfbd4177a614c71c58196701
503be18a74c74662a49c5c32d8deb575
1ffada0a7eb7450b802b066426610cda
X
03c1eb036a044425ba6b7f21cbbc4765--1ffada0a7eb7450b802b066426610cda
3750ad05c4314af2850c79deb4420eda
RX(theta₃)
1ffada0a7eb7450b802b066426610cda--3750ad05c4314af2850c79deb4420eda
839cf81a5e714aa78b97de7786d16234
RY(theta₇)
3750ad05c4314af2850c79deb4420eda--839cf81a5e714aa78b97de7786d16234
1db055bf32244110a5bd5f9911b7b54c
RX(theta₁₁)
839cf81a5e714aa78b97de7786d16234--1db055bf32244110a5bd5f9911b7b54c
4b0eec023e4443ae8d403afec4a5f89b
X
1db055bf32244110a5bd5f9911b7b54c--4b0eec023e4443ae8d403afec4a5f89b
4b0eec023e4443ae8d403afec4a5f89b--6ca12fa3f3294cefab0abe2ceda6e785
012acfa364684e798b1753130be973ce
4b0eec023e4443ae8d403afec4a5f89b--012acfa364684e798b1753130be973ce
237cc420448645648cbe032f08e14f17
RX(theta₁₅)
012acfa364684e798b1753130be973ce--237cc420448645648cbe032f08e14f17
79f3392fab1b49f6951a24aea3aae4fc
RY(theta₁₉)
237cc420448645648cbe032f08e14f17--79f3392fab1b49f6951a24aea3aae4fc
c40653847eaa48fdb007c0640a05334b
RX(theta₂₃)
79f3392fab1b49f6951a24aea3aae4fc--c40653847eaa48fdb007c0640a05334b
3fe06d00f8ae41f582c704de4695eb5f
X
c40653847eaa48fdb007c0640a05334b--3fe06d00f8ae41f582c704de4695eb5f
3fe06d00f8ae41f582c704de4695eb5f--e260e1622e1b487fa29c77fb7d43adbb
853568f893b64cada1d13bea1cfcb065
3fe06d00f8ae41f582c704de4695eb5f--853568f893b64cada1d13bea1cfcb065
853568f893b64cada1d13bea1cfcb065--503be18a74c74662a49c5c32d8deb575
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 , 1.+0. j , 0.+0. j , 0.+0. j , 0.+0. j , 0.+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 ]] )
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.1174-0.2038 j , 0.1194+0.0970 j , 0.4173-0.3010 j , 0.0464-0.0913 j ,
0.1557-0.1457 j , 0.3139+0.2603 j , 0.1850+0.1393 j , -0.6106-0.0869 j ],
[ 0.1436-0.4136 j , -0.0725+0.1590 j , 0.1971-0.0148 j , -0.0967-0.0249 j ,
-0.3791-0.4295 j , 0.1268-0.0350 j , -0.3676-0.0611 j , 0.1942-0.4546 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 ]] )