UnitaryMatrix

Struct UnitaryMatrix 

Source
pub struct UnitaryMatrix<C: ComplexScalar> { /* private fields */ }
Expand description

A unitary matrix over a qudit system.

This is a thin wrapper around a matrix that ensures it is unitary.

Implementations§

Source§

impl<C: ComplexScalar> UnitaryMatrix<C>

Source

pub fn new<T: Into<Radices>>(radices: T, matrix: Mat<C>) -> Self

Create a new unitary matrix.

§Arguments
  • radices - The radices of the qudit system.

  • matrix - The matrix to wrap.

§Panics

Panics if the matrix is not unitary.

§Example
use faer::Mat;
use qudit_core::UnitaryMatrix;
use qudit_core::c64;
let unitary: UnitaryMatrix<c64> = UnitaryMatrix::new([2, 2], Mat::<c64>::identity(4, 4));
§See Also
Source

pub fn new_unchecked<T: Into<Radices>>(radices: T, matrix: Mat<C>) -> Self

Create a new unitary matrix without checking if it is unitary.

§Arguments
  • radices - The radices of the qudit system.

  • matrix - The matrix to wrap.

§Safety

The caller must ensure that the provided matrix is unitary.

§Example
use faer::Mat;
use qudit_core::UnitaryMatrix;
use qudit_core::c64;
let unitary: UnitaryMatrix<c64> = UnitaryMatrix::new_unchecked([2, 2], Mat::identity(4, 4));
§See Also
Source

pub fn identity<T: Into<Radices>>(radices: T) -> Self

Create a new identity unitary matrix for a given qudit system.

§Arguments
  • radices - The radices of the qudit system.
§Returns

A new unitary matrix that is the identity.

§Example
use faer::Mat;
use qudit_core::UnitaryMatrix;
use qudit_core::c64;
let unitary: UnitaryMatrix<c64> = UnitaryMatrix::identity([2, 2]);
assert_eq!(unitary, UnitaryMatrix::new([2, 2], Mat::identity(4, 4)));
§See Also
Source

pub fn random<T: Into<Radices>>(radices: T) -> Self

Generate a random Unitary from the haar distribution.

Reference:

§Arguments
  • radices - The radices of the qudit system.
§Returns

A new unitary matrix that is random.

§Example
use qudit_core::c64;
use qudit_core::UnitaryMatrix;
let unitary: UnitaryMatrix<c64> = UnitaryMatrix::random([2, 2]);
assert!(UnitaryMatrix::is_unitary(&unitary));
§See Also
Source

pub fn is_unitary(mat: impl AsMatRef<T = C, Rows = usize, Cols = usize>) -> bool

Check if a matrix is unitary.

A matrix is unitary if it satisfies the following condition:

U U^\dagger = U^\dagger U = I

Where U is the matrix, U^\dagger is the dagger (conjugate-transpose) of U, and I is the identity matrix of the same size.

§Arguments
  • mat - The matrix to check.
§Returns

true if the matrix is unitary, false otherwise.

§Example
use qudit_core::c64;
use faer::mat;
use faer::Mat;
use qudit_core::UnitaryMatrix;
let mat: Mat<c64> = Mat::identity(2, 2);
assert!(UnitaryMatrix::is_unitary(&mat));

let mat = Mat::from_fn(2, 2, |_, _| c64::new(1.0, 1.0));
assert!(!UnitaryMatrix::is_unitary(&mat));
§Notes

The function checks the l2 norm or frobenius norm of the difference between the product of the matrix and its adjoint and the identity. Due to floating point errors, the norm is checked against a threshold defined by the THRESHOLD constant in the ComplexScalar trait.

§See Also
Source

pub fn get_distance_from( &self, x: impl AsMatRef<T = C, Rows = usize, Cols = usize>, ) -> C::R

Global-phase-agnostic, psuedo-metric over the space of unitaries.

This is based on the hilbert-schmidt inner product. It is defined as:

\sqrt{1 - \big(\frac{|\text{tr}(A B^\dagger)|}{\text{dim}(A)}\big)^2}

Where A and B are the unitaries, B^\dagger is the conjugate transpose of B, |\text{tr}(A B^\dagger)| is the absolute value of the trace of the product of A and B^\dagger, and dim(A) is the dimension of A.

§Arguments
  • x - The other unitary matrix.
§Returns

The distance between the two unitaries.

§Panics

Panics if the two unitaries have different dimensions.

