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.79164745-0.54544776 j 0. + 0. j -0.15618742-0.22668601 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_ea5c15a8aa54404a95524daf93d192f4
Circuit block
cluster_d3b67ad93abd4c9ea399e87bb7a285aa
Prep block
3918917c47b64279a709991e1974c225
0
58254b4548fc4f36b7f97fc5ac6fb345
3918917c47b64279a709991e1974c225--58254b4548fc4f36b7f97fc5ac6fb345
440d52368ad247189d9f00953c8b7521
1
6375746971e748858c5986f1d1c60379
RX(theta₀)
58254b4548fc4f36b7f97fc5ac6fb345--6375746971e748858c5986f1d1c60379
75aad47921aa4b99b187cf6d01630875
RY(theta₄)
6375746971e748858c5986f1d1c60379--75aad47921aa4b99b187cf6d01630875
d3c4d8aa410546d3a4d63a5ec9267220
RX(theta₈)
75aad47921aa4b99b187cf6d01630875--d3c4d8aa410546d3a4d63a5ec9267220
1de6dda3e52541a0b7817fb20eb0f102
d3c4d8aa410546d3a4d63a5ec9267220--1de6dda3e52541a0b7817fb20eb0f102
88fd6c6025114aa785ab2a7de5a18cd0
1de6dda3e52541a0b7817fb20eb0f102--88fd6c6025114aa785ab2a7de5a18cd0
63a0958a878e469caf3196f85b77f91f
RX(theta₁₂)
88fd6c6025114aa785ab2a7de5a18cd0--63a0958a878e469caf3196f85b77f91f
54be111fefc44c888dbb62648b1f5f6a
RY(theta₁₆)
63a0958a878e469caf3196f85b77f91f--54be111fefc44c888dbb62648b1f5f6a
a04de8aaa1ef4527873f7a006c0e757d
RX(theta₂₀)
54be111fefc44c888dbb62648b1f5f6a--a04de8aaa1ef4527873f7a006c0e757d
f193331bd40d4832a6a36daf8de1bce5
a04de8aaa1ef4527873f7a006c0e757d--f193331bd40d4832a6a36daf8de1bce5
6078151cb5274070a33ef601a1d0248e
f193331bd40d4832a6a36daf8de1bce5--6078151cb5274070a33ef601a1d0248e
b28f5062737344c69e714d3cf4fbd296
6078151cb5274070a33ef601a1d0248e--b28f5062737344c69e714d3cf4fbd296
793081db098840d6b70a8287489b0593
325e8627acf54563a81df65d7cce4a80
440d52368ad247189d9f00953c8b7521--325e8627acf54563a81df65d7cce4a80
b2ab49f763054cdfa9a853405b91a2c7
2
1ab96113e3454870a388e591ea72887e
RX(theta₁)
325e8627acf54563a81df65d7cce4a80--1ab96113e3454870a388e591ea72887e
84ec3cdf1de04f00b6f94aba6637cc12
RY(theta₅)
1ab96113e3454870a388e591ea72887e--84ec3cdf1de04f00b6f94aba6637cc12
689dba56ab3a4380b1fa14c4c60e2df7
RX(theta₉)
84ec3cdf1de04f00b6f94aba6637cc12--689dba56ab3a4380b1fa14c4c60e2df7
2503abaf09814a89b05627ca1684f31b
X
689dba56ab3a4380b1fa14c4c60e2df7--2503abaf09814a89b05627ca1684f31b
2503abaf09814a89b05627ca1684f31b--1de6dda3e52541a0b7817fb20eb0f102
908356aa0c2745e3a5820d6ed0848ae0
2503abaf09814a89b05627ca1684f31b--908356aa0c2745e3a5820d6ed0848ae0
c0ba1c0d839c43e68d85716f5ffe6f56
RX(theta₁₃)
908356aa0c2745e3a5820d6ed0848ae0--c0ba1c0d839c43e68d85716f5ffe6f56
0bcc9a67969847208cd0a94cf5cb3f3c
RY(theta₁₇)
c0ba1c0d839c43e68d85716f5ffe6f56--0bcc9a67969847208cd0a94cf5cb3f3c
0f2b85da415548a985e037f7cfcdcdbb
RX(theta₂₁)
0bcc9a67969847208cd0a94cf5cb3f3c--0f2b85da415548a985e037f7cfcdcdbb
f8b6d808e2b84046b38d3121b80b0453
X
0f2b85da415548a985e037f7cfcdcdbb--f8b6d808e2b84046b38d3121b80b0453
f8b6d808e2b84046b38d3121b80b0453--f193331bd40d4832a6a36daf8de1bce5
beaccafeab954dc8ac33794f2bfb8ae7
f8b6d808e2b84046b38d3121b80b0453--beaccafeab954dc8ac33794f2bfb8ae7
beaccafeab954dc8ac33794f2bfb8ae7--793081db098840d6b70a8287489b0593
77e231de30414ae59f023dc02d3cb6cc
70254aab020d4b3ea563ef4f59ef3b98
b2ab49f763054cdfa9a853405b91a2c7--70254aab020d4b3ea563ef4f59ef3b98
e40215454af8461ea64bf3bcf5d91c31
3
a3f24652b87b40bc808b511aa485183c
RX(theta₂)
70254aab020d4b3ea563ef4f59ef3b98--a3f24652b87b40bc808b511aa485183c
ba08b44dc7ce40cab2844d3ac2e979f3
RY(theta₆)
a3f24652b87b40bc808b511aa485183c--ba08b44dc7ce40cab2844d3ac2e979f3
580053b2625448e4a71ffcad2e095785
RX(theta₁₀)
ba08b44dc7ce40cab2844d3ac2e979f3--580053b2625448e4a71ffcad2e095785
c9c4086b78a4484c8d2ee1ccebd948e8
580053b2625448e4a71ffcad2e095785--c9c4086b78a4484c8d2ee1ccebd948e8
95a9c513003e48ebaa8104fc5b14d77c
X
c9c4086b78a4484c8d2ee1ccebd948e8--95a9c513003e48ebaa8104fc5b14d77c
95a9c513003e48ebaa8104fc5b14d77c--908356aa0c2745e3a5820d6ed0848ae0
c102b718c6f749188cdf162357510f89
RX(theta₁₄)
95a9c513003e48ebaa8104fc5b14d77c--c102b718c6f749188cdf162357510f89
1259469d0e5146b09a75cc276c1c523d
RY(theta₁₈)
c102b718c6f749188cdf162357510f89--1259469d0e5146b09a75cc276c1c523d
fd7a68046d174e4ca3bdb7d041962db3
RX(theta₂₂)
1259469d0e5146b09a75cc276c1c523d--fd7a68046d174e4ca3bdb7d041962db3
7070a36812f74ee688777a2b37497c79
fd7a68046d174e4ca3bdb7d041962db3--7070a36812f74ee688777a2b37497c79
c36eac881f914103b7e9d2ce1a359292
X
7070a36812f74ee688777a2b37497c79--c36eac881f914103b7e9d2ce1a359292
c36eac881f914103b7e9d2ce1a359292--beaccafeab954dc8ac33794f2bfb8ae7
c36eac881f914103b7e9d2ce1a359292--77e231de30414ae59f023dc02d3cb6cc
58f1ad654496466e99b5df54bde48673
66d5bcc9fc41494bb5f251ead81ceffc
X
e40215454af8461ea64bf3bcf5d91c31--66d5bcc9fc41494bb5f251ead81ceffc
66d24a0c72fb468cbfde5b6b01d9f07e
RX(theta₃)
66d5bcc9fc41494bb5f251ead81ceffc--66d24a0c72fb468cbfde5b6b01d9f07e
77f76178bccf4ebbb530db6cfeb1d5d8
RY(theta₇)
66d24a0c72fb468cbfde5b6b01d9f07e--77f76178bccf4ebbb530db6cfeb1d5d8
cb9c4c39edd9483eabf30746d9b21d25
RX(theta₁₁)
77f76178bccf4ebbb530db6cfeb1d5d8--cb9c4c39edd9483eabf30746d9b21d25
6b545a9130094920a6f80db4d119e722
X
cb9c4c39edd9483eabf30746d9b21d25--6b545a9130094920a6f80db4d119e722
6b545a9130094920a6f80db4d119e722--c9c4086b78a4484c8d2ee1ccebd948e8
b36070cbd01b4b36a77257b8be70f036
6b545a9130094920a6f80db4d119e722--b36070cbd01b4b36a77257b8be70f036
bee396d800454f12a09f331bdbea66af
RX(theta₁₅)
b36070cbd01b4b36a77257b8be70f036--bee396d800454f12a09f331bdbea66af
c276102ec3344e98a1ee210e4a4119b2
RY(theta₁₉)
bee396d800454f12a09f331bdbea66af--c276102ec3344e98a1ee210e4a4119b2
5e5bc65a547b4d0d9863e5242f708a0f
RX(theta₂₃)
c276102ec3344e98a1ee210e4a4119b2--5e5bc65a547b4d0d9863e5242f708a0f
d8886c1c96274dfe8126e895458951ab
X
5e5bc65a547b4d0d9863e5242f708a0f--d8886c1c96274dfe8126e895458951ab
d8886c1c96274dfe8126e895458951ab--7070a36812f74ee688777a2b37497c79
9e15d62a607c481f96afb060943059bc
d8886c1c96274dfe8126e895458951ab--9e15d62a607c481f96afb060943059bc
9e15d62a607c481f96afb060943059bc--58f1ad654496466e99b5df54bde48673
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 , 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 ]] )
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.2657-0.1563 j , -0.1378+0.0364 j , -0.0100+0.4277 j , -0.0458-0.2744 j ,
0.5303+0.1397 j , 0.4328-0.2540 j , 0.1917+0.0810 j , 0.1610-0.0493 j ],
[ -0.1124+0.6346 j , 0.0115-0.2532 j , 0.0335+0.0200 j , -0.3132-0.0899 j ,
-0.0593+0.2424 j , -0.0353-0.0099 j , -0.3368+0.1502 j , -0.4531-0.0885 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 )
└── 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 ]] )