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.79202251+0. j 0. + 0.26684655 j 0. -0.52034457 j
0.17531339+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_b56674d6e6a64da5b93f8616afa3e368
Circuit block
cluster_0b523c8911da4e65ac7279d1a0cf1469
Prep block
9e8d768b3ec64acfb6b928a1994c55e5
0
6d3f0c71ca7a41cb90dbc7528b601ead
9e8d768b3ec64acfb6b928a1994c55e5--6d3f0c71ca7a41cb90dbc7528b601ead
e9ae9a4e037e4911bcd4bf20fa77cb47
1
2ad14ca759694dcbb157103b83273e08
RX(theta₀)
6d3f0c71ca7a41cb90dbc7528b601ead--2ad14ca759694dcbb157103b83273e08
ac87b065584c4b7a8cc37d0c26d14bf4
RY(theta₄)
2ad14ca759694dcbb157103b83273e08--ac87b065584c4b7a8cc37d0c26d14bf4
7ca8a60510194930908f542bb698685b
RX(theta₈)
ac87b065584c4b7a8cc37d0c26d14bf4--7ca8a60510194930908f542bb698685b
25fa32709fdf4151931bb51f3b41191f
7ca8a60510194930908f542bb698685b--25fa32709fdf4151931bb51f3b41191f
8377a773195f4f6ba8d30abcfa2c92e2
25fa32709fdf4151931bb51f3b41191f--8377a773195f4f6ba8d30abcfa2c92e2
1cc33a6a576d4cf78322c3c93bc96ba9
RX(theta₁₂)
8377a773195f4f6ba8d30abcfa2c92e2--1cc33a6a576d4cf78322c3c93bc96ba9
d92f635fa84d4e9386c9f95e0a78e89e
RY(theta₁₆)
1cc33a6a576d4cf78322c3c93bc96ba9--d92f635fa84d4e9386c9f95e0a78e89e
347dfa6d410f41709efb3dc53723f75d
RX(theta₂₀)
d92f635fa84d4e9386c9f95e0a78e89e--347dfa6d410f41709efb3dc53723f75d
f260cf401ab44827a8f2edce8bb06dd2
347dfa6d410f41709efb3dc53723f75d--f260cf401ab44827a8f2edce8bb06dd2
de382b17a85d4947b52c7b3986ce9c9b
f260cf401ab44827a8f2edce8bb06dd2--de382b17a85d4947b52c7b3986ce9c9b
64c3e5b8ceed4a469d4079c9ec76b2be
de382b17a85d4947b52c7b3986ce9c9b--64c3e5b8ceed4a469d4079c9ec76b2be
d17cd55b3c704e7bac8f20447c5263ec
3e5593d4cb7347d3b4a71b7fd90403a9
e9ae9a4e037e4911bcd4bf20fa77cb47--3e5593d4cb7347d3b4a71b7fd90403a9
f884b4dbe15b4c67a799ce35b15165e2
2
36084d6dfdcc4eb19942d51542eec39d
RX(theta₁)
3e5593d4cb7347d3b4a71b7fd90403a9--36084d6dfdcc4eb19942d51542eec39d
2d68eb11305b4ecc9008a5d6e1cdfdc7
RY(theta₅)
36084d6dfdcc4eb19942d51542eec39d--2d68eb11305b4ecc9008a5d6e1cdfdc7
3a8010f26a7a4ad49a6a7f88474de6e8
RX(theta₉)
2d68eb11305b4ecc9008a5d6e1cdfdc7--3a8010f26a7a4ad49a6a7f88474de6e8
1ec76017b2d84aaeb9c0b61c437254ff
X
3a8010f26a7a4ad49a6a7f88474de6e8--1ec76017b2d84aaeb9c0b61c437254ff
1ec76017b2d84aaeb9c0b61c437254ff--25fa32709fdf4151931bb51f3b41191f
ddcb19f38d9a4d05b64d532901607cfd
1ec76017b2d84aaeb9c0b61c437254ff--ddcb19f38d9a4d05b64d532901607cfd
00bdb882ff6248768f41cca6decebab7
RX(theta₁₃)
ddcb19f38d9a4d05b64d532901607cfd--00bdb882ff6248768f41cca6decebab7
b0fa564de65b4ab082c408dc3c674e1e
RY(theta₁₇)
00bdb882ff6248768f41cca6decebab7--b0fa564de65b4ab082c408dc3c674e1e
18378b3c8b7345b7a3d5547d1e770f73
RX(theta₂₁)
b0fa564de65b4ab082c408dc3c674e1e--18378b3c8b7345b7a3d5547d1e770f73
e99329d2904e4601884a3062282869e7
X
18378b3c8b7345b7a3d5547d1e770f73--e99329d2904e4601884a3062282869e7
e99329d2904e4601884a3062282869e7--f260cf401ab44827a8f2edce8bb06dd2
3121e28b1e8b4bbc934895233ff7c5ca
e99329d2904e4601884a3062282869e7--3121e28b1e8b4bbc934895233ff7c5ca
3121e28b1e8b4bbc934895233ff7c5ca--d17cd55b3c704e7bac8f20447c5263ec
665e0d1eb98542f7ac86e5a0d54c0a6f
f610e7c656e04531a1080df2b26af5c3
f884b4dbe15b4c67a799ce35b15165e2--f610e7c656e04531a1080df2b26af5c3
d344511b0896447b910436515fbf9975
3
170f172cd7bb4b7aa03f85570e2086ad
RX(theta₂)
f610e7c656e04531a1080df2b26af5c3--170f172cd7bb4b7aa03f85570e2086ad
bd130024149d47f6a346e4102c7ad186
RY(theta₆)
170f172cd7bb4b7aa03f85570e2086ad--bd130024149d47f6a346e4102c7ad186
956ceaac32cf426698320b83401e9aaf
RX(theta₁₀)
bd130024149d47f6a346e4102c7ad186--956ceaac32cf426698320b83401e9aaf
17b7606720d64948b0df873831ad696f
956ceaac32cf426698320b83401e9aaf--17b7606720d64948b0df873831ad696f
26d4a928264e4ad79b97c0c401b70ef4
X
17b7606720d64948b0df873831ad696f--26d4a928264e4ad79b97c0c401b70ef4
26d4a928264e4ad79b97c0c401b70ef4--ddcb19f38d9a4d05b64d532901607cfd
6d67c0af80884fabadf16d7e49059fc6
RX(theta₁₄)
26d4a928264e4ad79b97c0c401b70ef4--6d67c0af80884fabadf16d7e49059fc6
1c5d88663c394091836aeba78abe5fe9
RY(theta₁₈)
6d67c0af80884fabadf16d7e49059fc6--1c5d88663c394091836aeba78abe5fe9
cde517ecc6bc4f9a8ccde39ba1d38976
RX(theta₂₂)
1c5d88663c394091836aeba78abe5fe9--cde517ecc6bc4f9a8ccde39ba1d38976
c9c446644d4b48c0af92b820f5d21c4f
cde517ecc6bc4f9a8ccde39ba1d38976--c9c446644d4b48c0af92b820f5d21c4f
c7c325cbf2b7488c911ffd7f8e369ec2
X
c9c446644d4b48c0af92b820f5d21c4f--c7c325cbf2b7488c911ffd7f8e369ec2
c7c325cbf2b7488c911ffd7f8e369ec2--3121e28b1e8b4bbc934895233ff7c5ca
c7c325cbf2b7488c911ffd7f8e369ec2--665e0d1eb98542f7ac86e5a0d54c0a6f
204ddf24c80f4411a3be963cc1cbc371
cf7ff9cdcb674548869e2b8e101965b6
X
d344511b0896447b910436515fbf9975--cf7ff9cdcb674548869e2b8e101965b6
a1a6b2fc034e4cfbb0108900fe3475c3
RX(theta₃)
cf7ff9cdcb674548869e2b8e101965b6--a1a6b2fc034e4cfbb0108900fe3475c3
500e877aef134765ba2099f619b033d5
RY(theta₇)
a1a6b2fc034e4cfbb0108900fe3475c3--500e877aef134765ba2099f619b033d5
f6c2a6553f81412c8eae1a089c0bf62b
RX(theta₁₁)
500e877aef134765ba2099f619b033d5--f6c2a6553f81412c8eae1a089c0bf62b
3f6b5cecb72d4c00a7be51f8a105b46b
X
f6c2a6553f81412c8eae1a089c0bf62b--3f6b5cecb72d4c00a7be51f8a105b46b
3f6b5cecb72d4c00a7be51f8a105b46b--17b7606720d64948b0df873831ad696f
ea8ad21807a541b69060873c74c922a3
3f6b5cecb72d4c00a7be51f8a105b46b--ea8ad21807a541b69060873c74c922a3
2e95d67cc527418aaa1a4c2499c46222
RX(theta₁₅)
ea8ad21807a541b69060873c74c922a3--2e95d67cc527418aaa1a4c2499c46222
fb67bf9f046e4f88a1251bcaf5680d88
RY(theta₁₉)
2e95d67cc527418aaa1a4c2499c46222--fb67bf9f046e4f88a1251bcaf5680d88
7e000fb399714f0e8dfe63cba7eac487
RX(theta₂₃)
fb67bf9f046e4f88a1251bcaf5680d88--7e000fb399714f0e8dfe63cba7eac487
2a25ddfe95424a50b6d3a6a2362d3ba3
X
7e000fb399714f0e8dfe63cba7eac487--2a25ddfe95424a50b6d3a6a2362d3ba3
2a25ddfe95424a50b6d3a6a2362d3ba3--c9c446644d4b48c0af92b820f5d21c4f
98060d994c694c2980ac8f139accaca5
2a25ddfe95424a50b6d3a6a2362d3ba3--98060d994c694c2980ac8f139accaca5
98060d994c694c2980ac8f139accaca5--204ddf24c80f4411a3be963cc1cbc371
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 ]] )
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 , 1.+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.2027-0.1964 j , -0.3514-0.1442 j , 0.1544-0.3021 j , 0.2899+0.3444 j ,
0.4650-0.2876 j , 0.0324+0.3107 j , -0.1282-0.1695 j , 0.1280-0.0138 j ],
[ 0.5771+0.2875 j , -0.0638+0.2801 j , 0.1174+0.2388 j , -0.0277+0.1725 j ,
0.0063-0.1267 j , -0.1059+0.0650 j , -0.0797-0.4300 j , -0.4060+0.1131 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 ]] )