§Example
use qudit_core::c64;
use faer::mat;
use faer::Mat;
use qudit_core::UnitaryMatrix;
use qudit_core::ComplexScalar;
let u1: UnitaryMatrix<c64> = UnitaryMatrix::identity([2, 2]);
let u2 = UnitaryMatrix::identity([2, 2]);
let u3 = UnitaryMatrix::random([2, 2]);
assert_eq!(u1.get_distance_from(&u2), 0.0);
assert!(u1.get_distance_from(&u3) > 0.0);
§See Also
Source

pub fn permute(&self, perm: &QuditPermutation) -> UnitaryMatrix<C>

Permute the unitary matrix according to a qudit system permutation.

§Arguments
  • perm - The permutation to apply.
§Returns

A newly allocated unitary matrix that is the result of applying the permutation to the original unitary matrix.

§Panics

Panics if there is a radix mismatch between the unitary matrix and the permutation.

§Example
use qudit_core::c64;
use faer::mat;
use faer::Mat;
use qudit_core::UnitaryMatrix;
use qudit_core::QuditPermutation;
use num_traits::{One, Zero};
let unitary: UnitaryMatrix<c64> = UnitaryMatrix::identity([2, 2]);
let perm = QuditPermutation::new([2, 2], &vec![1, 0]);
let permuted = unitary.permute(&perm);
let mat = mat![
    [c64::one(), c64::zero(), c64::zero(), c64::zero()],
    [c64::zero(), c64::zero(), c64::one(), c64::zero()],
    [c64::zero(), c64::one(), c64::zero(), c64::zero()],
    [c64::zero(), c64::zero(), c64::zero(), c64::one()],
];
assert_eq!(permuted, UnitaryMatrix::new([2, 2], Mat::identity(4, 4)));
Source

pub fn conjugate(&self) -> UnitaryMatrix<C>

Conjugate the unitary matrix.

§Returns

A newly allocated unitary matrix that is the conjugate of the original unitary matrix.

§Example
use qudit_core::c64;
use faer::mat;
use faer::Mat;
use qudit_core::UnitaryMatrix;
use num_traits::Zero;
let y_mat = mat![
   [c64::zero(), c64::new(0.0, -1.0)],
   [c64::new(0.0, 1.0), c64::zero()],
];
let unitary = UnitaryMatrix::new([2], y_mat);
let conjugate = unitary.conjugate();
let y_mat_conjugate = mat![
    [c64::zero(), c64::new(0.0, 1.0)],
    [c64::new(0.0, -1.0), c64::zero()],
];
assert_eq!(conjugate, UnitaryMatrix::new([2], y_mat_conjugate));
Source

pub fn transpose(&self) -> UnitaryMatrix<C>

Transpose the unitary matrix.

§Returns

A newly allocated unitary matrix that is the transpose of the original unitary matrix.

§Example
use qudit_core::c64;
use faer::mat;
use faer::Mat;
use qudit_core::UnitaryMatrix;
use num_traits::Zero;
let y_mat = mat![
  [c64::zero(), c64::new(0.0, -1.0)],
  [c64::new(0.0, 1.0), c64::zero()],
];
let unitary = UnitaryMatrix::new([2], y_mat);
let transpose = unitary.transpose();
let y_mat_transpose = mat![
    [c64::zero(), c64::new(0.0, 1.0)],
    [c64::new(0.0, -1.0), c64::zero()],
];
assert_eq!(transpose, UnitaryMatrix::new([2], y_mat_transpose));
Source

pub fn dagger(&self) -> Self

Adjoint or dagger the unitary matrix.

§Returns

A newly allocated unitary matrix that is the adjoint of the original unitary matrix.

§Example
use qudit_core::c64;
use faer::mat;
use faer::Mat;
use qudit_core::UnitaryMatrix;
use num_traits::Zero;
let y_mat: Mat<c64> = mat![
    [c64::zero(), c64::new(0.0, -1.0)],
    [c64::new(0.0, 1.0), c64::zero()],
];
let unitary = UnitaryMatrix::new([2], y_mat);
let dagger: UnitaryMatrix<c64> = unitary.dagger();
let y_mat_adjoint = mat![
    [c64::zero(), c64::new(0.0, -1.0)],
    [c64::new(0.0, 1.0), c64::zero()],
];
assert_eq!(dagger, UnitaryMatrix::new([2], y_mat_adjoint));
assert_eq!(dagger.dagger(), unitary);
assert_eq!(dagger.dot(&unitary), Mat::<c64>::identity(2, 2));
assert_eq!(unitary.dot(&dagger), Mat::<c64>::identity(2, 2));
Source

