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.58118498+0. j 0. -0.81374446 j 0. -0.0038541 j
-0.0053963 + 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_816cb842ffae43f3990255449ce8f50d
Circuit block
cluster_7a3d965a37454a81b27c93400f5b85a4
Prep block
89e28c26b1114782adcfc19b77609f4b
0
851751bb566f491b96bf33013526a77f
89e28c26b1114782adcfc19b77609f4b--851751bb566f491b96bf33013526a77f
03fba14459054177a2810b1a5f43cc7b
1
fa8a4c99bf2b415cb072f1888c92af7a
RX(theta₀)
851751bb566f491b96bf33013526a77f--fa8a4c99bf2b415cb072f1888c92af7a
2c05a345e99946d19df69439138ee532
RY(theta₄)
fa8a4c99bf2b415cb072f1888c92af7a--2c05a345e99946d19df69439138ee532
e64875f7912c4fb39fe3e6c431df4bd4
RX(theta₈)
2c05a345e99946d19df69439138ee532--e64875f7912c4fb39fe3e6c431df4bd4
94f1b868eb944469aeb7a3173dd1eaee
e64875f7912c4fb39fe3e6c431df4bd4--94f1b868eb944469aeb7a3173dd1eaee
ee9bfa48433a467a8b8039d1fde62265
94f1b868eb944469aeb7a3173dd1eaee--ee9bfa48433a467a8b8039d1fde62265
5a334550d3e5498fa101650e6c903a13
RX(theta₁₂)
ee9bfa48433a467a8b8039d1fde62265--5a334550d3e5498fa101650e6c903a13
b58d9fc4186c48a1b14fb1e538ba8039
RY(theta₁₆)
5a334550d3e5498fa101650e6c903a13--b58d9fc4186c48a1b14fb1e538ba8039
712165eba6c542c68efcfaf4ddce7697
RX(theta₂₀)
b58d9fc4186c48a1b14fb1e538ba8039--712165eba6c542c68efcfaf4ddce7697
978495cfbc954a188d85ecdaac9757d5
712165eba6c542c68efcfaf4ddce7697--978495cfbc954a188d85ecdaac9757d5
528c14ec6eb94d7ea8c9b5eceeeeddd8
978495cfbc954a188d85ecdaac9757d5--528c14ec6eb94d7ea8c9b5eceeeeddd8
44aae52292854a288b77e9e717c169d1
528c14ec6eb94d7ea8c9b5eceeeeddd8--44aae52292854a288b77e9e717c169d1
108aea92da344a09994143b51bf1539c
f321dfbee0fb4b0f97f20de53b40139f
03fba14459054177a2810b1a5f43cc7b--f321dfbee0fb4b0f97f20de53b40139f
10a72475655f467faeafaf1c4787d24b
2
a4cb14169187477692dee8e857be17ae
RX(theta₁)
f321dfbee0fb4b0f97f20de53b40139f--a4cb14169187477692dee8e857be17ae
b99261790c7b4bb99679934ba9a7424f
RY(theta₅)
a4cb14169187477692dee8e857be17ae--b99261790c7b4bb99679934ba9a7424f
c6e0f96ad233487ca7e14fda944dff1c
RX(theta₉)
b99261790c7b4bb99679934ba9a7424f--c6e0f96ad233487ca7e14fda944dff1c
ed863512fdc542d09e92d66593f7b936
X
c6e0f96ad233487ca7e14fda944dff1c--ed863512fdc542d09e92d66593f7b936
ed863512fdc542d09e92d66593f7b936--94f1b868eb944469aeb7a3173dd1eaee
74b5066066c849f78e0645f06dc21825
ed863512fdc542d09e92d66593f7b936--74b5066066c849f78e0645f06dc21825
503feabc785d4f37b2144113d151bba4
RX(theta₁₃)
74b5066066c849f78e0645f06dc21825--503feabc785d4f37b2144113d151bba4
5cc71377c36e484ba1443d278dbdc3d7
RY(theta₁₇)
503feabc785d4f37b2144113d151bba4--5cc71377c36e484ba1443d278dbdc3d7
713193e16bf84264b2dfc9945028f45b
RX(theta₂₁)
5cc71377c36e484ba1443d278dbdc3d7--713193e16bf84264b2dfc9945028f45b
aaa3870e12594031a99f985813b5ec38
X
713193e16bf84264b2dfc9945028f45b--aaa3870e12594031a99f985813b5ec38
aaa3870e12594031a99f985813b5ec38--978495cfbc954a188d85ecdaac9757d5
3e674b7edeb041fbbd9408b52e1cca58
aaa3870e12594031a99f985813b5ec38--3e674b7edeb041fbbd9408b52e1cca58
3e674b7edeb041fbbd9408b52e1cca58--108aea92da344a09994143b51bf1539c
7dcc7674d3164adf907f3023a086608a
62ea3a6001074106809d90cba7a1e955
10a72475655f467faeafaf1c4787d24b--62ea3a6001074106809d90cba7a1e955
a029c968d9d44d87bde7680d1ce3a360
3
c1fd52ae4be247b28a47f9f6edc718cb
RX(theta₂)
62ea3a6001074106809d90cba7a1e955--c1fd52ae4be247b28a47f9f6edc718cb
9b6f0f61867143ba87d1a15e4669cbff
RY(theta₆)
c1fd52ae4be247b28a47f9f6edc718cb--9b6f0f61867143ba87d1a15e4669cbff
f482f7f2793f4f259ac75f6bdc765029
RX(theta₁₀)
9b6f0f61867143ba87d1a15e4669cbff--f482f7f2793f4f259ac75f6bdc765029
97bb660f3ca2428f973e627f61709d23
f482f7f2793f4f259ac75f6bdc765029--97bb660f3ca2428f973e627f61709d23
fb6da9d8e5ed4f688435db9cb57d5f4a
X
97bb660f3ca2428f973e627f61709d23--fb6da9d8e5ed4f688435db9cb57d5f4a
fb6da9d8e5ed4f688435db9cb57d5f4a--74b5066066c849f78e0645f06dc21825
762def0c97c646a2ad0d21bc6ce22421
RX(theta₁₄)
fb6da9d8e5ed4f688435db9cb57d5f4a--762def0c97c646a2ad0d21bc6ce22421
697ff0354789444c807dcafd17cb31c6
RY(theta₁₈)
762def0c97c646a2ad0d21bc6ce22421--697ff0354789444c807dcafd17cb31c6
687ce6eef7b94c088d4af623600a44a1
RX(theta₂₂)
697ff0354789444c807dcafd17cb31c6--687ce6eef7b94c088d4af623600a44a1
87c9b19c883e42fc941e1672bc82eede
687ce6eef7b94c088d4af623600a44a1--87c9b19c883e42fc941e1672bc82eede
8fd2617e620d4a87bf3ea8643664cc0a
X
87c9b19c883e42fc941e1672bc82eede--8fd2617e620d4a87bf3ea8643664cc0a
8fd2617e620d4a87bf3ea8643664cc0a--3e674b7edeb041fbbd9408b52e1cca58
8fd2617e620d4a87bf3ea8643664cc0a--7dcc7674d3164adf907f3023a086608a
33bff10b04c24da4b1facbb7a1f5d17f
08bec690ce7045249cf1c82284ab416d
X
a029c968d9d44d87bde7680d1ce3a360--08bec690ce7045249cf1c82284ab416d
e7e6ab72dcbc4c7aa6cdae053792ad21
RX(theta₃)
08bec690ce7045249cf1c82284ab416d--e7e6ab72dcbc4c7aa6cdae053792ad21
7dc18f8b115b469cad1475979cf16ec1
RY(theta₇)
e7e6ab72dcbc4c7aa6cdae053792ad21--7dc18f8b115b469cad1475979cf16ec1
99f7061bac334d56b48a544a896ed65b
RX(theta₁₁)
7dc18f8b115b469cad1475979cf16ec1--99f7061bac334d56b48a544a896ed65b
9242f81729d847609ac17d4c5ed7e7bc
X
99f7061bac334d56b48a544a896ed65b--9242f81729d847609ac17d4c5ed7e7bc
9242f81729d847609ac17d4c5ed7e7bc--97bb660f3ca2428f973e627f61709d23
655a34c061d64bddbcba2a3aa4b76ccf
9242f81729d847609ac17d4c5ed7e7bc--655a34c061d64bddbcba2a3aa4b76ccf
6c8c500277bc468c8fbbaae893ac4503
RX(theta₁₅)
655a34c061d64bddbcba2a3aa4b76ccf--6c8c500277bc468c8fbbaae893ac4503
226641a169884f598c8f2d268b8715e8
RY(theta₁₉)
6c8c500277bc468c8fbbaae893ac4503--226641a169884f598c8f2d268b8715e8
c846995a8cd54069944c0b623e34c64c
RX(theta₂₃)
226641a169884f598c8f2d268b8715e8--c846995a8cd54069944c0b623e34c64c
6272c2e2458e4ea2a3d76c08deafe3c0
X
c846995a8cd54069944c0b623e34c64c--6272c2e2458e4ea2a3d76c08deafe3c0
6272c2e2458e4ea2a3d76c08deafe3c0--87c9b19c883e42fc941e1672bc82eede
d570b6db92fa4709a1adfff66fb3e422
6272c2e2458e4ea2a3d76c08deafe3c0--d570b6db92fa4709a1adfff66fb3e422
d570b6db92fa4709a1adfff66fb3e422--33bff10b04c24da4b1facbb7a1f5d17f
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 )
├── X( 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 ]] )