Introductory Tutorial

This tutorial will illustrate the basics of how to use |toqito⟩. This will cover how to instantiate and use the fundamental objects that |toqito⟩ provides; namely quantum states, channels, and measurements.

This is an introduction to the functionality in |toqito⟩ and is not meant to serve as an introduction to quantum information. For more information, please consult the book [1] or the freely available lecture notes [2].

This tutorial assumes you have |toqito⟩ installed on your machine. If you do not, please consult the installation instructions in Getting started.

States

A quantum state is a density operator

\[\rho \in \text{D}(\mathcal{X})\]

where \(\mathcal{X}\) is a complex Euclidean space and where \(\text{D}(\cdot)\) represents the set of density matrices, that is, the set of matrices that are positive semidefinite with trace equal to \(1\).

Quantum States

A complete overview of the scope of quantum states can be found here

The standard basis ket vectors given as \(|0\rangle\) and \(|1\rangle\) where

\[| 0 \rangle = [1, 0]^{\text{T}} \quad \text{and} \quad | 1 \rangle = [0, 1]^{\text{T}}\]

can be defined in |toqito⟩ as such

41 from toqito.matrices import standard_basis
42
43 # |0>
44 standard_basis(2)[0]
array([[1.],
       [0.]])

To get the other ket

49 # |1>
50 standard_basis(2)[1]
array([[0.],
       [1.]])

One may define one of the four Bell states written as

\[u_0 = \frac{1}{\sqrt{2}} \left(| 00 \rangle + | 11 \rangle \right)\]

using |toqito⟩ as

60 import numpy as np
61
62 e_0, e_1 = standard_basis(2)
63 u_0 = 1 / np.sqrt(2) * (np.kron(e_0, e_0) + np.kron(e_1, e_1))
64 u_0
array([[0.70710678],
       [0.        ],
       [0.        ],
       [0.70710678]])

The corresponding density operator of \(u_0\) can be obtained from

\[\begin{split}\rho_0 = u_0 u_0^* = \frac{1}{2} \begin{pmatrix} 1 & 0 & 0 & 1 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 1 & 0 & 0 & 1 \end{pmatrix} \in \text{D}(\mathcal{X}).\end{split}\]

In |toqito⟩, that can be obtained as

81 import numpy as np
82
83 e_0, e_1 = standard_basis(2)
84 u_0 = 1 / np.sqrt(2) * (np.kron(e_0, e_0) + np.kron(e_1, e_1))
85 rho_0 = u_0 @ u_0.conj().T
86 rho_0
array([[0.5, 0. , 0. , 0.5],
       [0. , 0. , 0. , 0. ],
       [0. , 0. , 0. , 0. ],
       [0.5, 0. , 0. , 0.5]])

Alternatively, we may leverage the bell function in |toqito⟩ to generate all four Bell states defined as

\[\begin{split}\begin{aligned} u_0 = \frac{1}{\sqrt{2}} \left(| 00 \rangle + | 11 \rangle \right), &\quad u_1 = \frac{1}{\sqrt{2}} \left(| 00 \rangle - | 11 \rangle \right), \\ u_2 = \frac{1}{\sqrt{2}} \left(| 01 \rangle + | 10 \rangle \right), &\quad u_3 = \frac{1}{\sqrt{2}} \left(| 01 \rangle - | 10 \rangle \right), \end{aligned}\end{split}\]

in a more concise manner as

103 import numpy as np
104
105 from toqito.states import bell
106
107 bell(0)
array([[0.70710678],
       [0.        ],
       [0.        ],
       [0.70710678]])

The Bell states constitute one such well-known class of quantum states. There are many other classes of states that are widely used in the field of quantum information. For instance, the GHZ state

\[| GHZ \rangle = \frac{1}{\sqrt{2}} \left( | 000 \rangle + | 111 \rangle \right)\]

is a well-known 3-qubit quantum state. We can invoke this using |toqito⟩ as