pub fn adjoint(&self) -> Self

Adjoint or dagger the unitary matrix (Alias for Self::dagger).

Source

pub fn dot(&self, rhs: impl AsMatRef<T = C, Rows = usize, Cols = usize>) -> Self

Multiply the unitary matrix by another matrix.

§Arguments
  • rhs - The matrix to multiply by.
§Returns

A newly allocated unitary matrix that is the result of multiplying the original unitary matrix by the other matrix.

§Panics

Panics if the two matrices have different dimensions.

§Example
use qudit_core::c64;
use faer::mat;
use faer::Mat;
use qudit_core::UnitaryMatrix;
use num_traits::Zero;
let y_mat = mat![
   [c64::zero(), c64::new(0.0, -1.0)],
   [c64::new(0.0, 1.0), c64::zero()],
];
let unitary = UnitaryMatrix::new([2], y_mat.clone());
let result = unitary.dot(&unitary);
assert_eq!(result, UnitaryMatrix::new([2], y_mat.clone() * y_mat));
§See Also
Source

pub fn kron(&self, rhs: &UnitaryMatrix<C>) -> Self

Kronecker product the unitary matrix with another matrix.

§Arguments
  • rhs - The matrix to kronecker product with.
§Returns

A newly allocated unitary matrix that is the result of kronecker producting the original unitary matrix with the other matrix.

§Example
use qudit_core::c64;
use faer::mat;
use faer::Mat;
use qudit_core::UnitaryMatrix;
use num_traits::Zero;
let y_mat = mat![
  [c64::zero(), c64::new(0.0, -1.0)],
  [c64::new(0.0, 1.0), c64::zero()],
];
let unitary = UnitaryMatrix::new([2], y_mat.clone());
let result = unitary.kron(&unitary);
let y_mat_kron = mat![
   [c64::zero(), c64::zero(), c64::zero(), c64::new(-1.0, 0.0)],
   [c64::zero(), c64::zero(), c64::new(1.0, 0.0), c64::zero()],
   [c64::zero(), c64::new(1.0, 0.0), c64::zero(), c64::zero()],
   [c64::new(-1.0, 0.0), c64::zero(), c64::zero(), c64::zero()],
];
assert_eq!(result, UnitaryMatrix::new([2, 2], y_mat_kron));
§See Also

Trait Implementations§

Source§

impl<C: ComplexScalar> AsMatRef for UnitaryMatrix<C>

Source§

type T = C

scalar type
Source§

type Rows = usize

row dimension type
Source§

type Cols = usize

column dimension type
Source§

type Owned = Mat<Own<C>>

owned matrix type
Source§

fn as_mat_ref(&self) -> MatRef<'_, C>

returns a view over self
Source§

impl<C: ComplexScalar> BitWidthConvertible for UnitaryMatrix<C>

Source§

type Width32 = UnitaryMatrix<Complex<f32>>

The 32-bit width representation of the type.
Source§

type Width64 = UnitaryMatrix<Complex<f64>>

The 64-bit width representation of the type.
Source§

fn to32(self) -> Self::Width32

Converts the type into its 32-bit width representation.
Source§

fn to64(self) -> Self::Width64

Converts the type into its 64-bit width representation.
Source§

fn from32(unitary: Self::Width32) -> Self

Constructs the type from a 32-bit width representation.
Source§

fn from64(unitary: Self::Width64) -> Self

Constructs the type from a 64-bit width representation.
Source§

impl<C: Clone + ComplexScalar> Clone for UnitaryMatrix<C>

Source§

fn clone(&self) -> UnitaryMatrix<C>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<C: ComplexScalar> Debug for UnitaryMatrix<C>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<C: ComplexScalar> Deref for UnitaryMatrix<C>

Source§

type Target = Mat<Own<C>>

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl<'a, C: ComplexScalar> From<&'a UnitaryMatrix<C>> for MatRef<'a, C>

Source§

