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.61294422+0. j 0. -0.62548256 j -0.33789941+0. j
0. + 0.34481145 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_20febeb5e5fd49b0b982acfc0c29c83d
Circuit block
cluster_e6ba4a54770b417dbfaa8f31684d3a04
Prep block
cd5c9a6bd6774a018e0e1450efc49d4b
0
5c70ab0f5fc845048d33c98785b0cc75
cd5c9a6bd6774a018e0e1450efc49d4b--5c70ab0f5fc845048d33c98785b0cc75
2d1efb4207b54ea68288444a75211417
1
d689ae40ccf64ad49ef3a18256e09f43
RX(theta₀)
5c70ab0f5fc845048d33c98785b0cc75--d689ae40ccf64ad49ef3a18256e09f43
b4351b460aeb4d5b81994efce6978c9b
RY(theta₄)
d689ae40ccf64ad49ef3a18256e09f43--b4351b460aeb4d5b81994efce6978c9b
4414090d3ed248958f2ed0124649748f
RX(theta₈)
b4351b460aeb4d5b81994efce6978c9b--4414090d3ed248958f2ed0124649748f
ca609c3923584ed087bb8a4fe006b215
4414090d3ed248958f2ed0124649748f--ca609c3923584ed087bb8a4fe006b215
30ad094c6a3944e0b8a8a7fb10b59a7f
ca609c3923584ed087bb8a4fe006b215--30ad094c6a3944e0b8a8a7fb10b59a7f
8b1c4fb2ae9e471f88e48b3ddf5073e7
RX(theta₁₂)
30ad094c6a3944e0b8a8a7fb10b59a7f--8b1c4fb2ae9e471f88e48b3ddf5073e7
ae1b54cf806f463595c27d55ae7382b0
RY(theta₁₆)
8b1c4fb2ae9e471f88e48b3ddf5073e7--ae1b54cf806f463595c27d55ae7382b0
6d5443466459448fb53807e5e066466a
RX(theta₂₀)
ae1b54cf806f463595c27d55ae7382b0--6d5443466459448fb53807e5e066466a
68837d1e8bdf4cbba5a01dfef8f2138d
6d5443466459448fb53807e5e066466a--68837d1e8bdf4cbba5a01dfef8f2138d
4afee3b1231945feb09e5d9256347004
68837d1e8bdf4cbba5a01dfef8f2138d--4afee3b1231945feb09e5d9256347004
817d1cd7287642b8bf61f0945b0259c0
4afee3b1231945feb09e5d9256347004--817d1cd7287642b8bf61f0945b0259c0
85e0feb5d4464421b40584ff5048fb6e
56e5d8e3b0a0496793a9e514b90f2a50
2d1efb4207b54ea68288444a75211417--56e5d8e3b0a0496793a9e514b90f2a50
37d6051f10ba4c87b7228632cd4ae186
2
94db8bc5f6a34315b682e4de9c4f05c8
RX(theta₁)
56e5d8e3b0a0496793a9e514b90f2a50--94db8bc5f6a34315b682e4de9c4f05c8
bb0a067d356747f883a56d4fc82be59f
RY(theta₅)
94db8bc5f6a34315b682e4de9c4f05c8--bb0a067d356747f883a56d4fc82be59f
1cef57bf06584f84b3d3e61badd8b0f0
RX(theta₉)
bb0a067d356747f883a56d4fc82be59f--1cef57bf06584f84b3d3e61badd8b0f0
2c93a7aba07b4fea97d4f9591ac6e931
X
1cef57bf06584f84b3d3e61badd8b0f0--2c93a7aba07b4fea97d4f9591ac6e931
2c93a7aba07b4fea97d4f9591ac6e931--ca609c3923584ed087bb8a4fe006b215
1444e3bd63734c86b3f1e3fe554e8456
2c93a7aba07b4fea97d4f9591ac6e931--1444e3bd63734c86b3f1e3fe554e8456
41098d66cdf24b8285fe51a09a2b2551
RX(theta₁₃)
1444e3bd63734c86b3f1e3fe554e8456--41098d66cdf24b8285fe51a09a2b2551
8e67ee837c7843c3a8a1e09d6f85cf95
RY(theta₁₇)
41098d66cdf24b8285fe51a09a2b2551--8e67ee837c7843c3a8a1e09d6f85cf95
e7fae26832704489b748bd40e7feab29
RX(theta₂₁)
8e67ee837c7843c3a8a1e09d6f85cf95--e7fae26832704489b748bd40e7feab29
2ce8c7e60cae4cafaeb8ccfed7577abb
X
e7fae26832704489b748bd40e7feab29--2ce8c7e60cae4cafaeb8ccfed7577abb
2ce8c7e60cae4cafaeb8ccfed7577abb--68837d1e8bdf4cbba5a01dfef8f2138d
d330f22b571b45a2a4be575e9965a33f
2ce8c7e60cae4cafaeb8ccfed7577abb--d330f22b571b45a2a4be575e9965a33f
d330f22b571b45a2a4be575e9965a33f--85e0feb5d4464421b40584ff5048fb6e
d373beb3c5dd44c4966633c47dbb1c01
d08098e9a8724055b91ec94a4dfa85d6
37d6051f10ba4c87b7228632cd4ae186--d08098e9a8724055b91ec94a4dfa85d6
df3d6c9fc9d64633b5ee410def9c0210
3
063d7d70685c4d258617c3ee2f089e1e
RX(theta₂)
d08098e9a8724055b91ec94a4dfa85d6--063d7d70685c4d258617c3ee2f089e1e
6f46d5e5bb894ded858914759c78db44
RY(theta₆)
063d7d70685c4d258617c3ee2f089e1e--6f46d5e5bb894ded858914759c78db44
0f0ae78f1b8d446e9dce3755dc8f07f4
RX(theta₁₀)
6f46d5e5bb894ded858914759c78db44--0f0ae78f1b8d446e9dce3755dc8f07f4
b018adb1df334e6a8deaf58afaa6beba
0f0ae78f1b8d446e9dce3755dc8f07f4--b018adb1df334e6a8deaf58afaa6beba
c18fdaa7d71a4bb28c19e122eef5f205
X
b018adb1df334e6a8deaf58afaa6beba--c18fdaa7d71a4bb28c19e122eef5f205
c18fdaa7d71a4bb28c19e122eef5f205--1444e3bd63734c86b3f1e3fe554e8456
f59c42e2c2fe43be978e6be7dfefe921
RX(theta₁₄)
c18fdaa7d71a4bb28c19e122eef5f205--f59c42e2c2fe43be978e6be7dfefe921
8149565607d1487c9a259aa235fdf876
RY(theta₁₈)
f59c42e2c2fe43be978e6be7dfefe921--8149565607d1487c9a259aa235fdf876
ac079ccabc1f4ba0be9bbd4b3a714685
RX(theta₂₂)
8149565607d1487c9a259aa235fdf876--ac079ccabc1f4ba0be9bbd4b3a714685
0abf807903654231a713a5137fdaa830
ac079ccabc1f4ba0be9bbd4b3a714685--0abf807903654231a713a5137fdaa830
3c3897b8a9b5475e9f5ab73551ddef90
X
0abf807903654231a713a5137fdaa830--3c3897b8a9b5475e9f5ab73551ddef90
3c3897b8a9b5475e9f5ab73551ddef90--d330f22b571b45a2a4be575e9965a33f
3c3897b8a9b5475e9f5ab73551ddef90--d373beb3c5dd44c4966633c47dbb1c01
05cc2aee09754e70bb64d5a876019be3
86270d1c2a8548b8aaf9c5a862bc502c
X
df3d6c9fc9d64633b5ee410def9c0210--86270d1c2a8548b8aaf9c5a862bc502c
a25b7de1002f481f8905ba5e9413b864
RX(theta₃)
86270d1c2a8548b8aaf9c5a862bc502c--a25b7de1002f481f8905ba5e9413b864
11948a43408e46b5909ad0c96e0a1e37
RY(theta₇)
a25b7de1002f481f8905ba5e9413b864--11948a43408e46b5909ad0c96e0a1e37
4eefb3784a40471db398a323d021a177
RX(theta₁₁)
11948a43408e46b5909ad0c96e0a1e37--4eefb3784a40471db398a323d021a177
23bb9b2fc6f0466d847c8c07025740ba
X
4eefb3784a40471db398a323d021a177--23bb9b2fc6f0466d847c8c07025740ba
23bb9b2fc6f0466d847c8c07025740ba--b018adb1df334e6a8deaf58afaa6beba
a0fad1d0e5a14b3abf4068ed8dba0ae8
23bb9b2fc6f0466d847c8c07025740ba--a0fad1d0e5a14b3abf4068ed8dba0ae8
ecb91557fb03427faa9ad45f3c9c561e
RX(theta₁₅)
a0fad1d0e5a14b3abf4068ed8dba0ae8--ecb91557fb03427faa9ad45f3c9c561e
50a03d44a9f343fb9e558f666390c504
RY(theta₁₉)
ecb91557fb03427faa9ad45f3c9c561e--50a03d44a9f343fb9e558f666390c504
98aeea0e865949bcabf4901700f09271
RX(theta₂₃)
50a03d44a9f343fb9e558f666390c504--98aeea0e865949bcabf4901700f09271
37d7855dea50466d82cef13dbcde4058
X
98aeea0e865949bcabf4901700f09271--37d7855dea50466d82cef13dbcde4058
37d7855dea50466d82cef13dbcde4058--0abf807903654231a713a5137fdaa830
b2ab227f1aef4134b3c656ae1d80a027
37d7855dea50466d82cef13dbcde4058--b2ab227f1aef4134b3c656ae1d80a027
b2ab227f1aef4134b3c656ae1d80a027--05cc2aee09754e70bb64d5a876019be3
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 , 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 , 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.0886-0.1665 j , 0.0552-0.0209 j , 0.0795-0.0616 j , -0.0848-0.4033 j ,
-0.1008-0.1063 j , 0.1614-0.3958 j , 0.1703+0.1561 j , -0.6405-0.3365 j ],
[ -0.3508+0.2872 j , 0.1534-0.3051 j , 0.1230-0.0179 j , 0.2616+0.2750 j ,
-0.1533+0.1843 j , -0.2038+0.0606 j , 0.4723-0.1386 j , -0.3999+0.1165 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 )
└── 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 ]] )