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.65634205+0. j -0.66770083+0. j -0.24624557+0. j 0.25050714+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_ccd90cedff37425a8adc40e2f75f20ef
Circuit block
cluster_7da7592c5bd245e58e0ec45efdeb28c7
Prep block
9fa97f011c1d4f5aa21aa200504751b4
0
7144b62fb9b9449c9487a5119c356483
9fa97f011c1d4f5aa21aa200504751b4--7144b62fb9b9449c9487a5119c356483
3d94cc2873154f368711b867d5ac3956
1
c218c9ba3dbd4c6d9883ecdb034db1e9
RX(theta₀)
7144b62fb9b9449c9487a5119c356483--c218c9ba3dbd4c6d9883ecdb034db1e9
4878e4ef1b9242d7886fca417ec189f8
RY(theta₄)
c218c9ba3dbd4c6d9883ecdb034db1e9--4878e4ef1b9242d7886fca417ec189f8
537dbe74cd4b4fa2baba90643955d689
RX(theta₈)
4878e4ef1b9242d7886fca417ec189f8--537dbe74cd4b4fa2baba90643955d689
7ab76ffcd50942b886dddd24f752d8fe
537dbe74cd4b4fa2baba90643955d689--7ab76ffcd50942b886dddd24f752d8fe
d301ecbf676e451e9cb0033e4e38ea11
7ab76ffcd50942b886dddd24f752d8fe--d301ecbf676e451e9cb0033e4e38ea11
81486de531a0497c8616a791c513cdcc
RX(theta₁₂)
d301ecbf676e451e9cb0033e4e38ea11--81486de531a0497c8616a791c513cdcc
1375542c964941f2a24059f8a1bbee4e
RY(theta₁₆)
81486de531a0497c8616a791c513cdcc--1375542c964941f2a24059f8a1bbee4e
c1189a8dae4f4d28a2168e0f88fa88eb
RX(theta₂₀)
1375542c964941f2a24059f8a1bbee4e--c1189a8dae4f4d28a2168e0f88fa88eb
78a39259b5254794b2e685d7b921ac41
c1189a8dae4f4d28a2168e0f88fa88eb--78a39259b5254794b2e685d7b921ac41
22926004f5fa47a59d8badd11e7073b7
78a39259b5254794b2e685d7b921ac41--22926004f5fa47a59d8badd11e7073b7
e1a291d557ca4fdcb64abd78e1919640
22926004f5fa47a59d8badd11e7073b7--e1a291d557ca4fdcb64abd78e1919640
8ead09137df44204bb0ccec089f5db5f
b26bf1cefd5444c494e308849d81abe8
3d94cc2873154f368711b867d5ac3956--b26bf1cefd5444c494e308849d81abe8
4ec60ec7f956424fb1077a152406d3d5
2
b4e67592771e404faf5202ab34669cef
RX(theta₁)
b26bf1cefd5444c494e308849d81abe8--b4e67592771e404faf5202ab34669cef
8d141b7739864181abf4eebcead545d6
RY(theta₅)
b4e67592771e404faf5202ab34669cef--8d141b7739864181abf4eebcead545d6
7ed0502a39f14cb49c17f298fccf9f52
RX(theta₉)
8d141b7739864181abf4eebcead545d6--7ed0502a39f14cb49c17f298fccf9f52
c7674878131b475dad1b11fe0d7c3804
X
7ed0502a39f14cb49c17f298fccf9f52--c7674878131b475dad1b11fe0d7c3804
c7674878131b475dad1b11fe0d7c3804--7ab76ffcd50942b886dddd24f752d8fe
f05cbbdb0bd2426fa0ac0f7b4e6a12c9
c7674878131b475dad1b11fe0d7c3804--f05cbbdb0bd2426fa0ac0f7b4e6a12c9
1e8e0e81921f4bac97dce730405d1c28
RX(theta₁₃)
f05cbbdb0bd2426fa0ac0f7b4e6a12c9--1e8e0e81921f4bac97dce730405d1c28
692a893bb36e44c1a3e34eab5dc9f27d
RY(theta₁₇)
1e8e0e81921f4bac97dce730405d1c28--692a893bb36e44c1a3e34eab5dc9f27d
ea7b3e6b45444f7c91173d6b6c7fc426
RX(theta₂₁)
692a893bb36e44c1a3e34eab5dc9f27d--ea7b3e6b45444f7c91173d6b6c7fc426
79cec9126b034468aaa0d9b38d9c0542
X
ea7b3e6b45444f7c91173d6b6c7fc426--79cec9126b034468aaa0d9b38d9c0542
79cec9126b034468aaa0d9b38d9c0542--78a39259b5254794b2e685d7b921ac41
cd3e3c9ddf574cb99ccf36b0c8cda8e9
79cec9126b034468aaa0d9b38d9c0542--cd3e3c9ddf574cb99ccf36b0c8cda8e9
cd3e3c9ddf574cb99ccf36b0c8cda8e9--8ead09137df44204bb0ccec089f5db5f
979e58eb3e3a4611a023b1479a6b90d0
d344f8157a8c4e3b811085ffc18595f1
4ec60ec7f956424fb1077a152406d3d5--d344f8157a8c4e3b811085ffc18595f1
e15eeb2a902243399069b5b5964d72f4
3
77a2a81f71f440278824cc227d1c1d65
RX(theta₂)
d344f8157a8c4e3b811085ffc18595f1--77a2a81f71f440278824cc227d1c1d65
99d4a953e3ae4414b012e231432a4a86
RY(theta₆)
77a2a81f71f440278824cc227d1c1d65--99d4a953e3ae4414b012e231432a4a86
24384a377c014928a04bd6663001cece
RX(theta₁₀)
99d4a953e3ae4414b012e231432a4a86--24384a377c014928a04bd6663001cece
a9d75322a49f433aaa95c37aaeff8b61
24384a377c014928a04bd6663001cece--a9d75322a49f433aaa95c37aaeff8b61
3b18c4d2a0b645deac6ca34f9a051838
X
a9d75322a49f433aaa95c37aaeff8b61--3b18c4d2a0b645deac6ca34f9a051838
3b18c4d2a0b645deac6ca34f9a051838--f05cbbdb0bd2426fa0ac0f7b4e6a12c9
caff9a01331a40c99ac678baf4d260fc
RX(theta₁₄)
3b18c4d2a0b645deac6ca34f9a051838--caff9a01331a40c99ac678baf4d260fc
1bad4b117036489193bc5a6a8e8ced81
RY(theta₁₈)
caff9a01331a40c99ac678baf4d260fc--1bad4b117036489193bc5a6a8e8ced81
7f1d47e3e4d34fb7ab062041d8d2034a
RX(theta₂₂)
1bad4b117036489193bc5a6a8e8ced81--7f1d47e3e4d34fb7ab062041d8d2034a
a5446cf095a74bec9b19a929c52c049e
7f1d47e3e4d34fb7ab062041d8d2034a--a5446cf095a74bec9b19a929c52c049e
850a200a12ff4add8ebfc392622ceba1
X
a5446cf095a74bec9b19a929c52c049e--850a200a12ff4add8ebfc392622ceba1
850a200a12ff4add8ebfc392622ceba1--cd3e3c9ddf574cb99ccf36b0c8cda8e9
850a200a12ff4add8ebfc392622ceba1--979e58eb3e3a4611a023b1479a6b90d0
5d949eb37ab64a758225a66450ed0704
3f334fd32ddc4c10a69e1728dc77f0fb
X
e15eeb2a902243399069b5b5964d72f4--3f334fd32ddc4c10a69e1728dc77f0fb
8bdbdf4746744154ab897de757b53a78
RX(theta₃)
3f334fd32ddc4c10a69e1728dc77f0fb--8bdbdf4746744154ab897de757b53a78
c64504872d1d41d192a072fa505c1c22
RY(theta₇)
8bdbdf4746744154ab897de757b53a78--c64504872d1d41d192a072fa505c1c22
03fe3f97d90948c8ae0fa2926997fd02
RX(theta₁₁)
c64504872d1d41d192a072fa505c1c22--03fe3f97d90948c8ae0fa2926997fd02
7d5cc2cf011d459aac4d61a4c1897267
X
03fe3f97d90948c8ae0fa2926997fd02--7d5cc2cf011d459aac4d61a4c1897267
7d5cc2cf011d459aac4d61a4c1897267--a9d75322a49f433aaa95c37aaeff8b61
f75dd560f7cb49ceb8eacab70db2a71e
7d5cc2cf011d459aac4d61a4c1897267--f75dd560f7cb49ceb8eacab70db2a71e
b557849a245343d0a48ca5b8bb7d49bf
RX(theta₁₅)
f75dd560f7cb49ceb8eacab70db2a71e--b557849a245343d0a48ca5b8bb7d49bf
cdfe1e17ca964850826121bf881390b4
RY(theta₁₉)
b557849a245343d0a48ca5b8bb7d49bf--cdfe1e17ca964850826121bf881390b4
cb91a63466ad49a4b0d71ae26f6dc85d
RX(theta₂₃)
cdfe1e17ca964850826121bf881390b4--cb91a63466ad49a4b0d71ae26f6dc85d
b307da20f5824c4691fb94c024d1ed51
X
cb91a63466ad49a4b0d71ae26f6dc85d--b307da20f5824c4691fb94c024d1ed51
b307da20f5824c4691fb94c024d1ed51--a5446cf095a74bec9b19a929c52c049e
173797292ac04b59aca3e2cb5992a59a
b307da20f5824c4691fb94c024d1ed51--173797292ac04b59aca3e2cb5992a59a
173797292ac04b59aca3e2cb5992a59a--5d949eb37ab64a758225a66450ed0704
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 , 1.+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 ]] )
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.1413-0.0314 j , 0.4271+0.0558 j , 0.1211-0.0650 j , -0.2887-0.3458 j ,
0.1520-0.5908 j , -0.2196-0.1824 j , 0.0992-0.2272 j , 0.2243+0.0795 j ],
[ 0.3506+0.1673 j , 0.0850-0.2147 j , -0.0631+0.6737 j , 0.0306+0.2123 j ,
0.3492+0.2833 j , 0.0531-0.1610 j , 0.1590-0.0134 j , 0.1670+0.0875 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 )
├── X( 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 ]] )