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.4016671 + 0.43579074 j -0.54587946-0.59225467 j 0. + 0. 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_4c3909b1e1504173bb71d6296c619227
Circuit block
cluster_95cbd247dba94b9ab47488d58bd87fd6
Prep block
ed13de46a4594da4b1112d6e19ac2b4b
0
16acd06766ff41419a6171dd523f1608
ed13de46a4594da4b1112d6e19ac2b4b--16acd06766ff41419a6171dd523f1608
d5ef1c76b47a4bbba61e28528f3a4be8
1
08645b7f9a314ecdb14aaad1be8f7df7
RX(theta₀)
16acd06766ff41419a6171dd523f1608--08645b7f9a314ecdb14aaad1be8f7df7
a1c431cac98146028bf0a4d50645fda7
RY(theta₄)
08645b7f9a314ecdb14aaad1be8f7df7--a1c431cac98146028bf0a4d50645fda7
a0e894cda626487cafc774f9b048b77b
RX(theta₈)
a1c431cac98146028bf0a4d50645fda7--a0e894cda626487cafc774f9b048b77b
2accd7eedd3343809d856f00efcc2d9a
a0e894cda626487cafc774f9b048b77b--2accd7eedd3343809d856f00efcc2d9a
6328046b112f4116bea83059ab43c5ee
2accd7eedd3343809d856f00efcc2d9a--6328046b112f4116bea83059ab43c5ee
0bad4fa858f14ad1b03601738ee75c86
RX(theta₁₂)
6328046b112f4116bea83059ab43c5ee--0bad4fa858f14ad1b03601738ee75c86
abacd7a534924728923183fb1a45593d
RY(theta₁₆)
0bad4fa858f14ad1b03601738ee75c86--abacd7a534924728923183fb1a45593d
f2bbafb0c9f2486f82d37aef7f49ac37
RX(theta₂₀)
abacd7a534924728923183fb1a45593d--f2bbafb0c9f2486f82d37aef7f49ac37
c76b0fded87544c9ba5ca08d6350a410
f2bbafb0c9f2486f82d37aef7f49ac37--c76b0fded87544c9ba5ca08d6350a410
95b4d01ad3bd44328702ad9cacb428fe
c76b0fded87544c9ba5ca08d6350a410--95b4d01ad3bd44328702ad9cacb428fe
c03850a993ad474fb94727441ff2b472
95b4d01ad3bd44328702ad9cacb428fe--c03850a993ad474fb94727441ff2b472
ec0117186fe84959ba5310e0f091f2cf
5dc4243a2adb417d9d17a255afbe8bdf
d5ef1c76b47a4bbba61e28528f3a4be8--5dc4243a2adb417d9d17a255afbe8bdf
8be03578480a4aaf90e21f47a380f327
2
37d0cf7b3f964c968558dd0a97905c67
RX(theta₁)
5dc4243a2adb417d9d17a255afbe8bdf--37d0cf7b3f964c968558dd0a97905c67
910c870fa5a34fdb86cee41eccc41f62
RY(theta₅)
37d0cf7b3f964c968558dd0a97905c67--910c870fa5a34fdb86cee41eccc41f62
c1f324421c5b44ec8c9e9146d8ea2c4c
RX(theta₉)
910c870fa5a34fdb86cee41eccc41f62--c1f324421c5b44ec8c9e9146d8ea2c4c
39e73d4388f041e4859efd337816f471
X
c1f324421c5b44ec8c9e9146d8ea2c4c--39e73d4388f041e4859efd337816f471
39e73d4388f041e4859efd337816f471--2accd7eedd3343809d856f00efcc2d9a
b9af09421619432e8ed5839ca97ce6f9
39e73d4388f041e4859efd337816f471--b9af09421619432e8ed5839ca97ce6f9
1d15ae7a867b4506b4246eca0794bcaa
RX(theta₁₃)
b9af09421619432e8ed5839ca97ce6f9--1d15ae7a867b4506b4246eca0794bcaa
0dccd1f8e27543f29a4776fcf9272585
RY(theta₁₇)
1d15ae7a867b4506b4246eca0794bcaa--0dccd1f8e27543f29a4776fcf9272585
1c66ed73ed3e4f068a0335f027954e8d
RX(theta₂₁)
0dccd1f8e27543f29a4776fcf9272585--1c66ed73ed3e4f068a0335f027954e8d
a4987cd810694fb9b94d279f11595f25
X
1c66ed73ed3e4f068a0335f027954e8d--a4987cd810694fb9b94d279f11595f25
a4987cd810694fb9b94d279f11595f25--c76b0fded87544c9ba5ca08d6350a410
bd9f97105f094a85b35b7eb687f3a4f1
a4987cd810694fb9b94d279f11595f25--bd9f97105f094a85b35b7eb687f3a4f1
bd9f97105f094a85b35b7eb687f3a4f1--ec0117186fe84959ba5310e0f091f2cf
ad5a07b13bdc47f6b3480ffbecf5060b
480363f734404f5f8c83af71f45b7453
8be03578480a4aaf90e21f47a380f327--480363f734404f5f8c83af71f45b7453
fabb6059e1fa4a05b88819a9c9481ded
3
985472a0d8904315a7e2a559b17a9f61
RX(theta₂)
480363f734404f5f8c83af71f45b7453--985472a0d8904315a7e2a559b17a9f61
b3d8abfa53b0470a8de4a221d5e9b4d5
RY(theta₆)
985472a0d8904315a7e2a559b17a9f61--b3d8abfa53b0470a8de4a221d5e9b4d5
b238097ff4894ebab11f804c6d1b9b4e
RX(theta₁₀)
b3d8abfa53b0470a8de4a221d5e9b4d5--b238097ff4894ebab11f804c6d1b9b4e
a7c1d3f7d1df49708fd666e196bba846
b238097ff4894ebab11f804c6d1b9b4e--a7c1d3f7d1df49708fd666e196bba846
ec847b20c0884bc89f395f8aaf1eba50
X
a7c1d3f7d1df49708fd666e196bba846--ec847b20c0884bc89f395f8aaf1eba50
ec847b20c0884bc89f395f8aaf1eba50--b9af09421619432e8ed5839ca97ce6f9
1ac6a1c46ef54fa8890f794cf35f66a4
RX(theta₁₄)
ec847b20c0884bc89f395f8aaf1eba50--1ac6a1c46ef54fa8890f794cf35f66a4
30aaaf96afc44b2fa2c19f30fad2b834
RY(theta₁₈)
1ac6a1c46ef54fa8890f794cf35f66a4--30aaaf96afc44b2fa2c19f30fad2b834
a2c6f897904e4c8195bd74f8e01b51d0
RX(theta₂₂)
30aaaf96afc44b2fa2c19f30fad2b834--a2c6f897904e4c8195bd74f8e01b51d0
34984e3b140b4e168e1f7fbdfd57a68a
a2c6f897904e4c8195bd74f8e01b51d0--34984e3b140b4e168e1f7fbdfd57a68a
096964289cd04852a6c15e5573948db9
X
34984e3b140b4e168e1f7fbdfd57a68a--096964289cd04852a6c15e5573948db9
096964289cd04852a6c15e5573948db9--bd9f97105f094a85b35b7eb687f3a4f1
096964289cd04852a6c15e5573948db9--ad5a07b13bdc47f6b3480ffbecf5060b
eeb1383249fb40b2b527c8c8b903dcaa
c363b67292054c1f8e3f7cfded6f8113
X
fabb6059e1fa4a05b88819a9c9481ded--c363b67292054c1f8e3f7cfded6f8113
287a1cca6ce747e1a35709c8be8d28e8
RX(theta₃)
c363b67292054c1f8e3f7cfded6f8113--287a1cca6ce747e1a35709c8be8d28e8
545dbc8166c44303a87594096c90fc85
RY(theta₇)
287a1cca6ce747e1a35709c8be8d28e8--545dbc8166c44303a87594096c90fc85
21f0771b93724743a715bb7078c35880
RX(theta₁₁)
545dbc8166c44303a87594096c90fc85--21f0771b93724743a715bb7078c35880
3fe023e389f14c99be072a8b3170baba
X
21f0771b93724743a715bb7078c35880--3fe023e389f14c99be072a8b3170baba
3fe023e389f14c99be072a8b3170baba--a7c1d3f7d1df49708fd666e196bba846
090be7062f7444ebb11a484256361fa6
3fe023e389f14c99be072a8b3170baba--090be7062f7444ebb11a484256361fa6
79acecb37daf4af58d326f91c51e873f
RX(theta₁₅)
090be7062f7444ebb11a484256361fa6--79acecb37daf4af58d326f91c51e873f
26c9a821ab0043e2a0a3f4c75b0698a0
RY(theta₁₉)
79acecb37daf4af58d326f91c51e873f--26c9a821ab0043e2a0a3f4c75b0698a0
3773eae14b024b0a811ddcfd2b6b9366
RX(theta₂₃)
26c9a821ab0043e2a0a3f4c75b0698a0--3773eae14b024b0a811ddcfd2b6b9366
468f03324b5342d6aaf5438050177d68
X
3773eae14b024b0a811ddcfd2b6b9366--468f03324b5342d6aaf5438050177d68
468f03324b5342d6aaf5438050177d68--34984e3b140b4e168e1f7fbdfd57a68a
9a76fd7754f0425096475d095d6bc029
468f03324b5342d6aaf5438050177d68--9a76fd7754f0425096475d095d6bc029
9a76fd7754f0425096475d095d6bc029--eeb1383249fb40b2b527c8c8b903dcaa
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 , 1.+0. j , 0.+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 ]] )
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.2390-0.1881 j , 0.1646-0.0699 j , -0.4417-0.1439 j , -0.1631+0.1908 j ,
0.0305-0.2692 j , 0.2547+0.0842 j , 0.1633+0.2059 j , -0.2162-0.5792 j ],
[ 0.0061+0.1679 j , 0.1055+0.2131 j , -0.1951-0.0451 j , 0.0293+0.2837 j ,
-0.1773+0.3076 j , -0.0885+0.0918 j , 0.4380+0.4700 j , -0.3802+0.3070 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 ]] )