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.89790539+0. j -0.17791877+0. j -0.39495107+0. j 0.07825903+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_1101a68aa26e49218030e0127d8c1a04
Circuit block
cluster_d63fc83829e640619e0dbd2b3f35d212
Prep block
6d2b9440f791492eb7b8233e0243bd98
0
74826676cd06473d8c1e37191135b948
6d2b9440f791492eb7b8233e0243bd98--74826676cd06473d8c1e37191135b948
1ada91a624c348488165841be79f48c3
1
4cb5842f52a4492c9db4a8d181541ce0
RX(theta₀)
74826676cd06473d8c1e37191135b948--4cb5842f52a4492c9db4a8d181541ce0
f83c55e2b9fd41339c722e6693c3ade8
RY(theta₄)
4cb5842f52a4492c9db4a8d181541ce0--f83c55e2b9fd41339c722e6693c3ade8
4f58b67aae284bb49f101ed7e94cc866
RX(theta₈)
f83c55e2b9fd41339c722e6693c3ade8--4f58b67aae284bb49f101ed7e94cc866
c009d6fb222e4fe98768cc839a25b96e
4f58b67aae284bb49f101ed7e94cc866--c009d6fb222e4fe98768cc839a25b96e
e01fb2ae970e4beabac715f7332dd3a6
c009d6fb222e4fe98768cc839a25b96e--e01fb2ae970e4beabac715f7332dd3a6
98c1ae999a73463eb938d15c19a32863
RX(theta₁₂)
e01fb2ae970e4beabac715f7332dd3a6--98c1ae999a73463eb938d15c19a32863
378f0c1c97f944f7881152acfc07a08e
RY(theta₁₆)
98c1ae999a73463eb938d15c19a32863--378f0c1c97f944f7881152acfc07a08e
755a9a8b37c44d02b9beb29b1808cf68
RX(theta₂₀)
378f0c1c97f944f7881152acfc07a08e--755a9a8b37c44d02b9beb29b1808cf68
4f247b7b76444a8b846976e43340a1ab
755a9a8b37c44d02b9beb29b1808cf68--4f247b7b76444a8b846976e43340a1ab
d9018a4078e14eed95db3b928f53c6dc
4f247b7b76444a8b846976e43340a1ab--d9018a4078e14eed95db3b928f53c6dc
c1ccb02974064ba1bad4c6e27d197f9b
d9018a4078e14eed95db3b928f53c6dc--c1ccb02974064ba1bad4c6e27d197f9b
3a3911a030c94be8b210f4c8755c0ea8
7ea42b763000499b9dbd19a69322b6b7
1ada91a624c348488165841be79f48c3--7ea42b763000499b9dbd19a69322b6b7
96456103357f478aac935d2b8fc17c67
2
fb9324a7b0724ea884cdeff6a9c46941
RX(theta₁)
7ea42b763000499b9dbd19a69322b6b7--fb9324a7b0724ea884cdeff6a9c46941
bc98407a0d4e4fbe892ecf092a36697f
RY(theta₅)
fb9324a7b0724ea884cdeff6a9c46941--bc98407a0d4e4fbe892ecf092a36697f
f1abe42231d6471da92bbe3f640a9017
RX(theta₉)
bc98407a0d4e4fbe892ecf092a36697f--f1abe42231d6471da92bbe3f640a9017
c11073b507d648e3bb5ec40579162607
X
f1abe42231d6471da92bbe3f640a9017--c11073b507d648e3bb5ec40579162607
c11073b507d648e3bb5ec40579162607--c009d6fb222e4fe98768cc839a25b96e
aa3a681f50ba476b802493b3924412c5
c11073b507d648e3bb5ec40579162607--aa3a681f50ba476b802493b3924412c5
8554480d30da439093c003079bc51d67
RX(theta₁₃)
aa3a681f50ba476b802493b3924412c5--8554480d30da439093c003079bc51d67
686e107ca9b14f48ab5731cfdd08688d
RY(theta₁₇)
8554480d30da439093c003079bc51d67--686e107ca9b14f48ab5731cfdd08688d
c86fb31129cc4629a9d3025f7c139065
RX(theta₂₁)
686e107ca9b14f48ab5731cfdd08688d--c86fb31129cc4629a9d3025f7c139065
57419287744e429a9b942e5dd72fe6b8
X
c86fb31129cc4629a9d3025f7c139065--57419287744e429a9b942e5dd72fe6b8
57419287744e429a9b942e5dd72fe6b8--4f247b7b76444a8b846976e43340a1ab
d70859a97c1b4e41880e0c099bc13e72
57419287744e429a9b942e5dd72fe6b8--d70859a97c1b4e41880e0c099bc13e72
d70859a97c1b4e41880e0c099bc13e72--3a3911a030c94be8b210f4c8755c0ea8
6ecb4e38b3a6482594aee5699879fd26
67dfe4fc214a462dbb2a7a0eb8252343
96456103357f478aac935d2b8fc17c67--67dfe4fc214a462dbb2a7a0eb8252343
f4a09b49edbe482e8e478595f23bb955
3
bedb01118a7843c5b40f14b89c471f19
RX(theta₂)
67dfe4fc214a462dbb2a7a0eb8252343--bedb01118a7843c5b40f14b89c471f19
d83f83393e4a4905bbfba73d66716ea9
RY(theta₆)
bedb01118a7843c5b40f14b89c471f19--d83f83393e4a4905bbfba73d66716ea9
6450e41079754d3f931ee39df30d5b02
RX(theta₁₀)
d83f83393e4a4905bbfba73d66716ea9--6450e41079754d3f931ee39df30d5b02
5667e93558b64cec89e30ab4ae9076be
6450e41079754d3f931ee39df30d5b02--5667e93558b64cec89e30ab4ae9076be
288ee51c326f421085beb29b111bef96
X
5667e93558b64cec89e30ab4ae9076be--288ee51c326f421085beb29b111bef96
288ee51c326f421085beb29b111bef96--aa3a681f50ba476b802493b3924412c5
b1ea7d9351304dafa27f37bbce0fc2ce
RX(theta₁₄)
288ee51c326f421085beb29b111bef96--b1ea7d9351304dafa27f37bbce0fc2ce
0bfa32c0a4ba48a890a36518c6dbdf6e
RY(theta₁₈)
b1ea7d9351304dafa27f37bbce0fc2ce--0bfa32c0a4ba48a890a36518c6dbdf6e
34bb754d1ac0430da7afce3db5580565
RX(theta₂₂)
0bfa32c0a4ba48a890a36518c6dbdf6e--34bb754d1ac0430da7afce3db5580565
09f142b8a44544748b1c5ddeaac0ccdf
34bb754d1ac0430da7afce3db5580565--09f142b8a44544748b1c5ddeaac0ccdf
41c658cf929d4c7d839d46453ca323de
X
09f142b8a44544748b1c5ddeaac0ccdf--41c658cf929d4c7d839d46453ca323de
41c658cf929d4c7d839d46453ca323de--d70859a97c1b4e41880e0c099bc13e72
41c658cf929d4c7d839d46453ca323de--6ecb4e38b3a6482594aee5699879fd26
269c0806b7eb480990bd4a881bb3c59d
8b3471fff2524dd68ea18e0d2c7f24da
X
f4a09b49edbe482e8e478595f23bb955--8b3471fff2524dd68ea18e0d2c7f24da
4c13db85fd7f461ab7f2fab1ca60b884
RX(theta₃)
8b3471fff2524dd68ea18e0d2c7f24da--4c13db85fd7f461ab7f2fab1ca60b884
b164931a9f5c4f2fb66eaac8a8c1ec0a
RY(theta₇)
4c13db85fd7f461ab7f2fab1ca60b884--b164931a9f5c4f2fb66eaac8a8c1ec0a
6b3540d6aebe4c4fa0494fae14cb90a5
RX(theta₁₁)
b164931a9f5c4f2fb66eaac8a8c1ec0a--6b3540d6aebe4c4fa0494fae14cb90a5
7364b3b6ce84404592731800b3dd0b81
X
6b3540d6aebe4c4fa0494fae14cb90a5--7364b3b6ce84404592731800b3dd0b81
7364b3b6ce84404592731800b3dd0b81--5667e93558b64cec89e30ab4ae9076be
e367fe2e83c744a3a302cf7795bece78
7364b3b6ce84404592731800b3dd0b81--e367fe2e83c744a3a302cf7795bece78
e46fe8323e594880a9436e7a8cde5731
RX(theta₁₅)
e367fe2e83c744a3a302cf7795bece78--e46fe8323e594880a9436e7a8cde5731
9fe63edf792745e5ae77ab9cd8ff7f11
RY(theta₁₉)
e46fe8323e594880a9436e7a8cde5731--9fe63edf792745e5ae77ab9cd8ff7f11
c239a81f16bd47939e65c6ca7959ab70
RX(theta₂₃)
9fe63edf792745e5ae77ab9cd8ff7f11--c239a81f16bd47939e65c6ca7959ab70
8cf95ced097b4085beb3dea8245f36ed
X
c239a81f16bd47939e65c6ca7959ab70--8cf95ced097b4085beb3dea8245f36ed
8cf95ced097b4085beb3dea8245f36ed--09f142b8a44544748b1c5ddeaac0ccdf
c149365aabd74be282c9bd718991718b
8cf95ced097b4085beb3dea8245f36ed--c149365aabd74be282c9bd718991718b
c149365aabd74be282c9bd718991718b--269c0806b7eb480990bd4a881bb3c59d
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 , 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.0960-0.0362 j , -0.1035+0.1122 j , 0.0139+0.2543 j , 0.2133+0.1648 j ,
0.4687+0.2195 j , -0.2819+0.0705 j , -0.0940-0.0842 j , 0.5079-0.4499 j ],
[ 0.0447-0.2164 j , -0.1827-0.2467 j , -0.1432+0.0792 j , -0.2743-0.1482 j ,
-0.0855+0.2340 j , 0.1316+0.4042 j , 0.0874-0.5930 j , 0.3484-0.0977 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 )
└── 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 ]] )