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.95253032+0. j -0.10844744+0. j 0. + 0.28264746 j
0. -0.03217997 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_adec49aeab104c7a841905e8af0158a1
Circuit block
cluster_af23ca15e328457daf5bde77461716c7
Prep block
457ccabd80d241e98ea4645f77e4bdb9
0
fca63722c1974f68a99547d6ab15a01b
457ccabd80d241e98ea4645f77e4bdb9--fca63722c1974f68a99547d6ab15a01b
de612bba5e974d4190caebcaa3c3488e
1
76b7f839d89c41ada2285dd0a8b6a47c
RX(theta₀)
fca63722c1974f68a99547d6ab15a01b--76b7f839d89c41ada2285dd0a8b6a47c
2da92035c29c49c494a86682a361b400
RY(theta₄)
76b7f839d89c41ada2285dd0a8b6a47c--2da92035c29c49c494a86682a361b400
edd0d72726474d08b1b5a6ad7a0bcd71
RX(theta₈)
2da92035c29c49c494a86682a361b400--edd0d72726474d08b1b5a6ad7a0bcd71
d7192745e9c54ae799727974dff9af84
edd0d72726474d08b1b5a6ad7a0bcd71--d7192745e9c54ae799727974dff9af84
b026004a381b4c02b79261ed50cbb22a
d7192745e9c54ae799727974dff9af84--b026004a381b4c02b79261ed50cbb22a
305e080dbaa645e782c57b58d132b5f2
RX(theta₁₂)
b026004a381b4c02b79261ed50cbb22a--305e080dbaa645e782c57b58d132b5f2
06ad38f252824f0993e0e4ee90a99b2f
RY(theta₁₆)
305e080dbaa645e782c57b58d132b5f2--06ad38f252824f0993e0e4ee90a99b2f
0ce99803a92f4021887d91d41a635362
RX(theta₂₀)
06ad38f252824f0993e0e4ee90a99b2f--0ce99803a92f4021887d91d41a635362
272ca61d55ea494ba7bc96b85683fef8
0ce99803a92f4021887d91d41a635362--272ca61d55ea494ba7bc96b85683fef8
3083b5be70cc423da990bfc5211d0c08
272ca61d55ea494ba7bc96b85683fef8--3083b5be70cc423da990bfc5211d0c08
a50e7c62817046a2a3e9911b4dd72bbc
3083b5be70cc423da990bfc5211d0c08--a50e7c62817046a2a3e9911b4dd72bbc
de1db80f467a47ce8b376b3165586bd9
5f80e8f4587a4865b664bc9ba29d674f
de612bba5e974d4190caebcaa3c3488e--5f80e8f4587a4865b664bc9ba29d674f
6ca4018f163247f2930f928f58ff746d
2
648015422d074713b0cbaee95b81c220
RX(theta₁)
5f80e8f4587a4865b664bc9ba29d674f--648015422d074713b0cbaee95b81c220
9eb706f8457c4527b3992e8f7f548157
RY(theta₅)
648015422d074713b0cbaee95b81c220--9eb706f8457c4527b3992e8f7f548157
3965ab8459724fa88591877fe17ea016
RX(theta₉)
9eb706f8457c4527b3992e8f7f548157--3965ab8459724fa88591877fe17ea016
66c04216d397472398a0a5d5a7aef126
X
3965ab8459724fa88591877fe17ea016--66c04216d397472398a0a5d5a7aef126
66c04216d397472398a0a5d5a7aef126--d7192745e9c54ae799727974dff9af84
77a10a95016248239a7962dc1f819f4c
66c04216d397472398a0a5d5a7aef126--77a10a95016248239a7962dc1f819f4c
a181fd14594643d8af97336e9a0310a2
RX(theta₁₃)
77a10a95016248239a7962dc1f819f4c--a181fd14594643d8af97336e9a0310a2
f83766efe776420fa1983b68fd0de1c1
RY(theta₁₇)
a181fd14594643d8af97336e9a0310a2--f83766efe776420fa1983b68fd0de1c1
ffaa337a336142639f65b5d6c7cae445
RX(theta₂₁)
f83766efe776420fa1983b68fd0de1c1--ffaa337a336142639f65b5d6c7cae445
6afd140fc2964f41806a8a9983dd8c85
X
ffaa337a336142639f65b5d6c7cae445--6afd140fc2964f41806a8a9983dd8c85
6afd140fc2964f41806a8a9983dd8c85--272ca61d55ea494ba7bc96b85683fef8
bac0c20fd8ce4f7284186850711cba15
6afd140fc2964f41806a8a9983dd8c85--bac0c20fd8ce4f7284186850711cba15
bac0c20fd8ce4f7284186850711cba15--de1db80f467a47ce8b376b3165586bd9
c42d89d016f64592afef2476a4ee6c58
9cfeb83d926f445fa72d962c8e919169
6ca4018f163247f2930f928f58ff746d--9cfeb83d926f445fa72d962c8e919169
3d90d36aa9a14fb68046eaafccb1bb39
3
5637e08cb32d49d18047f35f03acae31
RX(theta₂)
9cfeb83d926f445fa72d962c8e919169--5637e08cb32d49d18047f35f03acae31
2b883fed0fdc46e98e1535d962f6a9c9
RY(theta₆)
5637e08cb32d49d18047f35f03acae31--2b883fed0fdc46e98e1535d962f6a9c9
27c8795073fa4c48963a321eda629fdc
RX(theta₁₀)
2b883fed0fdc46e98e1535d962f6a9c9--27c8795073fa4c48963a321eda629fdc
17f9773736134546aec6f8fcccc4f26a
27c8795073fa4c48963a321eda629fdc--17f9773736134546aec6f8fcccc4f26a
8c7aa7127cdf42e393240b3f27755cf8
X
17f9773736134546aec6f8fcccc4f26a--8c7aa7127cdf42e393240b3f27755cf8
8c7aa7127cdf42e393240b3f27755cf8--77a10a95016248239a7962dc1f819f4c
9b3a306b8c9048b7aa7a64a39cb7bce0
RX(theta₁₄)
8c7aa7127cdf42e393240b3f27755cf8--9b3a306b8c9048b7aa7a64a39cb7bce0
7ebb7c3664b940b2bf204d63e29e57b7
RY(theta₁₈)
9b3a306b8c9048b7aa7a64a39cb7bce0--7ebb7c3664b940b2bf204d63e29e57b7
5894384466bb45308024a7ee17870c89
RX(theta₂₂)
7ebb7c3664b940b2bf204d63e29e57b7--5894384466bb45308024a7ee17870c89
c9d7a944221247b99ebbae833ada235a
5894384466bb45308024a7ee17870c89--c9d7a944221247b99ebbae833ada235a
1da1d1ebd3e74bbdbdb1ac1a47294634
X
c9d7a944221247b99ebbae833ada235a--1da1d1ebd3e74bbdbdb1ac1a47294634
1da1d1ebd3e74bbdbdb1ac1a47294634--bac0c20fd8ce4f7284186850711cba15
1da1d1ebd3e74bbdbdb1ac1a47294634--c42d89d016f64592afef2476a4ee6c58
20212aad7b5a404f9f2b309246771318
44321e77f0b340debe1aabf677e61b16
X
3d90d36aa9a14fb68046eaafccb1bb39--44321e77f0b340debe1aabf677e61b16
9be0fcbf1eaa4ad29055128438bb52b0
RX(theta₃)
44321e77f0b340debe1aabf677e61b16--9be0fcbf1eaa4ad29055128438bb52b0
aa4da93917f143d5a7cc6a57d20ce2ce
RY(theta₇)
9be0fcbf1eaa4ad29055128438bb52b0--aa4da93917f143d5a7cc6a57d20ce2ce
0ff87f2dcba64c0793df07f9b8be4c14
RX(theta₁₁)
aa4da93917f143d5a7cc6a57d20ce2ce--0ff87f2dcba64c0793df07f9b8be4c14
7b886d1a1a2a4df8aabb99ce32fb07e9
X
0ff87f2dcba64c0793df07f9b8be4c14--7b886d1a1a2a4df8aabb99ce32fb07e9
7b886d1a1a2a4df8aabb99ce32fb07e9--17f9773736134546aec6f8fcccc4f26a
f11e0e2102354accaa480f3b25eed5dd
7b886d1a1a2a4df8aabb99ce32fb07e9--f11e0e2102354accaa480f3b25eed5dd
773b8341c310478492dc0693b54ba89e
RX(theta₁₅)
f11e0e2102354accaa480f3b25eed5dd--773b8341c310478492dc0693b54ba89e
84b5f743c490441798f24d527a23e1ae
RY(theta₁₉)
773b8341c310478492dc0693b54ba89e--84b5f743c490441798f24d527a23e1ae
f928a936b76a458a871ff3dbcbaac049
RX(theta₂₃)
84b5f743c490441798f24d527a23e1ae--f928a936b76a458a871ff3dbcbaac049
16e3dbc12540451487c4ce4dba7a8bf3
X
f928a936b76a458a871ff3dbcbaac049--16e3dbc12540451487c4ce4dba7a8bf3
16e3dbc12540451487c4ce4dba7a8bf3--c9d7a944221247b99ebbae833ada235a
7cc7560517ab414e871875c1bacb3227
16e3dbc12540451487c4ce4dba7a8bf3--7cc7560517ab414e871875c1bacb3227
7cc7560517ab414e871875c1bacb3227--20212aad7b5a404f9f2b309246771318
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 )
├── 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 ]] )