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.92861342+0. j 0.36763729+0. j -0.04667426+0. j -0.0184783 + 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_26f18de5d7ed4abb9871b821baeb2b43
Circuit block
cluster_e43706f9a848402f9e5cd8b34f44960f
Prep block
2fa9dc8de9f34fb49ea27bf1387bdd40
0
a6ad8eda80604add819b50aadc0fd9d7
2fa9dc8de9f34fb49ea27bf1387bdd40--a6ad8eda80604add819b50aadc0fd9d7
aec10b8d4a594bed9f11859cf0bda35b
1
cf36fbbd800e4cdda85395d88535958d
RX(theta₀)
a6ad8eda80604add819b50aadc0fd9d7--cf36fbbd800e4cdda85395d88535958d
b83f5d4098e246f6ba37950b6aeee2ad
RY(theta₄)
cf36fbbd800e4cdda85395d88535958d--b83f5d4098e246f6ba37950b6aeee2ad
57cec917e1d5475c8b01dbbbe850b9cb
RX(theta₈)
b83f5d4098e246f6ba37950b6aeee2ad--57cec917e1d5475c8b01dbbbe850b9cb
ea462195c6364ca381cb25d37a5beced
57cec917e1d5475c8b01dbbbe850b9cb--ea462195c6364ca381cb25d37a5beced
3c3471db2a964962aec9c7c026396125
ea462195c6364ca381cb25d37a5beced--3c3471db2a964962aec9c7c026396125
604ebe925ba2494b96dffefb2d65f6f4
RX(theta₁₂)
3c3471db2a964962aec9c7c026396125--604ebe925ba2494b96dffefb2d65f6f4
4e703c8ad78c45efb0af9eb8e0c71c2c
RY(theta₁₆)
604ebe925ba2494b96dffefb2d65f6f4--4e703c8ad78c45efb0af9eb8e0c71c2c
0d7331a7c3d047638ce28bc43f901369
RX(theta₂₀)
4e703c8ad78c45efb0af9eb8e0c71c2c--0d7331a7c3d047638ce28bc43f901369
67275c467d904137bcd996fc2332607c
0d7331a7c3d047638ce28bc43f901369--67275c467d904137bcd996fc2332607c
edef43d14cff4b3fb8a3548a83fc9ee3
67275c467d904137bcd996fc2332607c--edef43d14cff4b3fb8a3548a83fc9ee3
0fbd22ceeef14f13886afe452ea2c578
edef43d14cff4b3fb8a3548a83fc9ee3--0fbd22ceeef14f13886afe452ea2c578
53e4940b89b4466b8f880144ef73f87d
90401d48597e4782a12601b6a7a23aa4
aec10b8d4a594bed9f11859cf0bda35b--90401d48597e4782a12601b6a7a23aa4
a70069f1501c4beb9669ced4a496a08e
2
7488ed6bc9964e32865bbe8de13436e8
RX(theta₁)
90401d48597e4782a12601b6a7a23aa4--7488ed6bc9964e32865bbe8de13436e8
8c21452d29db40f591b0a0d952c4659e
RY(theta₅)
7488ed6bc9964e32865bbe8de13436e8--8c21452d29db40f591b0a0d952c4659e
7f0f71df208c4be5904bd0ffec524b90
RX(theta₉)
8c21452d29db40f591b0a0d952c4659e--7f0f71df208c4be5904bd0ffec524b90
36d3a872a400414ba5a71543fa17079c
X
7f0f71df208c4be5904bd0ffec524b90--36d3a872a400414ba5a71543fa17079c
36d3a872a400414ba5a71543fa17079c--ea462195c6364ca381cb25d37a5beced
6b15107f32004303b6b8f79770ff6715
36d3a872a400414ba5a71543fa17079c--6b15107f32004303b6b8f79770ff6715
2cd9b1f9355d4272afdb90ef8bc89b46
RX(theta₁₃)
6b15107f32004303b6b8f79770ff6715--2cd9b1f9355d4272afdb90ef8bc89b46
9e92e73b735e4c49aa27833c39b467c0
RY(theta₁₇)
2cd9b1f9355d4272afdb90ef8bc89b46--9e92e73b735e4c49aa27833c39b467c0
f910552b4c7f4c8385e44abb94e5ff4c
RX(theta₂₁)
9e92e73b735e4c49aa27833c39b467c0--f910552b4c7f4c8385e44abb94e5ff4c
b0725e5c70524c27876d572aec41de0e
X
f910552b4c7f4c8385e44abb94e5ff4c--b0725e5c70524c27876d572aec41de0e
b0725e5c70524c27876d572aec41de0e--67275c467d904137bcd996fc2332607c
ad3597df04ef461ca2cd836d1f5347c2
b0725e5c70524c27876d572aec41de0e--ad3597df04ef461ca2cd836d1f5347c2
ad3597df04ef461ca2cd836d1f5347c2--53e4940b89b4466b8f880144ef73f87d
9d7d1c5c30a341b6ba2c340c9f3015bd
814ad8d50adb4dd3a650c8af0a95c9f7
a70069f1501c4beb9669ced4a496a08e--814ad8d50adb4dd3a650c8af0a95c9f7
7dee45c279f94cfa8009be303acce868
3
257e41edaa024b52bcba26793f0c2603
RX(theta₂)
814ad8d50adb4dd3a650c8af0a95c9f7--257e41edaa024b52bcba26793f0c2603
2daa8594c2aa4b2dbb2255231ea8ad58
RY(theta₆)
257e41edaa024b52bcba26793f0c2603--2daa8594c2aa4b2dbb2255231ea8ad58
ecd97ee9a250462990c5f9e353799ced
RX(theta₁₀)
2daa8594c2aa4b2dbb2255231ea8ad58--ecd97ee9a250462990c5f9e353799ced
a7a9805b008048dcb5b67de18d705fbd
ecd97ee9a250462990c5f9e353799ced--a7a9805b008048dcb5b67de18d705fbd
d38a48ac2003419089f3bf2d88a566b7
X
a7a9805b008048dcb5b67de18d705fbd--d38a48ac2003419089f3bf2d88a566b7
d38a48ac2003419089f3bf2d88a566b7--6b15107f32004303b6b8f79770ff6715
7eb1605e72e0499c97ef8bb31c2dbe34
RX(theta₁₄)
d38a48ac2003419089f3bf2d88a566b7--7eb1605e72e0499c97ef8bb31c2dbe34
8d8df817d5624f26add835b6cdce4e6d
RY(theta₁₈)
7eb1605e72e0499c97ef8bb31c2dbe34--8d8df817d5624f26add835b6cdce4e6d
8de0fe047c484a0d9d40b776d96f462a
RX(theta₂₂)
8d8df817d5624f26add835b6cdce4e6d--8de0fe047c484a0d9d40b776d96f462a
a464fbaaaf924d5d8714639fd735f3aa
8de0fe047c484a0d9d40b776d96f462a--a464fbaaaf924d5d8714639fd735f3aa
d6701d8e44374b65bce33c8b0e5613cf
X
a464fbaaaf924d5d8714639fd735f3aa--d6701d8e44374b65bce33c8b0e5613cf
d6701d8e44374b65bce33c8b0e5613cf--ad3597df04ef461ca2cd836d1f5347c2
d6701d8e44374b65bce33c8b0e5613cf--9d7d1c5c30a341b6ba2c340c9f3015bd
d615bedc690240d39cb6f48e49b3b5b3
079ef52bd33a4301bb54d00422d95b43
X
7dee45c279f94cfa8009be303acce868--079ef52bd33a4301bb54d00422d95b43
b3749076d3824179b391123261a4a867
RX(theta₃)
079ef52bd33a4301bb54d00422d95b43--b3749076d3824179b391123261a4a867
92c5b1876d424382bb40e135abdd76f3
RY(theta₇)
b3749076d3824179b391123261a4a867--92c5b1876d424382bb40e135abdd76f3
a2728a9b56254a8ea9be8ab34ef48306
RX(theta₁₁)
92c5b1876d424382bb40e135abdd76f3--a2728a9b56254a8ea9be8ab34ef48306
74907c24fb294163b7e28869495f2a57
X
a2728a9b56254a8ea9be8ab34ef48306--74907c24fb294163b7e28869495f2a57
74907c24fb294163b7e28869495f2a57--a7a9805b008048dcb5b67de18d705fbd
5d1b4f53695141a48f04a6313bf79c6b
74907c24fb294163b7e28869495f2a57--5d1b4f53695141a48f04a6313bf79c6b
1325e40ac3a44b39b3ae86b1bf2df8b4
RX(theta₁₅)
5d1b4f53695141a48f04a6313bf79c6b--1325e40ac3a44b39b3ae86b1bf2df8b4
58739be90b8348ba96a83ae093068e9b
RY(theta₁₉)
1325e40ac3a44b39b3ae86b1bf2df8b4--58739be90b8348ba96a83ae093068e9b
28440f4e3785414f8976b089ef13a065
RX(theta₂₃)
58739be90b8348ba96a83ae093068e9b--28440f4e3785414f8976b089ef13a065
e90dc05f28e344b49f1f9458675aeced
X
28440f4e3785414f8976b089ef13a065--e90dc05f28e344b49f1f9458675aeced
e90dc05f28e344b49f1f9458675aeced--a464fbaaaf924d5d8714639fd735f3aa
6beb9df2063d4bc8be1e6aebe4683003
e90dc05f28e344b49f1f9458675aeced--6beb9df2063d4bc8be1e6aebe4683003
6beb9df2063d4bc8be1e6aebe4683003--d615bedc690240d39cb6f48e49b3b5b3
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 , 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 ]] )
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.4778-0.3032 j , -0.2188+0.0063 j , -0.5854+0.1054 j , -0.0209+0.1171 j ,
-0.1233+0.1146 j , 0.2949-0.1529 j , 0.2178+0.2514 j , 0.0053+0.1206 j ],
[ 0.0060+0.1147 j , 0.1033+0.1432 j , -0.2309+0.3088 j , -0.2681+0.2402 j ,
-0.2283-0.2065 j , -0.4066+0.1532 j , -0.5098-0.1379 j , 0.2512-0.2275 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 ]] )