fn from(unitary: &'a UnitaryMatrix<C>) -> Self

Converts to this type from the input type.
Source§

impl<'a, C: ComplexScalar> From<&'a mut UnitaryMatrix<C>> for MatMut<'a, C>

Source§

fn from(unitary: &'a mut UnitaryMatrix<C>) -> Self

Converts to this type from the input type.
Source§

impl<'a, C: ComplexScalar> From<&'a mut UnitaryMatrix<C>> for MatRef<'a, C>

Source§

fn from(unitary: &'a mut UnitaryMatrix<C>) -> Self

Converts to this type from the input type.
Source§

impl<C: ComplexScalar> From<UnitaryMatrix<C>> for Mat<C>

Source§

fn from(unitary: UnitaryMatrix<C>) -> Self

Converts to this type from the input type.
Source§

impl<C: ComplexScalar> Index<(usize, usize)> for UnitaryMatrix<C>

Source§

type Output = C

The returned type after indexing.
Source§

fn index(&self, index: (usize, usize)) -> &Self::Output

Performs the indexing (container[index]) operation. Read more
Source§

impl<C: ComplexScalar> Mul<&UnitaryMatrix<C>> for &Mat<C>

Source§

type Output = Mat<Own<C>>

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: &UnitaryMatrix<C>) -> Self::Output

Performs the * operation. Read more
Source§

impl<C: ComplexScalar> Mul<&UnitaryMatrix<C>> for Mat<C>

Source§

type Output = Mat<Own<C>>

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: &UnitaryMatrix<C>) -> Self::Output

Performs the * operation. Read more
Source§

impl<C: ComplexScalar> Mul<UnitaryMatrix<C>> for &Mat<C>

Source§

type Output = Mat<Own<C>>

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: UnitaryMatrix<C>) -> Self::Output

Performs the * operation. Read more
Source§

impl<C: ComplexScalar> Mul<UnitaryMatrix<C>> for Mat<C>

Source§

type Output = Mat<Own<C>>

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: UnitaryMatrix<C>) -> Self::Output

Performs the * operation. Read more
Source§

impl<C: ComplexScalar> Mul for UnitaryMatrix<C>

Source§

type Output = UnitaryMatrix<C>

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: Self) -> Self::Output

Performs the * operation. Read more
Source§

impl<C: ComplexScalar> PartialEq<Mat<Own<C>>> for UnitaryMatrix<C>

Source§

fn eq(&self, other: &Mat<C>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<C: ComplexScalar> PartialEq<Mat<Own<i32>>> for UnitaryMatrix<C>

Source§

fn eq(&self, other: &Mat<i32>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<C: ComplexScalar> PartialEq for UnitaryMatrix<C>

Source§

fn eq(&self, other: &UnitaryMatrix<C>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<C: ComplexScalar> QuditSystem for UnitaryMatrix<C>

Source§

fn radices(&self) -> Radices

Returns the radices of the qudits in the system. Read more
Source§

fn num_qudits(&self) -> usize

Returns the number of qudits in the system. Read more
Source§

fn dimension(&self) -> usize

Returns the total dimension of the quantum system. Read more
Source§

fn is_qubit_only(&self) -> bool

Checks if the system consists only of qubits (2-level systems). Read more
Source§

fn is_qutrit_only(&self) -> bool

Checks if the system consists only of qutrits (3-level systems). Read more
Source§

fn is_qudit_only<T: Into<Radix>>(&self, radix: T) -> bool

Checks if the system consists only of qudits with a specified radix. Read more
Source§

fn is_homogenous(&self) -> bool

Checks if the system is homogenous, i.e., all qudits have the same radix. Read more
Source§

impl<C: ComplexScalar> Sub for UnitaryMatrix<C>

Source§

type Output = Mat<Own<C>>

The resulting type after applying the - operator.
Source§

fn sub(self, rhs: Self) -> Self::Output

Performs the - operation. Read more
Source§

impl<C: ComplexScalar> Eq for UnitaryMatrix<C>

Auto Trait Implementations§

§

impl<C> Freeze for UnitaryMatrix<C>

§

impl<C> RefUnwindSafe for UnitaryMatrix<C>
where C: RefUnwindSafe,

§

impl<C> Send for UnitaryMatrix<C>

§

impl<C> Sync for UnitaryMatrix<C>

§

impl<C> Unpin for UnitaryMatrix<C>
where C: Unpin,

§

impl<C> UnwindSafe for UnitaryMatrix<C>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> ByRef<T> for T

Source§

fn by_ref(&self) -> &T

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DistributionExt for T
where T: ?Sized,

Source§

fn rand<T>(&self, rng: &mut (impl Rng + ?Sized)) -> T
where Self: Distribution<T>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V