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.92042346+0.3752344 j 0. + 0. j 0.04138827-0.10152249 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_4ce0ffa4c4014c75a5013de6b12d6d64
Circuit block
cluster_9865317ca55e498fbab90c3d3bba2768
Prep block
5ac13b0f433c438d9d7e906678d2f934
0
8378db0bf9e149059b3e629b320d283a
5ac13b0f433c438d9d7e906678d2f934--8378db0bf9e149059b3e629b320d283a
daac939040d645bea53fa94662c16877
1
200fc41532624bf886080c354b281b7d
RX(theta₀)
8378db0bf9e149059b3e629b320d283a--200fc41532624bf886080c354b281b7d
5cb90460d2b841878cde2c5ee2dc6847
RY(theta₄)
200fc41532624bf886080c354b281b7d--5cb90460d2b841878cde2c5ee2dc6847
8f75cda9aefb4523b9094f23a646b9bd
RX(theta₈)
5cb90460d2b841878cde2c5ee2dc6847--8f75cda9aefb4523b9094f23a646b9bd
f833f0090c4546beb255b838762a25c4
8f75cda9aefb4523b9094f23a646b9bd--f833f0090c4546beb255b838762a25c4
dbb671eccb3e4c90bd13062023a089fd
f833f0090c4546beb255b838762a25c4--dbb671eccb3e4c90bd13062023a089fd
179ab97d1a1d4fedad0a5243544fd53f
RX(theta₁₂)
dbb671eccb3e4c90bd13062023a089fd--179ab97d1a1d4fedad0a5243544fd53f
bc0fd4642da34696ba4f9c00c2e67e87
RY(theta₁₆)
179ab97d1a1d4fedad0a5243544fd53f--bc0fd4642da34696ba4f9c00c2e67e87
148dbc86059846a48e6277d2d518f07e
RX(theta₂₀)
bc0fd4642da34696ba4f9c00c2e67e87--148dbc86059846a48e6277d2d518f07e
64404bceffc44f498f3212716a804a4c
148dbc86059846a48e6277d2d518f07e--64404bceffc44f498f3212716a804a4c
b3d87d73d500410d8901bc35994c7998
64404bceffc44f498f3212716a804a4c--b3d87d73d500410d8901bc35994c7998
6933d65e8ca24d66bd9929fc549586ab
b3d87d73d500410d8901bc35994c7998--6933d65e8ca24d66bd9929fc549586ab
3d35f86a1e5944228652b52fd9faf7ad
799e1baa7972495eb0e36e2d4e4aa534
daac939040d645bea53fa94662c16877--799e1baa7972495eb0e36e2d4e4aa534
6d87e87f642647c9b5b6e2a61874cdef
2
017bc6d239584849b03fb8a556520677
RX(theta₁)
799e1baa7972495eb0e36e2d4e4aa534--017bc6d239584849b03fb8a556520677
4e8e81b632ba4b8dac1bb213fe193a0e
RY(theta₅)
017bc6d239584849b03fb8a556520677--4e8e81b632ba4b8dac1bb213fe193a0e
09518538f27b4709b5a28c6a7d926f5f
RX(theta₉)
4e8e81b632ba4b8dac1bb213fe193a0e--09518538f27b4709b5a28c6a7d926f5f
462c0a63b286473e9fb7182f5241e6a2
X
09518538f27b4709b5a28c6a7d926f5f--462c0a63b286473e9fb7182f5241e6a2
462c0a63b286473e9fb7182f5241e6a2--f833f0090c4546beb255b838762a25c4
99d33b73a1f1418b918bfe2fb618ecca
462c0a63b286473e9fb7182f5241e6a2--99d33b73a1f1418b918bfe2fb618ecca
f06f4e6da5814a11b40a616485ff6c0b
RX(theta₁₃)
99d33b73a1f1418b918bfe2fb618ecca--f06f4e6da5814a11b40a616485ff6c0b
755c7f842aaf472f9dee99f5962edc89
RY(theta₁₇)
f06f4e6da5814a11b40a616485ff6c0b--755c7f842aaf472f9dee99f5962edc89
0a07b56b7456456d80bbd47717209fd8
RX(theta₂₁)
755c7f842aaf472f9dee99f5962edc89--0a07b56b7456456d80bbd47717209fd8
61bf95e14f2148829075aeb839fe4b42
X
0a07b56b7456456d80bbd47717209fd8--61bf95e14f2148829075aeb839fe4b42
61bf95e14f2148829075aeb839fe4b42--64404bceffc44f498f3212716a804a4c
9b0fb3cee35242c4a8d3d05378919920
61bf95e14f2148829075aeb839fe4b42--9b0fb3cee35242c4a8d3d05378919920
9b0fb3cee35242c4a8d3d05378919920--3d35f86a1e5944228652b52fd9faf7ad
a2aa1cb112474c99b546205cb3c34d8c
b9d9fc3d19e840d992ef8d2ffcfdc136
6d87e87f642647c9b5b6e2a61874cdef--b9d9fc3d19e840d992ef8d2ffcfdc136
18095005a0414805b00457707842deaa
3
93cbba6bef3348d38b3c5efb63de1b81
RX(theta₂)
b9d9fc3d19e840d992ef8d2ffcfdc136--93cbba6bef3348d38b3c5efb63de1b81
f3f182fd6fca44fea4d1296184730a25
RY(theta₆)
93cbba6bef3348d38b3c5efb63de1b81--f3f182fd6fca44fea4d1296184730a25
03af64b6419746a6a9634f0301b20c85
RX(theta₁₀)
f3f182fd6fca44fea4d1296184730a25--03af64b6419746a6a9634f0301b20c85
893463695d174a03accdaeed50f01280
03af64b6419746a6a9634f0301b20c85--893463695d174a03accdaeed50f01280
0cd41e1877f646cda0af5673a4d49706
X
893463695d174a03accdaeed50f01280--0cd41e1877f646cda0af5673a4d49706
0cd41e1877f646cda0af5673a4d49706--99d33b73a1f1418b918bfe2fb618ecca
9549f6b7c6594a12917d5d327f8ac5fe
RX(theta₁₄)
0cd41e1877f646cda0af5673a4d49706--9549f6b7c6594a12917d5d327f8ac5fe
af8c951fbf07496d8dad754d183522b2
RY(theta₁₈)
9549f6b7c6594a12917d5d327f8ac5fe--af8c951fbf07496d8dad754d183522b2
5f4f1b281425456cb64d38adac536ece
RX(theta₂₂)
af8c951fbf07496d8dad754d183522b2--5f4f1b281425456cb64d38adac536ece
47334c3310a54b39ab437161fac26ce7
5f4f1b281425456cb64d38adac536ece--47334c3310a54b39ab437161fac26ce7
b42cb6c38da4499db2669e47de1453e4
X
47334c3310a54b39ab437161fac26ce7--b42cb6c38da4499db2669e47de1453e4
b42cb6c38da4499db2669e47de1453e4--9b0fb3cee35242c4a8d3d05378919920
b42cb6c38da4499db2669e47de1453e4--a2aa1cb112474c99b546205cb3c34d8c
2ae737e7a4d1470cb8ce4db8feaaaf42
01cb8012612248e887f2794104e43335
X
18095005a0414805b00457707842deaa--01cb8012612248e887f2794104e43335
13179a6ddc9547bca093b68633037a83
RX(theta₃)
01cb8012612248e887f2794104e43335--13179a6ddc9547bca093b68633037a83
2c61c73f51dc49a7a659152f667b8001
RY(theta₇)
13179a6ddc9547bca093b68633037a83--2c61c73f51dc49a7a659152f667b8001
26e10f7305234eb98f37ef93758298b1
RX(theta₁₁)
2c61c73f51dc49a7a659152f667b8001--26e10f7305234eb98f37ef93758298b1
7bf478e2aaa548d7b8d4c94a263d1de1
X
26e10f7305234eb98f37ef93758298b1--7bf478e2aaa548d7b8d4c94a263d1de1
7bf478e2aaa548d7b8d4c94a263d1de1--893463695d174a03accdaeed50f01280
bf1639986d8043ac9e2a5475a433728d
7bf478e2aaa548d7b8d4c94a263d1de1--bf1639986d8043ac9e2a5475a433728d
8cb727d5542d4538825ac5026c8c1895
RX(theta₁₅)
bf1639986d8043ac9e2a5475a433728d--8cb727d5542d4538825ac5026c8c1895
9078fd91f82a4e98824450c4a57b80da
RY(theta₁₉)
8cb727d5542d4538825ac5026c8c1895--9078fd91f82a4e98824450c4a57b80da
7ed693e5e6e94fc2a3561b7057e3e1b1
RX(theta₂₃)
9078fd91f82a4e98824450c4a57b80da--7ed693e5e6e94fc2a3561b7057e3e1b1
3bfbd2017efb452f8fbe902ffa0400db
X
7ed693e5e6e94fc2a3561b7057e3e1b1--3bfbd2017efb452f8fbe902ffa0400db
3bfbd2017efb452f8fbe902ffa0400db--47334c3310a54b39ab437161fac26ce7
de7f455ca6c14d56b3465633c2924551
3bfbd2017efb452f8fbe902ffa0400db--de7f455ca6c14d56b3465633c2924551
de7f455ca6c14d56b3465633c2924551--2ae737e7a4d1470cb8ce4db8feaaaf42
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 , 1.+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 ]] )
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.1938-0.0520 j , -0.2004+0.3661 j , -0.0483-0.0577 j , -0.2657-0.3253 j ,
0.4508+0.0664 j , 0.2878+0.0577 j , -0.2979+0.1222 j , -0.0662+0.4491 j ],
[ 0.2315-0.2451 j , 0.2807+0.1053 j , -0.3644+0.4587 j , -0.0791+0.0530 j ,
-0.0125-0.1685 j , 0.2731-0.3878 j , -0.3455-0.2506 j , -0.0893-0.0241 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 ]] )