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.68785575+0. j -0.51406525+0. j 0.41047196+0. j -0.30676399+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_8cf8fb16a14149378cbec5d16865b363
Circuit block
cluster_ad0dac2cef4c4549a5586a4384692058
Prep block
7f138431d3c14a3eb58a2332a15fed11
0
06b69e3bfee140779a927d2f1b0acb99
7f138431d3c14a3eb58a2332a15fed11--06b69e3bfee140779a927d2f1b0acb99
4c1d47c7e73a452fbd22a3fba246cbca
1
1ddacfd27e6c48e8ba5bf655d622a91f
RX(theta₀)
06b69e3bfee140779a927d2f1b0acb99--1ddacfd27e6c48e8ba5bf655d622a91f
9f77cfde37b644d5bf294f10471f7626
RY(theta₄)
1ddacfd27e6c48e8ba5bf655d622a91f--9f77cfde37b644d5bf294f10471f7626
d8087bb14bfc4844aac811274c706694
RX(theta₈)
9f77cfde37b644d5bf294f10471f7626--d8087bb14bfc4844aac811274c706694
e549833f9faf4758a58b0670871b0b08
d8087bb14bfc4844aac811274c706694--e549833f9faf4758a58b0670871b0b08
0e696fef94d84b10aa61e90cd4f1a043
e549833f9faf4758a58b0670871b0b08--0e696fef94d84b10aa61e90cd4f1a043
b1653682f1a64945a831c838459f860c
RX(theta₁₂)
0e696fef94d84b10aa61e90cd4f1a043--b1653682f1a64945a831c838459f860c
4a0a7913e626434f936fca3863fe24c4
RY(theta₁₆)
b1653682f1a64945a831c838459f860c--4a0a7913e626434f936fca3863fe24c4
c650222c818e4252a05dd2666cf89975
RX(theta₂₀)
4a0a7913e626434f936fca3863fe24c4--c650222c818e4252a05dd2666cf89975
448cf69d7a7e40c784543ec9c5c1f08e
c650222c818e4252a05dd2666cf89975--448cf69d7a7e40c784543ec9c5c1f08e
61b4c8da1baa4fc088f54b331e123559
448cf69d7a7e40c784543ec9c5c1f08e--61b4c8da1baa4fc088f54b331e123559
e24ebaa03d7f4c20a78201fdcc2baa0a
61b4c8da1baa4fc088f54b331e123559--e24ebaa03d7f4c20a78201fdcc2baa0a
621ba43619504e928995fbb0e4b8c7b9
94631a567c8f4f93a558f22d962b5f89
4c1d47c7e73a452fbd22a3fba246cbca--94631a567c8f4f93a558f22d962b5f89
487d3fc6262f465f83af8a9be18531e1
2
c8827908620541a8af23534f11f42858
RX(theta₁)
94631a567c8f4f93a558f22d962b5f89--c8827908620541a8af23534f11f42858
d5f2e04a8b824b9e8c7bdf3d2b695a0c
RY(theta₅)
c8827908620541a8af23534f11f42858--d5f2e04a8b824b9e8c7bdf3d2b695a0c
8178e13f70cf428eab8732121b6cda69
RX(theta₉)
d5f2e04a8b824b9e8c7bdf3d2b695a0c--8178e13f70cf428eab8732121b6cda69
7092507b60e34ccf9d184e1af06943c4
X
8178e13f70cf428eab8732121b6cda69--7092507b60e34ccf9d184e1af06943c4
7092507b60e34ccf9d184e1af06943c4--e549833f9faf4758a58b0670871b0b08
78335dd98a1047e688a894b841534522
7092507b60e34ccf9d184e1af06943c4--78335dd98a1047e688a894b841534522
ca4961eaced64c898b234ef739e48e58
RX(theta₁₃)
78335dd98a1047e688a894b841534522--ca4961eaced64c898b234ef739e48e58
c8463c8eaa35439da3c03b18e56ad00f
RY(theta₁₇)
ca4961eaced64c898b234ef739e48e58--c8463c8eaa35439da3c03b18e56ad00f
a962c27b06954a02b9ad39dbb3e536b5
RX(theta₂₁)
c8463c8eaa35439da3c03b18e56ad00f--a962c27b06954a02b9ad39dbb3e536b5
2d1d340105db4a28be931f1d09ea0c99
X
a962c27b06954a02b9ad39dbb3e536b5--2d1d340105db4a28be931f1d09ea0c99
2d1d340105db4a28be931f1d09ea0c99--448cf69d7a7e40c784543ec9c5c1f08e
a5dac2563d3f4cacb5bd5d08b8900d53
2d1d340105db4a28be931f1d09ea0c99--a5dac2563d3f4cacb5bd5d08b8900d53
a5dac2563d3f4cacb5bd5d08b8900d53--621ba43619504e928995fbb0e4b8c7b9
960328f06dfd4ec1b803ecad0d9596b1
584c71e99a7b4ac094a347f6716d190c
487d3fc6262f465f83af8a9be18531e1--584c71e99a7b4ac094a347f6716d190c
203161bb83934d5888c7e0c4546dfd0a
3
5ce0c4a2bce64e12afaeaa9d1d12105d
RX(theta₂)
584c71e99a7b4ac094a347f6716d190c--5ce0c4a2bce64e12afaeaa9d1d12105d
3b88dae7dee64b1f9bb749cae4ccc8f0
RY(theta₆)
5ce0c4a2bce64e12afaeaa9d1d12105d--3b88dae7dee64b1f9bb749cae4ccc8f0
b53969a9e04e41769175725ed4c27266
RX(theta₁₀)
3b88dae7dee64b1f9bb749cae4ccc8f0--b53969a9e04e41769175725ed4c27266
a1c01692f2a84d6fa2aee38a2ccac63a
b53969a9e04e41769175725ed4c27266--a1c01692f2a84d6fa2aee38a2ccac63a
806d8c09eb58408c825d4fbf6aba907d
X
a1c01692f2a84d6fa2aee38a2ccac63a--806d8c09eb58408c825d4fbf6aba907d
806d8c09eb58408c825d4fbf6aba907d--78335dd98a1047e688a894b841534522
ff9018367e3b46488359550946cc3543
RX(theta₁₄)
806d8c09eb58408c825d4fbf6aba907d--ff9018367e3b46488359550946cc3543
80315d79cfa34c0ca8baefce1e94af70
RY(theta₁₈)
ff9018367e3b46488359550946cc3543--80315d79cfa34c0ca8baefce1e94af70
468bf1e11ffd4576aa047d515fdbaedb
RX(theta₂₂)
80315d79cfa34c0ca8baefce1e94af70--468bf1e11ffd4576aa047d515fdbaedb
566993fd47c842a18f064a9440b73778
468bf1e11ffd4576aa047d515fdbaedb--566993fd47c842a18f064a9440b73778
f5fc2e8e5f0047e3a593806fb568c30e
X
566993fd47c842a18f064a9440b73778--f5fc2e8e5f0047e3a593806fb568c30e
f5fc2e8e5f0047e3a593806fb568c30e--a5dac2563d3f4cacb5bd5d08b8900d53
f5fc2e8e5f0047e3a593806fb568c30e--960328f06dfd4ec1b803ecad0d9596b1
236a6c690e884967a00b6ccdd1a5f092
9d0ecae2dff14b17af84cbf91c2ea968
X
203161bb83934d5888c7e0c4546dfd0a--9d0ecae2dff14b17af84cbf91c2ea968
756333a55cdc42089feb33bd01d0bce5
RX(theta₃)
9d0ecae2dff14b17af84cbf91c2ea968--756333a55cdc42089feb33bd01d0bce5
9a9b33a2445d4bf8b069d9fa1a565e0d
RY(theta₇)
756333a55cdc42089feb33bd01d0bce5--9a9b33a2445d4bf8b069d9fa1a565e0d
4b95995493904d58b5c56c8a1ed086dc
RX(theta₁₁)
9a9b33a2445d4bf8b069d9fa1a565e0d--4b95995493904d58b5c56c8a1ed086dc
8f1fb51131a64b9e92a3dc2adc81666f
X
4b95995493904d58b5c56c8a1ed086dc--8f1fb51131a64b9e92a3dc2adc81666f
8f1fb51131a64b9e92a3dc2adc81666f--a1c01692f2a84d6fa2aee38a2ccac63a
a944156010114d1ea53c7b53a6c5aa0e
8f1fb51131a64b9e92a3dc2adc81666f--a944156010114d1ea53c7b53a6c5aa0e
c2d71e1cd3a14084b591ef9f1ad29624
RX(theta₁₅)
a944156010114d1ea53c7b53a6c5aa0e--c2d71e1cd3a14084b591ef9f1ad29624
fc1e46bf94d84995a61c880ab050ed66
RY(theta₁₉)
c2d71e1cd3a14084b591ef9f1ad29624--fc1e46bf94d84995a61c880ab050ed66
e7ce233f6d8043a1aa16f0e8102aa650
RX(theta₂₃)
fc1e46bf94d84995a61c880ab050ed66--e7ce233f6d8043a1aa16f0e8102aa650
dc65c05a8f824467abee9b4caf5140dc
X
e7ce233f6d8043a1aa16f0e8102aa650--dc65c05a8f824467abee9b4caf5140dc
dc65c05a8f824467abee9b4caf5140dc--566993fd47c842a18f064a9440b73778
1a0387bf8f3c4a81871f4d796556832d
dc65c05a8f824467abee9b4caf5140dc--1a0387bf8f3c4a81871f4d796556832d
1a0387bf8f3c4a81871f4d796556832d--236a6c690e884967a00b6ccdd1a5f092
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 , 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 , 0.+0. j , 0.+0. j , 1.+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.1343+0.1411 j , -0.1404-0.0388 j , 0.6885-0.1144 j , -0.0959-0.1422 j ,
-0.1421-0.1117 j , -0.0652+0.1798 j , 0.1188+0.0980 j , -0.3975+0.4163 j ],
[ 0.0151+0.3091 j , 0.5099-0.1773 j , 0.2565+0.2227 j , -0.0893-0.3264 j ,
-0.4148+0.0463 j , 0.2270+0.1741 j , -0.2717+0.1207 j , -0.1037-0.1665 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 )
├── X( 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 ]] )