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.95905179+0.07257001 j -0.27299549-0.02065716 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_0615399263254fd0bf594511bb28d775
Circuit block
cluster_b11e0bda350a476eb40f65dd0a7adf83
Prep block
1ae58760d0364f13928e5d318ee1f349
0
ea597de6f2b640e9a26589a52086339d
1ae58760d0364f13928e5d318ee1f349--ea597de6f2b640e9a26589a52086339d
f186f7dbca3948cc8172b9dd0809c2b7
1
e28a6fdf47904623b21072d1cd991278
RX(theta₀)
ea597de6f2b640e9a26589a52086339d--e28a6fdf47904623b21072d1cd991278
8b457b8b7c504dff81bb91ce49737911
RY(theta₄)
e28a6fdf47904623b21072d1cd991278--8b457b8b7c504dff81bb91ce49737911
50f2807f7d844c879400d6706c788dd0
RX(theta₈)
8b457b8b7c504dff81bb91ce49737911--50f2807f7d844c879400d6706c788dd0
919b4f92024b4a9ba23aa3702cb1d679
50f2807f7d844c879400d6706c788dd0--919b4f92024b4a9ba23aa3702cb1d679
028fecffd9a048fe91c560c1d978adcb
919b4f92024b4a9ba23aa3702cb1d679--028fecffd9a048fe91c560c1d978adcb
0e5acd3b8722437c9a09601e348bbcb8
RX(theta₁₂)
028fecffd9a048fe91c560c1d978adcb--0e5acd3b8722437c9a09601e348bbcb8
b0c1f13644494922b12a494f9c1f6b2c
RY(theta₁₆)
0e5acd3b8722437c9a09601e348bbcb8--b0c1f13644494922b12a494f9c1f6b2c
d0ee0ca39a9a4fa0a0066ff8fbd9f5d7
RX(theta₂₀)
b0c1f13644494922b12a494f9c1f6b2c--d0ee0ca39a9a4fa0a0066ff8fbd9f5d7
d8a764b718e2433ca2c48b506dc3ac4e
d0ee0ca39a9a4fa0a0066ff8fbd9f5d7--d8a764b718e2433ca2c48b506dc3ac4e
0ef5f2b7338d4aeea2dbc3ceaf800446
d8a764b718e2433ca2c48b506dc3ac4e--0ef5f2b7338d4aeea2dbc3ceaf800446
9266657de044454d86f85907a1cbfdc5
0ef5f2b7338d4aeea2dbc3ceaf800446--9266657de044454d86f85907a1cbfdc5
ea818eba22e34c7d9ce505d91e701f93
68f4c7c5d06a4aba90f1297f0df31d57
f186f7dbca3948cc8172b9dd0809c2b7--68f4c7c5d06a4aba90f1297f0df31d57
e826cdd4a8d54b77a1140311c1a384c5
2
408aecedcecb44d1851ea5ebeac39aee
RX(theta₁)
68f4c7c5d06a4aba90f1297f0df31d57--408aecedcecb44d1851ea5ebeac39aee
440baeed7e9349939745144836d1cf7a
RY(theta₅)
408aecedcecb44d1851ea5ebeac39aee--440baeed7e9349939745144836d1cf7a
e928bb401205488b912845e67dfe7cf5
RX(theta₉)
440baeed7e9349939745144836d1cf7a--e928bb401205488b912845e67dfe7cf5
0684a1d8cd424bfc903f6b8fa55fb05b
X
e928bb401205488b912845e67dfe7cf5--0684a1d8cd424bfc903f6b8fa55fb05b
0684a1d8cd424bfc903f6b8fa55fb05b--919b4f92024b4a9ba23aa3702cb1d679
921ccbf6a04c4064a7fa56c95f03943e
0684a1d8cd424bfc903f6b8fa55fb05b--921ccbf6a04c4064a7fa56c95f03943e
be3f174334a545ecacada5535904e5c1
RX(theta₁₃)
921ccbf6a04c4064a7fa56c95f03943e--be3f174334a545ecacada5535904e5c1
47e8ca249ab9429fa43a9c91c71078a3
RY(theta₁₇)
be3f174334a545ecacada5535904e5c1--47e8ca249ab9429fa43a9c91c71078a3
c8d8efe6e8834e80b5e50337b517f04f
RX(theta₂₁)
47e8ca249ab9429fa43a9c91c71078a3--c8d8efe6e8834e80b5e50337b517f04f
b2097f5ff8e6483b88b65aaa9217f354
X
c8d8efe6e8834e80b5e50337b517f04f--b2097f5ff8e6483b88b65aaa9217f354
b2097f5ff8e6483b88b65aaa9217f354--d8a764b718e2433ca2c48b506dc3ac4e
af825a338c0c437d8d12de7ecfb3fd80
b2097f5ff8e6483b88b65aaa9217f354--af825a338c0c437d8d12de7ecfb3fd80
af825a338c0c437d8d12de7ecfb3fd80--ea818eba22e34c7d9ce505d91e701f93
e02ddccdef9a4faba3eb8e211c2f6296
f090a31aaab24f37a7ac11fb2e928264
e826cdd4a8d54b77a1140311c1a384c5--f090a31aaab24f37a7ac11fb2e928264
0f99cc5ce99c4a6ab8f8795fd078c1e7
3
08ba275a5f554b46aa92778e96747b4f
RX(theta₂)
f090a31aaab24f37a7ac11fb2e928264--08ba275a5f554b46aa92778e96747b4f
eb853549e72143dfac18f0b64f71f321
RY(theta₆)
08ba275a5f554b46aa92778e96747b4f--eb853549e72143dfac18f0b64f71f321
0134dec0cc41486b90eb489ace35bd1c
RX(theta₁₀)
eb853549e72143dfac18f0b64f71f321--0134dec0cc41486b90eb489ace35bd1c
364ae636655e420588ee2d4f94c72a30
0134dec0cc41486b90eb489ace35bd1c--364ae636655e420588ee2d4f94c72a30
550d9e969f994a8dba7cbe5a561bfc19
X
364ae636655e420588ee2d4f94c72a30--550d9e969f994a8dba7cbe5a561bfc19
550d9e969f994a8dba7cbe5a561bfc19--921ccbf6a04c4064a7fa56c95f03943e
4a2c5fce062d4504823ba64725255bb8
RX(theta₁₄)
550d9e969f994a8dba7cbe5a561bfc19--4a2c5fce062d4504823ba64725255bb8
6f21efd1cea1403eb44d7b5b5a5a2e21
RY(theta₁₈)
4a2c5fce062d4504823ba64725255bb8--6f21efd1cea1403eb44d7b5b5a5a2e21
2dd68537f40b4d9c9802666cf6b929c7
RX(theta₂₂)
6f21efd1cea1403eb44d7b5b5a5a2e21--2dd68537f40b4d9c9802666cf6b929c7
4e2a1cd8744946e196113f93aa7f006b
2dd68537f40b4d9c9802666cf6b929c7--4e2a1cd8744946e196113f93aa7f006b
1a73a48f68734774a1ca8e2cc17cd3d3
X
4e2a1cd8744946e196113f93aa7f006b--1a73a48f68734774a1ca8e2cc17cd3d3
1a73a48f68734774a1ca8e2cc17cd3d3--af825a338c0c437d8d12de7ecfb3fd80
1a73a48f68734774a1ca8e2cc17cd3d3--e02ddccdef9a4faba3eb8e211c2f6296
866e7fbc25b1492d88e5744f620797b2
bc93b688325b4ba6be8cd11439f619f7
X
0f99cc5ce99c4a6ab8f8795fd078c1e7--bc93b688325b4ba6be8cd11439f619f7
892c675e4b6a401ab275eed57414b482
RX(theta₃)
bc93b688325b4ba6be8cd11439f619f7--892c675e4b6a401ab275eed57414b482
fb9f87320eac4e51b886d3881dec82eb
RY(theta₇)
892c675e4b6a401ab275eed57414b482--fb9f87320eac4e51b886d3881dec82eb
bdbd982335d44194b71847c63535c2be
RX(theta₁₁)
fb9f87320eac4e51b886d3881dec82eb--bdbd982335d44194b71847c63535c2be
3f348c15435d413995b3d7cb30d1b62b
X
bdbd982335d44194b71847c63535c2be--3f348c15435d413995b3d7cb30d1b62b
3f348c15435d413995b3d7cb30d1b62b--364ae636655e420588ee2d4f94c72a30
6ea47e76e93f4d4a9d12e8488b3dad02
3f348c15435d413995b3d7cb30d1b62b--6ea47e76e93f4d4a9d12e8488b3dad02
fe1c99727d75445d91bf777e5859e5b3
RX(theta₁₅)
6ea47e76e93f4d4a9d12e8488b3dad02--fe1c99727d75445d91bf777e5859e5b3
5d5d0a611f374f17974696098dbd7a23
RY(theta₁₉)
fe1c99727d75445d91bf777e5859e5b3--5d5d0a611f374f17974696098dbd7a23
0192f760e7744a7184e3aaf5a053a922
RX(theta₂₃)
5d5d0a611f374f17974696098dbd7a23--0192f760e7744a7184e3aaf5a053a922
a820c08ae09e46c8b002858b46dc043f
X
0192f760e7744a7184e3aaf5a053a922--a820c08ae09e46c8b002858b46dc043f
a820c08ae09e46c8b002858b46dc043f--4e2a1cd8744946e196113f93aa7f006b
5b5d4add046e4f929af6b63e988c3c03
a820c08ae09e46c8b002858b46dc043f--5b5d4add046e4f929af6b63e988c3c03
5b5d4add046e4f929af6b63e988c3c03--866e7fbc25b1492d88e5744f620797b2
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 , 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 ]] )
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.4778-0.3032 j , -0.2188+0.0063 j , -0.5854+0.1054 j , -0.0209+0.1171 j ,
-0.1233+0.1146 j , 0.2949-0.1529 j , 0.2178+0.2514 j , 0.0053+0.1206 j ],
[ 0.0060+0.1147 j , 0.1033+0.1432 j , -0.2309+0.3088 j , -0.2681+0.2402 j ,
-0.2283-0.2065 j , -0.4066+0.1532 j , -0.5098-0.1379 j , 0.2512-0.2275 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 ]] )