119 from toqito.states import ghz
120
121 ghz(2, 3)
array([[0.70710678],
       [0.        ],
       [0.        ],
       [0.        ],
       [0.        ],
       [0.        ],
       [0.        ],
       [0.70710678]])

While the 3-qubit form of the GHZ state is arguably the most notable, it is possible to define a generalized GHZ state

\[| GHZ_n \rangle = \frac{1}{\sqrt{n}} \left( | 0 \rangle^{\otimes n} + | 1 \rangle^{\otimes n} \right).\]

This generalized state may be obtained in |toqito⟩ as well. For instance, here is the GHZ state \(\mathbb{C}^{4^{\otimes 7}}\) as

\[\frac{1}{\sqrt{30}} \left(| 0000000 \rangle + 2| 1111111 \rangle + 3| 2222222 \rangle + 4| 3333333\rangle \right).\]
139 import numpy as np
140
141 from toqito.states import ghz
142
143 dim = 4
144 num_parties = 7
145 coeffs = [1 / np.sqrt(30), 2 / np.sqrt(30), 3 / np.sqrt(30), 4 / np.sqrt(30)]
146 vec = ghz(dim, num_parties, coeffs)
147 for idx in np.nonzero(vec)[0]:
148     print(f"Index: {int(idx)}, Value: {vec[idx][0]:.8f}")
Index: 0, Value: 0.18257419
Index: 5461, Value: 0.36514837
Index: 10922, Value: 0.54772256
Index: 16383, Value: 0.73029674

Properties of Quantum States

Given a quantum state, it is often useful to be able to determine certain properties of the state.

For instance, we can check if a quantum state is pure, that is, if the density matrix that describes the state has rank 1.

Any one of the Bell states serve as an example of a pure state

163 from toqito.state_props import is_pure
164 from toqito.states import bell
165
166 rho = bell(0) @ bell(0).conj().T
167 is_pure(rho)
True

Another property that is useful is whether a given state is PPT (positive partial transpose), that is, whether the state remains positive after taking the partial transpose of the state.

For quantum states consisting of shared systems of either dimension \(2 \otimes 2\) or \(2 \otimes 3\), the notion of whether a state is PPT serves as a method to determine whether a given quantum state is entangled or separable.

As an example, any one of the Bell states constitute a canonical maximally entangled state over \(2 \otimes 2\) and therefore should not satisfy the PPT criterion.

184 from toqito.state_props import is_ppt
185 from toqito.states import bell
186
187 rho = bell(2) @ bell(2).conj().T
188 is_ppt(rho)
False

As we can see, the PPT criterion is False for an entangled state in \(2 \otimes 2\).

Determining whether a quantum state is separable or entangled is often useful but is, unfortunately, NP-hard. For a given density matrix represented by a quantum state, we can use |toqito⟩ to run a number of separability tests from the literature to determine if it is separable or entangled.

For instance, the following bound-entangled tile state is found to be entangled (i.e. not separable).

203 import numpy as np
204
205 from toqito.state_props import is_separable
206 from toqito.states import tile
207
208 rho = np.identity(9)
209 for i in range(5):
210     rho -= tile(i) @ tile(i).conj().T
211
212 rho /= 4
213 is_separable(rho)
False

Further properties that one can check via |toqito⟩ may be found on this page.

Distance Metrics for Quantum States

Given two quantum states, it is often useful to have some way in which to quantify how similar or different one state is from another.

One well known metric is the fidelity function defined for two quantum states. For two states \(\rho\) and \(\sigma\), one defines the fidelity between \(\rho\) and \(\sigma\) as

\[|| \sqrt{\rho} \sqrt{\sigma} ||_1,\]

where \(|| \cdot ||_1\) denotes the trace norm.

The fidelity function yields a value between \(0\) and \(1\), with \(0\) representing the scenario where \(\rho\) and \(\sigma\) are as different as can be and where a value of \(1\) indicates a scenario where \(\rho\) and \(\sigma\) are identical.

