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.78316776+0.38817527 j 0. + 0. j -0.21572422+0.43523705 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_991d5031cc494a90aa06fab91316e892
Circuit block
cluster_d30861260a9c43f188db28d9e340e41b
Prep block
d969d29724c74b5db045841114fd6b74
0
f092b17165bb43d99c811bb59ed38cf4
d969d29724c74b5db045841114fd6b74--f092b17165bb43d99c811bb59ed38cf4
d561fb67aa344c6eadcd6c336c3174d4
1
382642cee59047309df7ef47766c95c9
RX(theta₀)
f092b17165bb43d99c811bb59ed38cf4--382642cee59047309df7ef47766c95c9
71e0ec1123414b098cc569215af2346a
RY(theta₄)
382642cee59047309df7ef47766c95c9--71e0ec1123414b098cc569215af2346a
d219f16b5eac4ee488611232573a8aac
RX(theta₈)
71e0ec1123414b098cc569215af2346a--d219f16b5eac4ee488611232573a8aac
647c15b00fae401f94c50d08108d1f75
d219f16b5eac4ee488611232573a8aac--647c15b00fae401f94c50d08108d1f75
70208c4e5e60420684c042a5a866ac56
647c15b00fae401f94c50d08108d1f75--70208c4e5e60420684c042a5a866ac56
86542da964454a198676ad8e337329f2
RX(theta₁₂)
70208c4e5e60420684c042a5a866ac56--86542da964454a198676ad8e337329f2
f734bfac41744c4ea6318f2877a7b19a
RY(theta₁₆)
86542da964454a198676ad8e337329f2--f734bfac41744c4ea6318f2877a7b19a
fdf8d60052e34cc396a8519dd2e10078
RX(theta₂₀)
f734bfac41744c4ea6318f2877a7b19a--fdf8d60052e34cc396a8519dd2e10078
fb71f0458b534acc8bd3ad4ab0f9e760
fdf8d60052e34cc396a8519dd2e10078--fb71f0458b534acc8bd3ad4ab0f9e760
beb8e2c0898e41fca00433887f37b888
fb71f0458b534acc8bd3ad4ab0f9e760--beb8e2c0898e41fca00433887f37b888
bf28bbffe3544402a5a91b49d2486c2c
beb8e2c0898e41fca00433887f37b888--bf28bbffe3544402a5a91b49d2486c2c
89562545eb7f433fb23978ffbb272891
34d0edef382049a39093e286b32f450b
d561fb67aa344c6eadcd6c336c3174d4--34d0edef382049a39093e286b32f450b
b7c5da04d8354f49ad7e77362fc6406b
2
6af6cdd0eeea4823a6185d0ef0f8914e
RX(theta₁)
34d0edef382049a39093e286b32f450b--6af6cdd0eeea4823a6185d0ef0f8914e
6b79320afc334956ad4f2bbd7473770f
RY(theta₅)
6af6cdd0eeea4823a6185d0ef0f8914e--6b79320afc334956ad4f2bbd7473770f
2d177ca021ac4a52b3deaf3ef132d56e
RX(theta₉)
6b79320afc334956ad4f2bbd7473770f--2d177ca021ac4a52b3deaf3ef132d56e
24854a90bb424c40b69563861761ff0d
X
2d177ca021ac4a52b3deaf3ef132d56e--24854a90bb424c40b69563861761ff0d
24854a90bb424c40b69563861761ff0d--647c15b00fae401f94c50d08108d1f75
560bebf06e3e46e4a742a85a00e0ce2c
24854a90bb424c40b69563861761ff0d--560bebf06e3e46e4a742a85a00e0ce2c
044a592b183c47068438b20da2ecfa51
RX(theta₁₃)
560bebf06e3e46e4a742a85a00e0ce2c--044a592b183c47068438b20da2ecfa51
a5a1065ee16c469fb2a1cd3da7ae9c8c
RY(theta₁₇)
044a592b183c47068438b20da2ecfa51--a5a1065ee16c469fb2a1cd3da7ae9c8c
ca5aceb906a2417d8e5bb9bd0c7f5d4d
RX(theta₂₁)
a5a1065ee16c469fb2a1cd3da7ae9c8c--ca5aceb906a2417d8e5bb9bd0c7f5d4d
c689e64aacfb466488a196dcc19f4ae9
X
ca5aceb906a2417d8e5bb9bd0c7f5d4d--c689e64aacfb466488a196dcc19f4ae9
c689e64aacfb466488a196dcc19f4ae9--fb71f0458b534acc8bd3ad4ab0f9e760
f04907cf8a894431ac373af0248c1f9f
c689e64aacfb466488a196dcc19f4ae9--f04907cf8a894431ac373af0248c1f9f
f04907cf8a894431ac373af0248c1f9f--89562545eb7f433fb23978ffbb272891
73dfb1e0c00141fd84125346442e7e0a
e4940a1468bd4db1aa7a18f2c716fc27
b7c5da04d8354f49ad7e77362fc6406b--e4940a1468bd4db1aa7a18f2c716fc27
5f74b65f3e8f49e9bfc8b8d4e8791ba1
3
13f9a9d57d2c4de2bfd5309d284e8394
RX(theta₂)
e4940a1468bd4db1aa7a18f2c716fc27--13f9a9d57d2c4de2bfd5309d284e8394
ae893ed2329d4304b3586e60fa32d9e3
RY(theta₆)
13f9a9d57d2c4de2bfd5309d284e8394--ae893ed2329d4304b3586e60fa32d9e3
390dcf8752fb4c13a9b64ba1103e73a6
RX(theta₁₀)
ae893ed2329d4304b3586e60fa32d9e3--390dcf8752fb4c13a9b64ba1103e73a6
ba4d6eca83814ad7a56f8b94d880d7fb
390dcf8752fb4c13a9b64ba1103e73a6--ba4d6eca83814ad7a56f8b94d880d7fb
1dea952910a6403888a5ffab11444b82
X
ba4d6eca83814ad7a56f8b94d880d7fb--1dea952910a6403888a5ffab11444b82
1dea952910a6403888a5ffab11444b82--560bebf06e3e46e4a742a85a00e0ce2c
b6513f5bdb314606b0c135d0d86ecff7
RX(theta₁₄)
1dea952910a6403888a5ffab11444b82--b6513f5bdb314606b0c135d0d86ecff7
a1523be9282f4926b35c2d0fc9250ca5
RY(theta₁₈)
b6513f5bdb314606b0c135d0d86ecff7--a1523be9282f4926b35c2d0fc9250ca5
686ffeb03154497890d2e4ebd51164e3
RX(theta₂₂)
a1523be9282f4926b35c2d0fc9250ca5--686ffeb03154497890d2e4ebd51164e3
b132fb099f384e48a1ffab49c87c082f
686ffeb03154497890d2e4ebd51164e3--b132fb099f384e48a1ffab49c87c082f
7e8970e2de87439f827acb35573cbf3c
X
b132fb099f384e48a1ffab49c87c082f--7e8970e2de87439f827acb35573cbf3c
7e8970e2de87439f827acb35573cbf3c--f04907cf8a894431ac373af0248c1f9f
7e8970e2de87439f827acb35573cbf3c--73dfb1e0c00141fd84125346442e7e0a
d0c091b5079047c1b0327182015149b8
a1fee463943b4068b69da00e92577dfe
X
5f74b65f3e8f49e9bfc8b8d4e8791ba1--a1fee463943b4068b69da00e92577dfe
fa74bee7ac374c6092b3953c286d3587
RX(theta₃)
a1fee463943b4068b69da00e92577dfe--fa74bee7ac374c6092b3953c286d3587
7b6f610a4efd4f559e2e14d8a922e4cf
RY(theta₇)
fa74bee7ac374c6092b3953c286d3587--7b6f610a4efd4f559e2e14d8a922e4cf
cc8f8387ea794a3ea2fe2764cc5a7c0a
RX(theta₁₁)
7b6f610a4efd4f559e2e14d8a922e4cf--cc8f8387ea794a3ea2fe2764cc5a7c0a
606342449aa940eab905128b4151a674
X
cc8f8387ea794a3ea2fe2764cc5a7c0a--606342449aa940eab905128b4151a674
606342449aa940eab905128b4151a674--ba4d6eca83814ad7a56f8b94d880d7fb
ea53358ba500402eb5761a2da2e662b2
606342449aa940eab905128b4151a674--ea53358ba500402eb5761a2da2e662b2
2da3bf9817f242b3977799835de6466a
RX(theta₁₅)
ea53358ba500402eb5761a2da2e662b2--2da3bf9817f242b3977799835de6466a
adaca6f50c324197b95145dd2f194a2e
RY(theta₁₉)
2da3bf9817f242b3977799835de6466a--adaca6f50c324197b95145dd2f194a2e
a8bfe24293a1455e8d66a669feb0473e
RX(theta₂₃)
adaca6f50c324197b95145dd2f194a2e--a8bfe24293a1455e8d66a669feb0473e
61f7bf26d77a43a28adaee773fb23dd3
X
a8bfe24293a1455e8d66a669feb0473e--61f7bf26d77a43a28adaee773fb23dd3
61f7bf26d77a43a28adaee773fb23dd3--b132fb099f384e48a1ffab49c87c082f
d853a4fac5fe49d4bcc05eafa6a82bf9
61f7bf26d77a43a28adaee773fb23dd3--d853a4fac5fe49d4bcc05eafa6a82bf9
d853a4fac5fe49d4bcc05eafa6a82bf9--d0c091b5079047c1b0327182015149b8
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 , 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 ]] )
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.2606+0.0076 j , -0.4074+0.1547 j , 0.5133-0.1015 j , -0.0119-0.1060 j ,
0.5207+0.0390 j , -0.1361+0.2232 j , -0.0205+0.0557 j , -0.2464-0.2275 j ],
[ 0.0011+0.0747 j , 0.2227-0.3560 j , -0.1053+0.0844 j , -0.1065+0.5197 j ,
-0.1590+0.2325 j , -0.1133+0.1762 j , -0.6188-0.0830 j , -0.0578-0.0459 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 )
├── I( 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 ]] )