HilbertState

Struct HilbertState 

Source
pub struct HilbertState { /* private fields */ }
Expand description

A strong type representing a Quantum State Vector (Ket) |ψ>.

This represents a Minimal Left Ideal of the algebra Cl(10) (or others), acting as the Hilbert Space.

§Invariants

  • The coefficients are always Complex<f64>.
  • The Metric is fixed at construction time (preventing mixed-algebra operations).

Implementations§

Source§

impl HilbertState

Source

pub fn new_spin10( data: Vec<Complex<f64>>, ) -> Result<Self, CausalMultiVectorError>

Creates a new Hilbert State for the Grand Unified Algebra (Spin(10)). This enforces the metric Cl(10) (NonEuclidean, 10D).

Source

pub fn new( data: Vec<Complex<f64>>, metric: Metric, ) -> Result<Self, CausalMultiVectorError>

Generic constructor for other quantum systems (e.g. Qubits / Cl(2)).

Source

pub fn new_unchecked(data: Vec<Complex<f64>>, metric: Metric) -> Self

Source

pub fn from(mv: CausalMultiVector<Complex<f64>>) -> Self

Source

pub fn into_inner(self) -> CausalMultiVector<Complex<f64>>

Unwraps the state to access the underlying algebraic object. Useful when you need to perform raw geometric operations.

Source

pub fn as_inner(&self) -> &CausalMultiVector<Complex<f64>>

Borrows the underlying algebraic object.

Source

pub fn mv(&self) -> &CausalMultiVector<Complex<f64>>

Trait Implementations§

Source§

impl Add for HilbertState

Source§

type Output = HilbertState

The resulting type after applying the + operator.
Source§

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

Performs the + operation. Read more
Source§

impl Clone for HilbertState

Source§

fn clone(&self) -> HilbertState

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 Debug for HilbertState

Source§

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

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

impl Mul<Complex<f64>> for HilbertState

Source§

type Output = HilbertState

The resulting type after applying the * operator.
Source§

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

Performs the * operation. Read more
Source§

impl PartialEq for HilbertState

Source§

fn eq(&self, other: &HilbertState) -> 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 QuantumGates for HilbertState

Source§

fn gate_identity() -> Self

The Identity Operator (No-op).

§Physics

The identity operator $I$ leaves any quantum state $|\psi\rangle$ unchanged: $I|\psi\rangle = |\psi\rangle$. It is a fundamental operator that represents “doing nothing” to the quantum system.

§Math

In Geometric Algebra, the identity element is the scalar $1$. When represented as a multivector, it has a coefficient of $1$ for the scalar blade (grade 0) and zero for all other blades.

§Rust Details

A new HilbertState is created with a data vector initialized to zeros, except for the first element (data[0]), which corresponds to the scalar component, set to Complex64::one(). The state is constructed using new_spin10(), ensuring it is part of the Cl(0,10) algebra.

Source§

fn gate_x() -> Self

Pauli-X (NOT Gate).

§Physics

The Pauli-X gate is the quantum equivalent of the classical NOT gate. It performs a bit flip, transforming $|0\rangle \leftrightarrow |1\rangle$. It corresponds to a rotation around the X-axis of the Bloch sphere by $\pi$ radians.

§Math (Clifford Algebra Mapping)

In the Cl(0,10) algebra (where basis vectors $e_k$ square to $-1$), the Pauli-X operator is represented as $X = i e_1$. This choice ensures that $X^2 = (i e_1)(i e_1) = i^2 e_1^2 = (-1)(-1) = 1$, matching the physical property of the Pauli-X matrix.

§Rust Details

A HilbertState is initialized with all coefficients as zero. The coefficient for the first basis vector ($e_1$, corresponding to bitmap 1) is set to the imaginary unit i. The state is constructed using new_spin10(), ensuring it operates within Cl(0,10).

Source§

fn gate_y() -> Self

Pauli-Y.

§Physics

The Pauli-Y gate performs a transformation $|0\rangle \to i|1\rangle$ and $|1\rangle \to -i|0\rangle$. It corresponds to a rotation around the Y-axis of the Bloch sphere by $\pi$ radians.

§Math (Clifford Algebra Mapping)

In the Cl(0,10) algebra, the Pauli-Y operator is represented as $Y = i e_2$. This ensures that $Y^2 = (i e_2)(i e_2) = i^2 e_2^2 = (-1)(-1) = 1$, matching the physical property of the Pauli-Y matrix.

§Rust Details

A HilbertState is initialized with all coefficients as zero. The coefficient for the second basis vector ($e_2$, corresponding to bitmap 10 or index 2) is set to the imaginary unit i. The state is constructed using new_spin10().

Source§

fn gate_z() -> Self

Pauli-Z (Phase Flip).

§Physics

