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 = [ 9.74766377e-01+0. j -2.23196158e-01+0. j -3.64528914e-03+0. j
8.34676440e-04+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_8608be44a7104966b80cda8d5b87b586
Circuit block
cluster_c3c198e6602e453a872846cef7f5b8d9
Prep block
381db8e669114ab5b35fbbea74fd5457
0
925d16c5e2d84935a83ee00e282fd62f
381db8e669114ab5b35fbbea74fd5457--925d16c5e2d84935a83ee00e282fd62f
17995c74e5824c538137741d1ef9fc74
1
1564ea52f1e04495b562289ddf9c7a8b
RX(theta₀)
925d16c5e2d84935a83ee00e282fd62f--1564ea52f1e04495b562289ddf9c7a8b
d9fcf8b8ce1741e9aa503bd370fa4d28
RY(theta₄)
1564ea52f1e04495b562289ddf9c7a8b--d9fcf8b8ce1741e9aa503bd370fa4d28
ae6c0731c28846a9b35389c9932532b8
RX(theta₈)
d9fcf8b8ce1741e9aa503bd370fa4d28--ae6c0731c28846a9b35389c9932532b8
ba3d0caf02d74a66959c72438a4bf448
ae6c0731c28846a9b35389c9932532b8--ba3d0caf02d74a66959c72438a4bf448
9fb6bce56c1f4f53b43e99719eb0f160
ba3d0caf02d74a66959c72438a4bf448--9fb6bce56c1f4f53b43e99719eb0f160
42f3305efce941a4ac51a633bd1b1ed3
RX(theta₁₂)
9fb6bce56c1f4f53b43e99719eb0f160--42f3305efce941a4ac51a633bd1b1ed3
0aa9bacc5a90462ca21edd346509464d
RY(theta₁₆)
42f3305efce941a4ac51a633bd1b1ed3--0aa9bacc5a90462ca21edd346509464d
c901d4d4ed054214a84976dcd68dc3b9
RX(theta₂₀)
0aa9bacc5a90462ca21edd346509464d--c901d4d4ed054214a84976dcd68dc3b9
ecc25b4d62a340e5889de6602dec3799
c901d4d4ed054214a84976dcd68dc3b9--ecc25b4d62a340e5889de6602dec3799
b28aafde57704e5aa69a488f6669a01a
ecc25b4d62a340e5889de6602dec3799--b28aafde57704e5aa69a488f6669a01a
f7438661ff984dee97b8f8fb53e5928d
b28aafde57704e5aa69a488f6669a01a--f7438661ff984dee97b8f8fb53e5928d
aa82535e52ac46dcb2a30babd7df7345
741f32c34995463e8315fc9e39e7a521
17995c74e5824c538137741d1ef9fc74--741f32c34995463e8315fc9e39e7a521
49295c1771b44ada9c7c39cd6bc49da2
2
7d6aa4d46f754f089724bc528c79305c
RX(theta₁)
741f32c34995463e8315fc9e39e7a521--7d6aa4d46f754f089724bc528c79305c
18c25122f8f64b61af248e65451e0de4
RY(theta₅)
7d6aa4d46f754f089724bc528c79305c--18c25122f8f64b61af248e65451e0de4
fc5d91f23d2d436c951dfa6e8c2342d1
RX(theta₉)
18c25122f8f64b61af248e65451e0de4--fc5d91f23d2d436c951dfa6e8c2342d1
2e596dfa8142474abdf061fddc530f19
X
fc5d91f23d2d436c951dfa6e8c2342d1--2e596dfa8142474abdf061fddc530f19
2e596dfa8142474abdf061fddc530f19--ba3d0caf02d74a66959c72438a4bf448
ae7e19ea75d64e6393987fb99ea1b519
2e596dfa8142474abdf061fddc530f19--ae7e19ea75d64e6393987fb99ea1b519
be079b58b07649f08ca0f1f9b32597a1
RX(theta₁₃)
ae7e19ea75d64e6393987fb99ea1b519--be079b58b07649f08ca0f1f9b32597a1
38a1dee8da6e47f28c450dae39491cbf
RY(theta₁₇)
be079b58b07649f08ca0f1f9b32597a1--38a1dee8da6e47f28c450dae39491cbf
05c27747912d49758565896dac05c8ea
RX(theta₂₁)
38a1dee8da6e47f28c450dae39491cbf--05c27747912d49758565896dac05c8ea
784b59f6ee8c4c478faf23a465e6d446
X
05c27747912d49758565896dac05c8ea--784b59f6ee8c4c478faf23a465e6d446
784b59f6ee8c4c478faf23a465e6d446--ecc25b4d62a340e5889de6602dec3799
bd46a69cc721403aab541a79939f2863
784b59f6ee8c4c478faf23a465e6d446--bd46a69cc721403aab541a79939f2863
bd46a69cc721403aab541a79939f2863--aa82535e52ac46dcb2a30babd7df7345
b65adb48d7be458786cf3bfc300bfb2a
739c613dafa14e8cbc5d3a3b811eaffe
49295c1771b44ada9c7c39cd6bc49da2--739c613dafa14e8cbc5d3a3b811eaffe
4e1a389b6d5b4370ba1cbf0ae5a98a5b
3
8fc5bd5bc802415a897ce94c9d158d3b
RX(theta₂)
739c613dafa14e8cbc5d3a3b811eaffe--8fc5bd5bc802415a897ce94c9d158d3b
a57a233865f8419ab4a23f5e488d9492
RY(theta₆)
8fc5bd5bc802415a897ce94c9d158d3b--a57a233865f8419ab4a23f5e488d9492
998218bc3e584c7c9e49f61ee1198beb
RX(theta₁₀)
a57a233865f8419ab4a23f5e488d9492--998218bc3e584c7c9e49f61ee1198beb
7d7abdf6de984f03b4bf1acf0b33c0c3
998218bc3e584c7c9e49f61ee1198beb--7d7abdf6de984f03b4bf1acf0b33c0c3
34fdada750ef44a89d17391373a4269e
X
7d7abdf6de984f03b4bf1acf0b33c0c3--34fdada750ef44a89d17391373a4269e
34fdada750ef44a89d17391373a4269e--ae7e19ea75d64e6393987fb99ea1b519
f18ed0871cc747aaad6f603ec6e2c2a6
RX(theta₁₄)
34fdada750ef44a89d17391373a4269e--f18ed0871cc747aaad6f603ec6e2c2a6
6f139d33fa7942f6a514eeaccc7f8240
RY(theta₁₈)
f18ed0871cc747aaad6f603ec6e2c2a6--6f139d33fa7942f6a514eeaccc7f8240
a7c964235ff142cca7c6763a0de15a56
RX(theta₂₂)
6f139d33fa7942f6a514eeaccc7f8240--a7c964235ff142cca7c6763a0de15a56
7cf0700a556b479cbcf2690bf2aaa750
a7c964235ff142cca7c6763a0de15a56--7cf0700a556b479cbcf2690bf2aaa750
772533dd0e1c47cab78aea17284212fc
X
7cf0700a556b479cbcf2690bf2aaa750--772533dd0e1c47cab78aea17284212fc
772533dd0e1c47cab78aea17284212fc--bd46a69cc721403aab541a79939f2863
772533dd0e1c47cab78aea17284212fc--b65adb48d7be458786cf3bfc300bfb2a
76568b59304249b1bac4cd7397492446
8684733eb7c545abb95c0a7045c43e73
X
4e1a389b6d5b4370ba1cbf0ae5a98a5b--8684733eb7c545abb95c0a7045c43e73
fd3facac0d2d433fadc45189f5a871d3
RX(theta₃)
8684733eb7c545abb95c0a7045c43e73--fd3facac0d2d433fadc45189f5a871d3
d86088c8b1834215bafb6c4735dc8519
RY(theta₇)
fd3facac0d2d433fadc45189f5a871d3--d86088c8b1834215bafb6c4735dc8519
ebfc62c73405477db52f2774f73981e2
RX(theta₁₁)
d86088c8b1834215bafb6c4735dc8519--ebfc62c73405477db52f2774f73981e2
2f32c77d5a1e4e23a42f91928215a8de
X
ebfc62c73405477db52f2774f73981e2--2f32c77d5a1e4e23a42f91928215a8de
2f32c77d5a1e4e23a42f91928215a8de--7d7abdf6de984f03b4bf1acf0b33c0c3
9a4d0e4cf97d4692b551f450753c9988
2f32c77d5a1e4e23a42f91928215a8de--9a4d0e4cf97d4692b551f450753c9988
e288ee201f18448db25ab8060ea5a399
RX(theta₁₅)
9a4d0e4cf97d4692b551f450753c9988--e288ee201f18448db25ab8060ea5a399
73deedfeadbe4bcbb83ac02ee4dc0941
RY(theta₁₉)
e288ee201f18448db25ab8060ea5a399--73deedfeadbe4bcbb83ac02ee4dc0941
4b67a0b0a0e648f5954a9af0aec7a9fe
RX(theta₂₃)
73deedfeadbe4bcbb83ac02ee4dc0941--4b67a0b0a0e648f5954a9af0aec7a9fe
f3601e147ebc4a7e8c3ca690790e12ba
X
4b67a0b0a0e648f5954a9af0aec7a9fe--f3601e147ebc4a7e8c3ca690790e12ba
f3601e147ebc4a7e8c3ca690790e12ba--7cf0700a556b479cbcf2690bf2aaa750
8165123baaf640c5a772108446d6deb8
f3601e147ebc4a7e8c3ca690790e12ba--8165123baaf640c5a772108446d6deb8
8165123baaf640c5a772108446d6deb8--76568b59304249b1bac4cd7397492446
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 , 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 ]] )
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.4025-0.1833 j , -0.2130-0.1846 j , 0.0888+0.1441 j , 0.2353+0.1470 j ,
-0.0163+0.0063 j , -0.5182-0.4070 j , 0.0032-0.2105 j , 0.3715-0.0498 j ],
[ 0.5168-0.1029 j , 0.1842-0.3470 j , 0.3309-0.1683 j , 0.0565-0.1246 j ,
0.2506-0.3857 j , -0.1022-0.3466 j , -0.0437-0.0899 j , -0.2311+0.0773 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 )
├── 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 ]] )