Let us consider an example in |toqito⟩ where we wish to calculate the fidelity function between quantum states that happen to be identical.

243 import numpy as np
244
245 from toqito.state_metrics import fidelity
246 from toqito.states import bell
247
248 # Define two identical density operators.
249 rho = bell(0) @ bell(0).conj().T
250 sigma = bell(0) @ bell(0).conj().T
251
252 # Calculate the fidelity between `rho` and `sigma`
253 np.around(fidelity(rho, sigma), decimals=2)
np.float64(1.0)

There are a number of other metrics one can compute on two density matrices including the trace norm, trace distance. These and others are also available in |toqito⟩. For a full list of distance metrics one can compute on quantum states, consult the docs.

Channels

A quantum channel can be defined as a completely positive and trace preserving linear map.

More formally, let \(\mathcal{X}\) and \(\mathcal{Y}\) represent complex Euclidean spaces and let \(\text{L}(\cdot)\) represent the set of linear operators. Then a quantum channel, \(\Phi\) is defined as

\[\Phi: \text{L}(\mathcal{X}) \rightarrow \text{L}(\mathcal{Y})\]

such that \(\Phi\) is completely positive and trace preserving.

Quantum Channels

The partial trace operation is an often used in various applications of quantum information. The partial trace is defined as

\[\left( \text{Tr} \otimes \mathbb{I}_{\mathcal{Y}} \right) \left(X \otimes Y \right) = \text{Tr}(X)Y\]

where \(X \in \text{L}(\mathcal{X})\) and \(Y \in \text{L}(\mathcal{Y})\) are linear operators over complex Euclidean spaces \(\mathcal{X}\) and \(\mathcal{Y}\).

Consider the following matrix

\[\begin{split}X = \begin{pmatrix} 1 & 2 & 3 & 4 \\ 5 & 6 & 7 & 8 \\ 9 & 10 & 11 & 12 \\ 13 & 14 & 15 & 16 \end{pmatrix}.\end{split}\]

Taking the partial trace over the second subsystem of \(X\) yields the following matrix

\[\begin{split}\text{Tr}_B(X) = \begin{pmatrix} 7 & 11 \\ 23 & 27 \end{pmatrix}.\end{split}\]

By default, the partial trace function in |toqito⟩ takes the trace of the second subsystem.

311 import numpy as np
312
313 from toqito.matrix_ops import partial_trace
314
315 test_input_mat = np.arange(1, 17).reshape(4, 4)
316 partial_trace(test_input_mat)
array([[ 7, 11],
       [23, 27]])

By specifying the sys = [0] argument, we can perform the partial trace over the first subsystem (instead of the default second subsystem as done above). Performing the partial trace over the first subsystem yields the following matrix

\[\begin{split}X_{pt, 1} = \begin{pmatrix} 12 & 14 \\ 20 & 22 \end{pmatrix}.\end{split}\]
330 import numpy as np
331
332 from toqito.matrix_ops import partial_trace
333
334 test_input_mat = np.arange(1, 17).reshape(4, 4)
335 partial_trace(test_input_mat, sys=[0])
array([[12, 14],
       [20, 22]])

Another often useful channel is the partial transpose. The partial transpose is defined as

\[\left( \text{T} \otimes \mathbb{I}_{\mathcal{Y}} \right) \left(X\right)\]

where \(X \in \text{L}(\mathcal{X})\) is a linear operator over the complex Euclidean space \(\mathcal{X}\) and where \(\text{T}\) is the transpose mapping \(\text{T} \in \text{T}(\mathcal{X})\) defined as

\[\text{T}(X) = X^{\text{T}}\]

for all \(X \in \text{L}(\mathcal{X})\).

Consider the following matrix

\[\begin{split}X = \begin{pmatrix} 1 & 2 & 3 & 4 \\ 5 & 6 & 7 & 8 \\ 9 & 10 & 11 & 12 \\ 13 & 14 & 15 & 16 \end{pmatrix}.\end{split}\]