The Pauli-Z gate leaves the $|0\rangle$ state unchanged and maps $|1\rangle \to -|1\rangle$. It applies a $\pi$ phase shift to the $|1\rangle$ component. It corresponds to a rotation around the Z-axis of the Bloch sphere by $\pi$ radians.

§Math (Clifford Algebra Mapping)

In the Cl(0,10) algebra, the Pauli-Z operator is constructed from the geometric product of the X and Y operators. Specifically, $Z = -iXY$. Using the previous definitions $X = i e_1$ and $Y = i e_2$: $$ Z = -i(i e_1)(i e_2) = -i(i^2 e_1 e_2) = -i(-e_1 e_2) = i e_{12} $$ This ensures $Z^2 = (i e_{12})(i e_{12}) = i^2 (e_{12})^2 = (-1)(-1) = 1$, matching the physical property of the Pauli-Z matrix.

§Rust Details

This implementation constructs the Z gate by first obtaining instances of the X and Y gates. It then computes their geometric product (xy = x.as_inner() * y.as_inner()). Finally, it scales this product by -i to match the definition $Z = -iXY$. The state is constructed using new_spin10().

Source§

fn gate_hadamard() -> Self

Hadamard Gate (H).

§Physics

The Hadamard gate is a single-qubit gate that creates superposition. It transforms a basis state into a superposition of $|0\rangle$ and $|1\rangle$. Specifically, $|0\rangle \to \frac{1}{\sqrt{2}}(|0\rangle + |1\rangle)$ and $|1\rangle \to \frac{1}{\sqrt{2}}(|0\rangle - |1\rangle)$. It effectively rotates a state on the Bloch sphere by $\pi$ around the axis $(\hat{x} + \hat{z})/\sqrt{2}$.

§Math

The Hadamard gate can be defined in terms of Pauli matrices: $$ H = \frac{1}{\sqrt{2}}(X + Z) $$

§Rust Details

This implementation directly follows the mathematical definition. It obtains instances of the Pauli-X and Pauli-Z gates, adds their underlying CausalMultiVector representations, and then scales the result by $1/\sqrt{2}$. The state is constructed using new_spin10().

Source§

fn gate_s() -> Self

Phase Gate (S).

§Physics

The S-gate, also known as the Phase gate, applies a phase shift of $\pi/2$ ($90^\circ$) around the Z-axis of the Bloch sphere. It transforms $|0\rangle \to |0\rangle$ and $|1\rangle \to i|1\rangle$.

§Math

The S-gate is a Z-rotation gate, which can be expressed in exponential form. The implementation here uses the form $S = e^{-i \frac{\pi}{4} Z}$. Given that $Z^2 = I$ (Identity), the exponential can be expanded as: $$ e^{-i\theta Z} = (\cos \theta) I - i (\sin \theta) Z $$ For the S-gate, $\theta = \frac{\pi}{4}$.

§Rust Details
  1. It obtains the Identity gate ($I$) and the Pauli-Z gate ($Z$).
  2. The angle theta is set to FRAC_PI_4 ($\pi/4$).
  3. The terms cos(theta) * I and -i * sin(theta) * Z are calculated.
  4. These two multivectors are added to form the final S-gate operator.

The new state is constructed using new_spin10().

Source§

fn gate_t() -> Self

T Gate (pi/8).

§Physics

The T-gate, also known as the $\pi/8$ gate, applies a phase shift of $\pi/4$ ($45^\circ$) around the Z-axis of the Bloch sphere. It is a fundamental single-qubit gate, and a ‘non-Clifford’ gate, meaning it cannot be constructed from Hadamard and CNOT gates alone. It transforms $|0\rangle \to |0\rangle$ and $|1\rangle \to e^{i\pi/4}|1\rangle$.

§Math

The T-gate is a Z-rotation gate, expressed in exponential form. The implementation here uses the form $T = e^{-i \frac{\pi}{8} Z}$. Given that $Z^2 = I$ (Identity), the exponential can be expanded as: $$ e^{-i\theta Z} = (\cos \theta) I - i (\sin \theta) Z $$ For the T-gate, $\theta = \frac{\pi}{8}$.

§Rust Details
  1. It obtains the Identity gate ($I$) and the Pauli-Z gate ($Z$).
  2. The angle theta is set to FRAC_PI_8 ($\pi/8$).
  3. The terms cos(theta) * I and -i * sin(theta) * Z are calculated.
  4. These two multivectors are added to form the final T-gate operator.

The new state is constructed using new_spin10().

Source§

impl QuantumOps for HilbertState

Source§

fn dag(&self) -> Self

The Hermitian Conjugate: $\psi^\dagger$.

