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_62976969a46f457cb8c9667c9a84b41d
Circuit block
cluster_3282ce8eb5ac4363b18f4825570c9ced
Prep block
520ffe9ae72846b7a7e56d375e424503
0
ca61a2a77c3145d2b764eadf52418157
520ffe9ae72846b7a7e56d375e424503--ca61a2a77c3145d2b764eadf52418157
af9bdf3af9d6439283a1fc37cb57c107
1
fc04d72076744d1ca201937f3e2d96a3
RX(theta₀)
ca61a2a77c3145d2b764eadf52418157--fc04d72076744d1ca201937f3e2d96a3
d43572e168c4417499c2173fa59440b0
RY(theta₄)
fc04d72076744d1ca201937f3e2d96a3--d43572e168c4417499c2173fa59440b0
557bf28e2a114d009d04ccee053161d5
RX(theta₈)
d43572e168c4417499c2173fa59440b0--557bf28e2a114d009d04ccee053161d5
80836a7929ef40649b6e6a38b019e5c2
557bf28e2a114d009d04ccee053161d5--80836a7929ef40649b6e6a38b019e5c2
2b9f5cc6a5574f7399b1cb961792dadb
80836a7929ef40649b6e6a38b019e5c2--2b9f5cc6a5574f7399b1cb961792dadb
9048c2c6830446fb9f5dfc6dc104245d
RX(theta₁₂)
2b9f5cc6a5574f7399b1cb961792dadb--9048c2c6830446fb9f5dfc6dc104245d
a79ff9670e1b4644a9a1605c8921585d
RY(theta₁₆)
9048c2c6830446fb9f5dfc6dc104245d--a79ff9670e1b4644a9a1605c8921585d
f298602aeef14038a52c1acd1b4aabf0
RX(theta₂₀)
a79ff9670e1b4644a9a1605c8921585d--f298602aeef14038a52c1acd1b4aabf0
a75b6551fb5d467d92fec991962923e4
f298602aeef14038a52c1acd1b4aabf0--a75b6551fb5d467d92fec991962923e4
46243ac4f8f4432c96a50dd6d28fb96e
a75b6551fb5d467d92fec991962923e4--46243ac4f8f4432c96a50dd6d28fb96e
6579697e53504fef8eb75d1b66963c3f
46243ac4f8f4432c96a50dd6d28fb96e--6579697e53504fef8eb75d1b66963c3f
b6e80c2b95444f6da55cdf8d0d88025b
42c89fcf4299450ea6b35124badafd07
af9bdf3af9d6439283a1fc37cb57c107--42c89fcf4299450ea6b35124badafd07
53120add01484919a4c8d72679ead5d2
2
5b86c9f90ce84aae95f125136219577d
RX(theta₁)
42c89fcf4299450ea6b35124badafd07--5b86c9f90ce84aae95f125136219577d
e364e82336a7465192a7e3ab1a594b3c
RY(theta₅)
5b86c9f90ce84aae95f125136219577d--e364e82336a7465192a7e3ab1a594b3c
494af2f3954b4233995363ff4052d098
RX(theta₉)
e364e82336a7465192a7e3ab1a594b3c--494af2f3954b4233995363ff4052d098
cf7853cd07ac469e9ba620d13e956deb
X
494af2f3954b4233995363ff4052d098--cf7853cd07ac469e9ba620d13e956deb
cf7853cd07ac469e9ba620d13e956deb--80836a7929ef40649b6e6a38b019e5c2
0c3e975d38804006adefd520ad1a9310
cf7853cd07ac469e9ba620d13e956deb--0c3e975d38804006adefd520ad1a9310
65a7d705e5ad455ebffc7ef77ca3b409
RX(theta₁₃)
0c3e975d38804006adefd520ad1a9310--65a7d705e5ad455ebffc7ef77ca3b409
b68d11bc21e246a3bc2c5527d40a0c57
RY(theta₁₇)
65a7d705e5ad455ebffc7ef77ca3b409--b68d11bc21e246a3bc2c5527d40a0c57
879f20f90a7a4e02be58dd18e54ee8cf
RX(theta₂₁)
b68d11bc21e246a3bc2c5527d40a0c57--879f20f90a7a4e02be58dd18e54ee8cf
fce5c0ac5f854531b3ce2d7aa2801748
X
879f20f90a7a4e02be58dd18e54ee8cf--fce5c0ac5f854531b3ce2d7aa2801748
fce5c0ac5f854531b3ce2d7aa2801748--a75b6551fb5d467d92fec991962923e4
d51e3c448e8c422f9155340053443d32
fce5c0ac5f854531b3ce2d7aa2801748--d51e3c448e8c422f9155340053443d32
d51e3c448e8c422f9155340053443d32--b6e80c2b95444f6da55cdf8d0d88025b
414276f3367c4c39beaa33c010da691e
a4b8a6e4a2cc48ffa1d99a22be7bcce2
53120add01484919a4c8d72679ead5d2--a4b8a6e4a2cc48ffa1d99a22be7bcce2
3569ee43101c40f793edd301d87843b3
3
eae76bb3602647d89f53a0659ed6aad6
RX(theta₂)
a4b8a6e4a2cc48ffa1d99a22be7bcce2--eae76bb3602647d89f53a0659ed6aad6
a8acebb0e769428e87ba5032b44a8334
RY(theta₆)
eae76bb3602647d89f53a0659ed6aad6--a8acebb0e769428e87ba5032b44a8334
eab833ef951c40febc5ea35f00b00c5b
RX(theta₁₀)
a8acebb0e769428e87ba5032b44a8334--eab833ef951c40febc5ea35f00b00c5b
4f20c8ac6e8c47079295acef2a00e20f
eab833ef951c40febc5ea35f00b00c5b--4f20c8ac6e8c47079295acef2a00e20f
75720122ef9f4e29aeed6f50fb981139
X
4f20c8ac6e8c47079295acef2a00e20f--75720122ef9f4e29aeed6f50fb981139
75720122ef9f4e29aeed6f50fb981139--0c3e975d38804006adefd520ad1a9310
edc80f16b1184c8698708a08b5cbbd62
RX(theta₁₄)
75720122ef9f4e29aeed6f50fb981139--edc80f16b1184c8698708a08b5cbbd62
2c93c568e670429b9414894a638ea853
RY(theta₁₈)
edc80f16b1184c8698708a08b5cbbd62--2c93c568e670429b9414894a638ea853
2065544662fb42e28130b78c9896876d
RX(theta₂₂)
2c93c568e670429b9414894a638ea853--2065544662fb42e28130b78c9896876d
23afd58b0fb54efeab47910a7762bd75
2065544662fb42e28130b78c9896876d--23afd58b0fb54efeab47910a7762bd75
beeef22982d440a3894b4a7ad11a102f
X
23afd58b0fb54efeab47910a7762bd75--beeef22982d440a3894b4a7ad11a102f
beeef22982d440a3894b4a7ad11a102f--d51e3c448e8c422f9155340053443d32
beeef22982d440a3894b4a7ad11a102f--414276f3367c4c39beaa33c010da691e
25938321e16c4e12a460edff9a5132b6
e60ac74de6134bbaa507d4adab915d62
X
3569ee43101c40f793edd301d87843b3--e60ac74de6134bbaa507d4adab915d62
b848bb0152d347d99208b145f5877f41
RX(theta₃)
e60ac74de6134bbaa507d4adab915d62--b848bb0152d347d99208b145f5877f41
eabafc91d5c3407a9fe21ea0052e292c
RY(theta₇)
b848bb0152d347d99208b145f5877f41--eabafc91d5c3407a9fe21ea0052e292c
56f6124e81394f3d823a1e2c1eaf3de1
RX(theta₁₁)
eabafc91d5c3407a9fe21ea0052e292c--56f6124e81394f3d823a1e2c1eaf3de1
4132f0dfe9ab4b69881aa974845d919f
X
56f6124e81394f3d823a1e2c1eaf3de1--4132f0dfe9ab4b69881aa974845d919f
4132f0dfe9ab4b69881aa974845d919f--4f20c8ac6e8c47079295acef2a00e20f
3a108d86fc054c509a41c2a97a17fc61
4132f0dfe9ab4b69881aa974845d919f--3a108d86fc054c509a41c2a97a17fc61
5f0066ecf3b34eaebd077a32568ba838
RX(theta₁₅)
3a108d86fc054c509a41c2a97a17fc61--5f0066ecf3b34eaebd077a32568ba838
89370ef86a534222b42d8e8ff315940e
RY(theta₁₉)
5f0066ecf3b34eaebd077a32568ba838--89370ef86a534222b42d8e8ff315940e
013bf075fa0e43709dc19535987abf11
RX(theta₂₃)
89370ef86a534222b42d8e8ff315940e--013bf075fa0e43709dc19535987abf11
7c04f9d986b34efb92879c50c6a88bb1
X
013bf075fa0e43709dc19535987abf11--7c04f9d986b34efb92879c50c6a88bb1
7c04f9d986b34efb92879c50c6a88bb1--23afd58b0fb54efeab47910a7762bd75
1bacefda4ac641e09461030c98b68cbb
7c04f9d986b34efb92879c50c6a88bb1--1bacefda4ac641e09461030c98b68cbb
1bacefda4ac641e09461030c98b68cbb--25938321e16c4e12a460edff9a5132b6
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 ]] )