Performing the partial transpose on the matrix \(X\) over the second subsystem yields the following matrix

\[\begin{split}X^{T_B} = \begin{pmatrix} 1 & 5 & 3 & 7 \\ 2 & 6 & 4 & 8 \\ 9 & 13 & 11 & 15 \\ 10 & 14 & 12 & 16 \end{pmatrix}.\end{split}\]

By default, in |toqito⟩, the partial transpose function performs the transposition on the second subsystem as follows.

379 import numpy as np
380
381 from toqito.matrix_ops import partial_transpose
382
383 test_input_mat = np.arange(1, 17).reshape(4, 4)
384 partial_transpose(test_input_mat)
array([[ 1,  5,  3,  7],
       [ 2,  6,  4,  8],
       [ 9, 13, 11, 15],
       [10, 14, 12, 16]])

By specifying the sys = [0] argument, we can perform the partial transpose over the first subsystem (instead of the default second subsystem as done above). Performing the partial transpose over the first subsystem yields the following matrix

\[\begin{split}X_{pt, 1} = \begin{pmatrix} 1 & 2 & 9 & 10 \\ 5 & 6 & 13 & 14 \\ 3 & 4 & 11 & 12 \\ 7 & 8 & 15 & 16 \end{pmatrix}.\end{split}\]
401 import numpy as np
402
403 from toqito.matrix_ops import partial_transpose
404
405 test_input_mat = np.arange(1, 17).reshape(4, 4)
406 partial_transpose(test_input_mat, sys=[0])
array([[ 1,  2,  9, 10],
       [ 5,  6, 13, 14],
       [ 3,  4, 11, 12],
       [ 7,  8, 15, 16]])

Applying Quantum Channels

Another important operation when working with quantum channels is applying them to quantum states. apply_channel() in |toqito⟩ provides a convenient way to apply a quantum channel (represented by its Choi matrix) to a given quantum state.

Here, we illustrate how to apply two widely used channels – the depolarizing channel and the dephasing channel – using apply_channel().

Depolarizing Channel

The depolarizing channel replaces a state with the maximally mixed state with probability \(p\) and leaves it unchanged with probability \((1-p)\). Mathematically, it is defined as

\[\mathcal{N}(\rho) = (1-p) \rho + p\,\frac{\mathbb{I}}{d},\]

where \(\mathbb{I}\) is the identity operator and \(d\) is the dimension of the Hilbert space. The example below applies the depolarizing channel with \(p=0.3\) to the computational basis state \(|0\rangle\).

424 import numpy as np
425
426 from toqito.channel_ops import apply_channel
427 from toqito.channels import depolarizing
428
429 # Create a quantum state |0⟩⟨0|.
430 rho = np.array([[1, 0], [0, 0]])
431
432 # Generate the depolarizing channel Choi matrix with noise probability p = 0.3.
433 choi = depolarizing(2, 0.3)
434
435 # Apply the depolarizing channel using apply_channel.
436 output_state = apply_channel(rho, choi)
437 print(output_state)
[[0.65 0.  ]
 [0.   0.35]]

Dephasing Channel

The dephasing channel reduces the off-diagonal elements of a density matrix without changing the diagonal entries, thereby diminishing quantum coherence. It is commonly expressed as

\[\mathcal{N}(\rho) = (1-p) \rho + p\, Z \rho Z,\]

where \(Z\) is the Pauli-Z operator and \(p\) represents the dephasing probability. The example below demonstrates how to apply the dephasing channel with \(p=0.4\) to the plus state \(|+\rangle = \frac{1}{\sqrt{2}}(|0\rangle + |1\rangle)\).

449 import numpy as np
450
451 from toqito.channel_ops import apply_channel
452 from toqito.channels import dephasing
453
454 # Create a quantum state |+⟩⟨+|.
455 rho = np.array([[0.5, 0.5], [0.5, 0.5]])
456
457 # Generate the dephasing channel Choi matrix with dephasing probability p = 0.4.
458 choi = dephasing(2, 0.4)
459
460 # Apply the dephasing channel using apply_channel.
461 output_state = apply_channel(rho, choi)
462 print(output_state)
[[0.5 0.2]
 [0.2 0.5]]