In quantum mechanics, the Hermitian conjugate (or adjoint) of a ket $|\psi\rangle$ is the bra $\langle\psi|$. For operators, it generalizes to $O^\dagger$. In the context of Geometric Algebra with complex coefficients, this operation involves two steps:

  1. Geometric Reversion: Reversing the order of basis vectors within each blade. This changes the sign of certain blades based on their grade (e.g., $(e_1 e_2)^\dagger = e_2 e_1 = -e_1 e_2$).
  2. Complex Conjugation: Taking the complex conjugate of all scalar coefficients.

Mathematically, if $A = \sum_I (a_I + i b_I) e_I$, then $A^\dagger = \sum_I (a_I - i b_I) \tilde{e_I}$, where $\tilde{e_I}$ is the reversion of the basis blade $e_I$.

§Rust Details

This is implemented by first calling the reversion() method on the underlying CausalMultiVector to handle the geometric part, and then iterating through the resulting data vector to apply c.conj() (complex conjugate) to each Complex64 coefficient.

Source§

fn bracket(&self, other: &Self) -> Complex64

The Inner Product: $\langle \psi | \phi \rangle$.

§Physics

In quantum mechanics, the inner product of two state vectors (a bra $\langle \psi |$ and a ket $| \phi \rangle$) results in a complex scalar, known as a probability amplitude. Its squared magnitude, $|\langle \psi | \phi \rangle|^2$, represents the probability of finding the system in state $|\psi\rangle$ given it was prepared in state $|\phi\rangle$.

§Math

The inner product is calculated as the scalar (grade 0) component of the geometric product of the Hermitian conjugate of the first state with the second state: $ \langle \psi | \phi \rangle = \text{ScalarPart}(\psi^\dagger \cdot \phi) $

§Rust Details

The dag() method is first called on self to obtain the bra $\langle \psi |$. Then, the geometric_product() of the resulting bra’s underlying multivector and the other ket’s underlying multivector (other.mv()) is computed. Finally, the scalar component (grade 0, index 0) is extracted from the result.

Source§

fn expectation_value(&self, operator: &Self) -> Complex64

The Expectation Value: $\langle \psi | \hat{O} | \psi \rangle$.

§Physics

The expectation value of an observable (represented by a Hermitian operator $\hat{O}$) for a quantum system in state $|\psi\rangle$ is the average value of many measurements of that observable. It is a real scalar.

§Math

The expectation value is calculated using the “sandwich” product: $ \langle \psi | \hat{O} | \psi \rangle = \text{ScalarPart}(\psi^\dagger \cdot \hat{O} \cdot \psi) $

The operator operator is passed as &Self. In Furey’s algebraic approach, operators (End(A)) and states (Ideals) can live in the same algebra (e.g., Cl(0,10)), so representing the operator as a HilbertState (or similar Newtype) is a valid type-safe approach.

§Rust Details

The implementation first obtains the bra $\langle \psi |$ using self.dag(). It then performs two sequential geometric products:

  1. op.geometric_product(ket): Applies the operator $\hat{O}$ to the ket $|\psi\rangle$, resulting in an intermediate state $|\phi\rangle = \hat{O}|\psi\rangle$.
  2. bra.mv().geometric_product(&phi): Takes the inner product $\langle \psi | \phi \rangle$.
  3. Finally, the scalar (grade 0) component of the result is extracted.
Source§

fn normalize(&self) -> Self

Normalizes the state so $\langle \psi | \psi \rangle = 1$.

§Physics

In quantum mechanics, physical states are represented by normalized vectors in Hilbert space. The normalization condition $\langle \psi | \psi \rangle = 1$ ensures that the total probability of finding the system in any possible state is unity.

§Math

A state $|\psi\rangle$ is normalized by dividing it by its norm (magnitude): $ |\psi’\rangle = \frac{|\psi\rangle}{\sqrt{\langle \psi | \psi \rangle}} $ where $\sqrt{\langle \psi | \psi \rangle}$ is the L2 norm of the state vector. The term $\langle \psi | \psi \rangle$ is the squared norm (or probability density), which is a real, non-negative scalar.

§Rust Details
  1. The bracket(self) method is called to calculate $\langle \psi | \psi \rangle$. Since this must be a real number, its real part (.re) is extracted.
  2. A check is performed for norm_sq <= f64::EPSILON to handle cases where the state is effectively a zero vector, preventing division by zero or NaN results. In such cases, the original (unnormalized) state is returned.
  3. The scaling factor is computed as 1.0 / norm_sq.sqrt().
  4. Each complex coefficient in the underlying CausalMultiVector’s data is multiplied by this scaling factor.
  5. A new HilbertState is constructed using Self::new_unchecked(). This is safe because normalization only scales coefficients and does not change the metric or the structure of the multivector, thus preserving its validity with respect to its original construction.
Source§

impl StructuralPartialEq for HilbertState

Auto Trait Implementations§

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> 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> 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<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.