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.93701774+0. j 0. + 0.05709562 j 0. + 0.34394566 j
-0.02095776+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_692e3a20f9a746739bed164e21b4b066
Circuit block
cluster_d17f02db10ed46ffb06c97d3ee2283a7
Prep block
71fce36cd79f4715a3b74b50647be0e7
0
9325d50ea8994f618998fe4be575981a
71fce36cd79f4715a3b74b50647be0e7--9325d50ea8994f618998fe4be575981a
a8e1dd121aeb445d829f37cb74d2adaa
1
8a9704b1c5834765b79ae570479d36f6
RX(theta₀)
9325d50ea8994f618998fe4be575981a--8a9704b1c5834765b79ae570479d36f6
8d0f2a4e8fca4238957a10069dbbd7e6
RY(theta₄)
8a9704b1c5834765b79ae570479d36f6--8d0f2a4e8fca4238957a10069dbbd7e6
6b389b2cd28d41adb3bd971c616d285b
RX(theta₈)
8d0f2a4e8fca4238957a10069dbbd7e6--6b389b2cd28d41adb3bd971c616d285b
6f1acf190f324e0aaca5c7ca4685528b
6b389b2cd28d41adb3bd971c616d285b--6f1acf190f324e0aaca5c7ca4685528b
9279766e892148398d52d3d176526d06
6f1acf190f324e0aaca5c7ca4685528b--9279766e892148398d52d3d176526d06
1f9e03a47f1f41bcb2423721d9cb93db
RX(theta₁₂)
9279766e892148398d52d3d176526d06--1f9e03a47f1f41bcb2423721d9cb93db
05691c8cca454bc583a0f2ea6403a8d1
RY(theta₁₆)
1f9e03a47f1f41bcb2423721d9cb93db--05691c8cca454bc583a0f2ea6403a8d1
ec42476ce1d1436895de56bdbe8df581
RX(theta₂₀)
05691c8cca454bc583a0f2ea6403a8d1--ec42476ce1d1436895de56bdbe8df581
2bf9fd97edbb4e5dac5fb43d37f09d10
ec42476ce1d1436895de56bdbe8df581--2bf9fd97edbb4e5dac5fb43d37f09d10
179c1004f092431f8ab33affa9bfdaa6
2bf9fd97edbb4e5dac5fb43d37f09d10--179c1004f092431f8ab33affa9bfdaa6
abd1dd3564b54bec8538f52f602c7a7e
179c1004f092431f8ab33affa9bfdaa6--abd1dd3564b54bec8538f52f602c7a7e
884df4d2ee6f4d8abd14b3bd467da353
b7d980e672ed4a35bbd3b4fa06b10540
a8e1dd121aeb445d829f37cb74d2adaa--b7d980e672ed4a35bbd3b4fa06b10540
f9eb2bce9f724f75be7a982118a1c2fc
2
1264f4f5174443488cf1d8e57cd7a942
RX(theta₁)
b7d980e672ed4a35bbd3b4fa06b10540--1264f4f5174443488cf1d8e57cd7a942
5f194d9676484e04a62402f23a17c4d4
RY(theta₅)
1264f4f5174443488cf1d8e57cd7a942--5f194d9676484e04a62402f23a17c4d4
f367402551dd4d278c7b2ae698eb052f
RX(theta₉)
5f194d9676484e04a62402f23a17c4d4--f367402551dd4d278c7b2ae698eb052f
96ebdaf6d5964c2f838a2e63630c855a
X
f367402551dd4d278c7b2ae698eb052f--96ebdaf6d5964c2f838a2e63630c855a
96ebdaf6d5964c2f838a2e63630c855a--6f1acf190f324e0aaca5c7ca4685528b
a2b886e8822c4c6d955d3c7e34f792e4
96ebdaf6d5964c2f838a2e63630c855a--a2b886e8822c4c6d955d3c7e34f792e4
736d0fde014c42f399684b6bc7767262
RX(theta₁₃)
a2b886e8822c4c6d955d3c7e34f792e4--736d0fde014c42f399684b6bc7767262
4ba3e9646223431fa1286b427af73976
RY(theta₁₇)
736d0fde014c42f399684b6bc7767262--4ba3e9646223431fa1286b427af73976
5d5bb260b7424543b211bae3a3370944
RX(theta₂₁)
4ba3e9646223431fa1286b427af73976--5d5bb260b7424543b211bae3a3370944
14f841117584454bb125207ef40def22
X
5d5bb260b7424543b211bae3a3370944--14f841117584454bb125207ef40def22
14f841117584454bb125207ef40def22--2bf9fd97edbb4e5dac5fb43d37f09d10
ad12b4a1e614426d933cf4700bb1e0bb
14f841117584454bb125207ef40def22--ad12b4a1e614426d933cf4700bb1e0bb
ad12b4a1e614426d933cf4700bb1e0bb--884df4d2ee6f4d8abd14b3bd467da353
9da1560cb28a4963b03287243b414fe3
99dafceb7efe40a696172c0734b25fe1
f9eb2bce9f724f75be7a982118a1c2fc--99dafceb7efe40a696172c0734b25fe1
89312e3058b54863b211fa5adfa9668b
3
1b478fe902c148d2be2c47fe1d7617bb
RX(theta₂)
99dafceb7efe40a696172c0734b25fe1--1b478fe902c148d2be2c47fe1d7617bb
3f7e5337d77a468dab3af76badf2100f
RY(theta₆)
1b478fe902c148d2be2c47fe1d7617bb--3f7e5337d77a468dab3af76badf2100f
7f9b5da1032f4330b4893c5608895796
RX(theta₁₀)
3f7e5337d77a468dab3af76badf2100f--7f9b5da1032f4330b4893c5608895796
50a0d747e682413ab37185908a573d97
7f9b5da1032f4330b4893c5608895796--50a0d747e682413ab37185908a573d97
8fffcaf3ae364400a9e3e581e4875ff1
X
50a0d747e682413ab37185908a573d97--8fffcaf3ae364400a9e3e581e4875ff1
8fffcaf3ae364400a9e3e581e4875ff1--a2b886e8822c4c6d955d3c7e34f792e4
521a7166b8bc4e808e3fa06b5ae77e1c
RX(theta₁₄)
8fffcaf3ae364400a9e3e581e4875ff1--521a7166b8bc4e808e3fa06b5ae77e1c
8037c83e579549f1a230e0d5f1e005fc
RY(theta₁₈)
521a7166b8bc4e808e3fa06b5ae77e1c--8037c83e579549f1a230e0d5f1e005fc
b3b45eb57c094318b65ca8f825606290
RX(theta₂₂)
8037c83e579549f1a230e0d5f1e005fc--b3b45eb57c094318b65ca8f825606290
667d6356c0d244e4af1dd80d58ede61d
b3b45eb57c094318b65ca8f825606290--667d6356c0d244e4af1dd80d58ede61d
9220e66889184bf59696811ce62c1609
X
667d6356c0d244e4af1dd80d58ede61d--9220e66889184bf59696811ce62c1609
9220e66889184bf59696811ce62c1609--ad12b4a1e614426d933cf4700bb1e0bb
9220e66889184bf59696811ce62c1609--9da1560cb28a4963b03287243b414fe3
dec3813a5bfe439f9a41e6792d1d6f90
0319b50a9f254e73ba4d1af8a970382d
X
89312e3058b54863b211fa5adfa9668b--0319b50a9f254e73ba4d1af8a970382d
850862a9ef15475e8aa77c7d8306d215
RX(theta₃)
0319b50a9f254e73ba4d1af8a970382d--850862a9ef15475e8aa77c7d8306d215
6e10c055675a460599356814187b9b91
RY(theta₇)
850862a9ef15475e8aa77c7d8306d215--6e10c055675a460599356814187b9b91
54358b6098ac40b684db89493131147f
RX(theta₁₁)
6e10c055675a460599356814187b9b91--54358b6098ac40b684db89493131147f
fa04187c977f4baaadb901c27e3c362a
X
54358b6098ac40b684db89493131147f--fa04187c977f4baaadb901c27e3c362a
fa04187c977f4baaadb901c27e3c362a--50a0d747e682413ab37185908a573d97
730f8efeb2ba497dbb6fbf9492209773
fa04187c977f4baaadb901c27e3c362a--730f8efeb2ba497dbb6fbf9492209773
8ab8e10e179449629028505f1dc92ad4
RX(theta₁₅)
730f8efeb2ba497dbb6fbf9492209773--8ab8e10e179449629028505f1dc92ad4
4bb3f2b97fa84146a21c7b0ba2882ddd
RY(theta₁₉)
8ab8e10e179449629028505f1dc92ad4--4bb3f2b97fa84146a21c7b0ba2882ddd
7d90e3797f3d42ea8e9e2b4fbed30613
RX(theta₂₃)
4bb3f2b97fa84146a21c7b0ba2882ddd--7d90e3797f3d42ea8e9e2b4fbed30613
ef17da18cd684088b51d04bb31cdf826
X
7d90e3797f3d42ea8e9e2b4fbed30613--ef17da18cd684088b51d04bb31cdf826
ef17da18cd684088b51d04bb31cdf826--667d6356c0d244e4af1dd80d58ede61d
1cf5b1d065ad4fef9de90bef62683bb6
ef17da18cd684088b51d04bb31cdf826--1cf5b1d065ad4fef9de90bef62683bb6
1cf5b1d065ad4fef9de90bef62683bb6--dec3813a5bfe439f9a41e6792d1d6f90
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 , 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.2714+0.0785 j , -0.1087+0.2429 j , -0.4963+0.3840 j , 0.1460+0.4261 j ,
-0.0952-0.0776 j , 0.1443+0.4171 j , 0.0775-0.0652 j , -0.1783-0.0284 j ],
[ 0.0303+0.0078 j , -0.1696-0.1015 j , 0.6217-0.2615 j , 0.1677-0.1973 j ,
0.2207-0.1543 j , 0.4491+0.2522 j , -0.1606+0.1907 j , -0.0576+0.1862 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 ]] )
Density matrices conversion
It is also possible to obtain density matrices from statevectors. They can be passed as inputs to quantum programs performing density matrix based operations such as noisy simulations, when the backend allows such as PyQTorch.
from qadence import product_state , density_mat
init_state = product_state ( "10" )
init_density_matrix = density_mat ( init_state )
final_density_matrix = run ( CNOT ( 0 , 1 ), state = init_density_matrix )
I n i t ial = De ns i t yMa tr ix( [[[ 0.+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 , 0.+0. j , 1.+0. j , 0.+0. j ],
[ 0.+0. j , 0.+0. j , 0.+0. j , 0.+0. j ]]] )
Fi nal = De ns i t yMa tr ix( [[[ 0.-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 , 0.-0. j , 0.-0. j , 0.-0. j ],
[ 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 )
├── 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 ]] )