Noisy Channels

Quantum noise channels model the interaction between quantum systems and their environment, resulting in decoherence and loss of quantum information. The |toqito⟩ library provides implementations of common noise models used in quantum information processing.

Phase Damping Channel

The phase damping channel models quantum decoherence where phase information is lost without any energy dissipation. It is characterized by a parameter \(\gamma\) representing the probability of phase decoherence.

\[\begin{split}K_0 = \begin{pmatrix} 1 & 0 \\ 0 & \sqrt{1 - \gamma} \end{pmatrix}, \quad K_1 = \begin{pmatrix} 0 & 0 \\ 0 & \sqrt{\gamma} \end{pmatrix}\end{split}\]

The phase damping channel can be applied to a quantum state as follows:

481 import numpy as np
482
483 from toqito.channels import phase_damping
484
485 # Create a density matrix with coherence.
486 rho = np.array([[1, 0.5], [0.5, 1]])
487
488 # Apply phase damping with γ = 0.2.
489 result = phase_damping(rho, gamma=0.2)
490 print(result)
[[1.       +0.j 0.4472136+0.j]
 [0.4472136+0.j 1.       +0.j]]

Note that the off-diagonal elements (coherences) are reduced by a factor of \(\sqrt{1-\gamma}\), while the diagonal elements (populations) remain unchanged.

Amplitude Damping Channel

The amplitude damping channel models energy dissipation from a quantum system to its environment, such as the spontaneous emission of a photon. It is parameterized by \(\gamma\), representing the probability of losing a quantum of energy.

\[\begin{split}K_0 = \begin{pmatrix} 1 & 0 \\ 0 & \sqrt{1 - \gamma} \end{pmatrix}, \quad K_1 = \begin{pmatrix} 0 & \sqrt{\gamma} \\ 0 & 0 \end{pmatrix}\end{split}\]

Here’s how to use the amplitude damping channel:

505 import numpy as np
506
507 from toqito.channels import amplitude_damping
508
509 # Create a quantum state.
510 rho = np.array([[0.5, 0.5], [0.5, 0.5]])
511
512 # Apply amplitude damping with γ = 0.3.
513 result = amplitude_damping(rho, gamma=0.3)
514 print(result)
[[0.65      +0.j 0.41833001+0.j]
 [0.41833001+0.j 0.35      +0.j]]

Bit-Flip Channel

The bit-flip channel randomly flips the state of a qubit with probability \(p\), analogous to the classical bit-flip error in classical information theory.

\[\begin{split}K_0 = \sqrt{1 - p} \, I = \sqrt{1 - p} \begin{pmatrix} 1 & 0 \\ 0 & 1 \end{pmatrix}, \quad K_1 = \sqrt{p} \, X = \sqrt{p} \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix}\end{split}\]
526 import numpy as np
527
528 from toqito.channels import bitflip
529
530 # Create a quantum state |0⟩⟨0|.
531 rho = np.array([[1, 0], [0, 0]])
532
533 # Apply bit-flip with probability = 0.25.
534 result = bitflip(rho, prob=0.25)
535 print(result)
[[0.75+0.j 0.  +0.j]
 [0.  +0.j 0.25+0.j]]

Observe that the result is a mixed state with 75% probability of being in state \(|0\rangle\) and 25% probability of being in state \(|1\rangle\), as expected for a bit flip error with probability \(p = 0.25\).

Pauli Channel

The Pauli channel is a quantum noise model that applies a probabilistic mixture of Pauli operators to a quantum state. It is defined by a probability vector \((p_0, \ldots, p_{4^q - 1})\), where \(q\) is the number of qubits, and \(P_i\) are the Pauli operators acting on the system.

\[\Phi(\rho) = \sum_{i=0}^{4^q - 1} p_i P_i \rho P_i^\dagger.\]

For example, when \(q = 1\), the Pauli operators are: \(P_0 = I\), \(P_1 = X\), \(P_2 = Y\), and \(P_3 = Z\). For multiple qubits, these operators are extended as tensor products.

It is also worth noting that when

The Pauli channel can be used to apply noise to an input quantum state or generate a Choi matrix.

564 import numpy as np
565
566 from toqito.channels import pauli_channel
567
568 # Define probabilities for single-qubit Pauli operators.
569 probabilities = np.array([0.5, 0.2, 0.2, 0.1])
570
571 # Define an input density matrix.
572 rho = np.array([[1, 0], [0, 0]])
573
574 # Apply the Pauli channel.
575 _, result = pauli_channel(prob=probabilities, input_mat=rho)
576 print(result)
[[0.6+0.j 0. +0.j]
 [0. +0.j 0.4+0.j]]

Here, the probabilities correspond to applying the identity (\(I\)), bit-flip (\(X\)), phase-flip (\(Z\)), and combined bit-phase flip (\(Y\)) operators.

Measurements

A measurement can be defined as a function

\[\mu: \Sigma \rightarrow \text{Pos}(\mathcal{X})\]

satisfying

\[\sum_{a \in \Sigma} \mu(a) = \mathbb{I}_{\mathcal{X}}\]

where \(\Sigma\) represents a set of measurement outcomes and where \(\mu(a)\) represents the measurement operator associated with outcome \(a \in \Sigma\).

POVM

POVM (Positive Operator-Valued Measure) is a set of positive operators that sum up to the identity.

Consider the following matrices:

\[\begin{split}M_0 = \begin{pmatrix} 1 & 0 \\ 0 & 0 \end{pmatrix} \quad \text{and} \quad M_1 = \begin{pmatrix} 0 & 0 \\ 0 & 1 \end{pmatrix}.\end{split}\]

Our function expects this set of operators to be a POVM because it checks if the operators sum up to the identity, ensuring that the measurement outcomes are properly normalized.

622 import numpy as np
623
624 from toqito.measurement_props import is_povm
625
626 meas_1 = np.array([[1, 0], [0, 0]])
627 meas_2 = np.array([[0, 0], [0, 1]])
628 meas = [meas_1, meas_2]
629 is_povm(meas)
True

Random POVM

We may also use random_povm() to randomly generate a POVM, and can verify that a randomly generated set satisfies the criteria for being a POVM set.

638 import numpy as np
639
640 from toqito.measurement_props import is_povm
641 from toqito.rand import random_povm
642
643 dim, num_inputs, num_outputs = 2, 2, 2
644 measurements = random_povm(dim, num_inputs, num_outputs)
645 is_povm([measurements[:, :, 0, 0], measurements[:, :, 0, 1]])
True

Alternatively, the following matrices do not constitute a POVM set.

\[\begin{split}M_0 = \begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix} \quad \text{and} \quad M_1 = \begin{pmatrix} 5 & 6 \\ 7 & 8 \end{pmatrix},\end{split}\]
663 import numpy as np
664
665 from toqito.measurement_props import is_povm
666
667 non_meas_1 = np.array([[1, 2], [3, 4]])
668 non_meas_2 = np.array([[5, 6], [7, 8]])
669 non_meas = [non_meas_1, non_meas_2]
670 is_povm(non_meas)
False

Measurement Operators

Consider the following state:

\[u = \frac{1}{\sqrt{3}} e_0 + \sqrt{\frac{2}{3}} e_1\]

where we define \(u u^* = \rho \in \text{D}(\mathcal{X})\) and \(e_0\) and \(e_1\) are the standard basis vectors.

\[\begin{split}e_0 = \begin{pmatrix} 1 \\ 0 \end{pmatrix} \quad \text{and} \quad e_1 = \begin{pmatrix} 0 \\ 1 \end{pmatrix}\end{split}\]

The measurement operators are defined as shown below:

\[P_0 = e_0 e_0^* \quad \text{and} \quad P_1 = e_1 e_1^*.\]
692 import numpy as np
693
694 from toqito.matrices import standard_basis
695 from toqito.measurement_ops import measure
696
697 e_0, e_1 = standard_basis(2)
698
699 u = (1 / np.sqrt(3)) * e_0 + (np.sqrt(2 / 3)) * e_1
700 rho = u @ u.conj().T
701
702 proj_0 = e_0 @ e_0.conj().T
703 proj_1 = e_1 @ e_1.conj().T

Then the probability of obtaining outcome \(0\) is given by

\[\langle P_0, \rho \rangle = \frac{1}{3}.\]
711 measure(proj_0, rho)
np.float64(0.3333333333333334)

Similarly, the probability of obtaining outcome \(1\) is given by

\[\langle P_1, \rho \rangle = \frac{2}{3}.\]
719 measure(proj_1, rho)
np.float64(0.6666666666666667)

Pretty Good Measurement

Consider “pretty good measurement” on the set of trine states.

The pretty good measurement (PGM), also known as the “square root measurement” is a set of POVMs \((G_1, \ldots, G_n)\) defined as

\[G_i = P^{-1/2} \left(p_i \rho_i\right) P^{-1/2} \quad \text{where} \quad P = \sum_{i=1}^n p_i \rho_i.\]

This measurement was initially defined in [3] and has found applications in quantum state discrimination tasks. While not always optimal, the PGM provides a reasonable measurement strategy that can be computed efficiently.

For example, consider the following trine states:

\[u_0 = |0\rangle, \quad u_1 = -\frac{1}{2}\left(|0\rangle + \sqrt{3}|1\rangle\right), \quad \text{and} \quad u_2 = -\frac{1}{2}\left(|0\rangle - \sqrt{3}|1\rangle\right).\]
742 from toqito.measurements import pretty_good_measurement
743 from toqito.states import trine
744
745 states = trine()
746 probs = [1 / 3, 1 / 3, 1 / 3]
747 pgm = pretty_good_measurement(states, probs)
748 pgm
[array([[0.66666667, 0.        ],
       [0.        , 0.        ]]), array([[0.16666667, 0.28867513],
       [0.28867513, 0.5       ]]), array([[ 0.16666667, -0.28867513],
       [-0.28867513,  0.5       ]])]

Pretty Bad Measurement

Similarly, we can consider so-called “pretty bad measurement” (PBM) on the set of trine states [4].

The pretty bad measurement (PBM) is a set of POVMs \((B_1, \ldots, B_n)\) defined as

\[B_i = \left(P + (n-1)p_i \rho_i\right)^{-1} p_i \rho_i \left(P + (n-1)p_i \rho_i\right)^{-1} \quad \text{where} \quad P = \sum_{i=1}^n p_i \rho_i.\]

Like the PGM, the PBM provides a measurement strategy for quantum state discrimination, but with different properties that can be useful in certain contexts.

\[u_0 = |0\rangle, \quad u_1 = -\frac{1}{2}\left(|0\rangle + \sqrt{3}|1\rangle\right), \quad \text{and} \quad u_2 = -\frac{1}{2}\left(|0\rangle - \sqrt{3}|1\rangle\right).\]
768 from toqito.measurements import pretty_bad_measurement
769 from toqito.states import trine
770
771 states = trine()
772 probs = [1 / 3, 1 / 3, 1 / 3]
773 pbm = pretty_bad_measurement(states, probs)
774 pbm
[array([[0.16666667, 0.        ],
       [0.        , 0.5       ]]), array([[ 0.41666667, -0.14433757],
       [-0.14433757,  0.25      ]]), array([[0.41666667, 0.14433757],
       [0.14433757, 0.25      ]])]

References

Total running time of the script: (0 minutes 0.087 seconds)

Gallery generated by Sphinx-Gallery