Skip to content

State preparation

State Preparation Routines

density_mat(state)

Computes the density matrix from a pure state vector.

PARAMETER DESCRIPTION
state

The pure state vector :math:|\psi\rangle.

TYPE: Tensor

RETURNS DESCRIPTION
Tensor

The density matrix :math:\rho = |\psi \rangle \langle\psi|.

TYPE: DensityMatrix

Source code in qadence/states.py
def density_mat(state: Tensor) -> DensityMatrix:
    """
    Computes the density matrix from a pure state vector.

    Arguments:
        state: The pure state vector :math:`|\\psi\\rangle`.

    Returns:
        Tensor: The density matrix :math:`\\rho = |\psi \\rangle \\langle\\psi|`.
    """
    if isinstance(state, DensityMatrix):
        return state
    return DensityMatrix(torch.einsum("bi,bj->bij", (state, state.conj())))

fidelity(rho, sigma)

Calculate the fidelity between two quantum states represented by density matrices.

The fidelity is defined as F(ρ,σ) = Tr[√(√ρ σ √ρ)], or equivalently, F(ρ,σ) = ||√ρ·√σ||₁ where ||·||₁ is the trace norm.

PARAMETER DESCRIPTION
rho

First density matrix of shape [batch_size, dim, dim]

TYPE: DensityMatrix

sigma

Second density matrix of shape [batch_size, dim, dim]

TYPE: DensityMatrix

RETURNS DESCRIPTION
Tensor

Fidelity between each pair of density matrices in the batch, shape [batch_size]

Source code in qadence/states.py
def fidelity(rho: DensityMatrix, sigma: DensityMatrix) -> Tensor:
    """Calculate the fidelity between two quantum states represented by density matrices.

    The fidelity is defined as F(ρ,σ) = Tr[√(√ρ σ √ρ)], or equivalently,
    F(ρ,σ) = ||√ρ·√σ||₁ where ||·||₁ is the trace norm.

    Args:
        rho: First density matrix of shape [batch_size, dim, dim]
        sigma: Second density matrix of shape [batch_size, dim, dim]

    Returns:
        Fidelity between each pair of density matrices in the batch, shape [batch_size]
    """

    # Compute square root of rho
    rho_eigvals, rho_eigvecs = torch.linalg.eigh(rho)

    # Ensure non-negative eigenvalues
    rho_eigvals = torch.clamp(rho_eigvals, min=0)

    # Compute square root using eigendecomposition
    sqrt_eigvals = torch.sqrt(rho_eigvals)

    # Compute √ρ for each batch element
    sqrt_rho = torch.zeros_like(rho)
    for i in range(rho.shape[0]):
        sqrt_rho[i] = torch.mm(
            rho_eigvecs[i],
            torch.mm(
                torch.diag(sqrt_eigvals[i]).to(dtype=rho_eigvecs.dtype), rho_eigvecs[i].t().conj()
            ),
        )

    # Compute √ρ σ √ρ for each batch element
    inner_product = torch.zeros_like(rho)
    for i in range(rho.shape[0]):
        inner_product[i] = torch.mm(sqrt_rho[i], torch.mm(sigma[i], sqrt_rho[i]))

    # Compute eigenvalues of inner product
    inner_eigvals = torch.linalg.eigvalsh(inner_product)

    # Ensure non-negative eigenvalues
    inner_eigvals = torch.clamp(inner_eigvals, min=0)

    # Compute the fidelity as the sum of the square roots of eigenvalues
    fidelity_values = torch.sum(torch.sqrt(inner_eigvals), dim=1)

    return fidelity_values

ghz_block(n_qubits)

Generates the abstract ghz state for a specified number of qubits.

PARAMETER DESCRIPTION
n_qubits

The number of qubits.

TYPE: int

RETURNS DESCRIPTION
ChainBlock

A ChainBlock representing the GHZ state.

Examples:

from qadence.states import ghz_block

block = ghz_block(n_qubits=2)
print(block)
ChainBlock(0,1)
├── H(0)
└── ChainBlock(0,1)
    └── CNOT(0, 1)

Source code in qadence/states.py
def ghz_block(n_qubits: int) -> ChainBlock:
    """
    Generates the abstract ghz state for a specified number of qubits.

    Arguments:
        n_qubits (int): The number of qubits.

    Returns:
        A ChainBlock representing the GHZ state.

    Examples:
    ```python exec="on" source="material-block" result="json"
    from qadence.states import ghz_block

    block = ghz_block(n_qubits=2)
    print(block)
    ```
    """
    cnots = chain(CNOT(i - 1, i) for i in range(1, n_qubits))
    return chain(H(0), cnots)

ghz_state(n_qubits, batch_size=1)

Creates a GHZ state.

PARAMETER DESCRIPTION
n_qubits

The number of qubits.

TYPE: int

batch_size

How many bitstrings to use.

TYPE: int DEFAULT: 1

RETURNS DESCRIPTION
Tensor

A torch.Tensor.

Examples:

from qadence.states import ghz_state

print(ghz_state(n_qubits=2, batch_size=2))
tensor([[0.7071+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.7071+0.j]])

Source code in qadence/states.py
def ghz_state(n_qubits: int, batch_size: int = 1) -> Tensor:
    """
    Creates a GHZ state.

    Arguments:
        n_qubits (int): The number of qubits.
        batch_size (int): How many bitstrings to use.

    Returns:
        A torch.Tensor.

    Examples:
    ```python exec="on" source="material-block" result="json"
    from qadence.states import ghz_state

    print(ghz_state(n_qubits=2, batch_size=2))
    ```
    """
    norm = 1 / torch.sqrt(torch.tensor(2))
    return norm * (zero_state(n_qubits, batch_size) + one_state(n_qubits, batch_size))

is_normalized(wf, atol=NORMALIZATION_ATOL)

Checks if a wave function is normalized.

PARAMETER DESCRIPTION
wf

The wave function as a torch tensor.

TYPE: Tensor

atol

The tolerance.

TYPE: float) DEFAULT: NORMALIZATION_ATOL

RETURNS DESCRIPTION
bool

A bool.

Examples:

from qadence.states import uniform_state, is_normalized

print(is_normalized(uniform_state(2)))
True

Source code in qadence/states.py
def is_normalized(wf: Tensor, atol: float = NORMALIZATION_ATOL) -> bool:
    """
    Checks if a wave function is normalized.

    Arguments:
        wf (torch.Tensor): The wave function as a torch tensor.
        atol (float) : The tolerance.

    Returns:
        A bool.

    Examples:
    ```python exec="on" source="material-block" result="json"
    from qadence.states import uniform_state, is_normalized

    print(is_normalized(uniform_state(2)))
    ```
    """
    if wf.dim() == 1:
        wf = wf.unsqueeze(0)
    sum_probs: Tensor = (wf.abs() ** 2).sum(dim=1)
    ones = torch.ones_like(sum_probs)
    return torch.allclose(sum_probs, ones, rtol=0.0, atol=atol)  # type: ignore[no-any-return]

normalize(wf)

Normalizes a wavefunction or batch of wave functions.

PARAMETER DESCRIPTION
wf

Normalized wavefunctions.

TYPE: Tensor

RETURNS DESCRIPTION
Tensor

A torch.Tensor.

Examples:

from qadence.states import uniform_state, normalize

print(normalize(uniform_state(2, 2)))
tensor([[0.5000+0.j, 0.5000+0.j, 0.5000+0.j, 0.5000+0.j],
        [0.5000+0.j, 0.5000+0.j, 0.5000+0.j, 0.5000+0.j]])

Source code in qadence/states.py
def normalize(wf: Tensor) -> Tensor:
    """
    Normalizes a wavefunction or batch of wave functions.

    Arguments:
        wf (torch.Tensor): Normalized wavefunctions.

    Returns:
        A torch.Tensor.

    Examples:
    ```python exec="on" source="material-block" result="json"
    from qadence.states import uniform_state, normalize

    print(normalize(uniform_state(2, 2)))
    ```
    """
    if wf.dim() == 1:
        return wf / torch.sqrt((wf.abs() ** 2).sum())
    else:
        return wf / torch.sqrt((wf.abs() ** 2).sum(1)).unsqueeze(1)

one_block(n_qubits)

Generates the abstract one state for a specified number of qubits.

PARAMETER DESCRIPTION
n_qubits

The number of qubits.

TYPE: int

RETURNS DESCRIPTION
KronBlock

A KronBlock representing the one state.

Examples:

from qadence.states import one_block

block = one_block(n_qubits=2)
print(block)
KronBlock(0,1)
├── X(0)
└── X(1)

Source code in qadence/states.py
def one_block(n_qubits: int) -> KronBlock:
    """
    Generates the abstract one state for a specified number of qubits.

    Arguments:
        n_qubits (int): The number of qubits.

    Returns:
        A KronBlock representing the one state.

    Examples:
    ```python exec="on" source="material-block" result="json"
    from qadence.states import one_block

    block = one_block(n_qubits=2)
    print(block)
    ```
    """
    return _from_op(X, n_qubits=n_qubits)

one_state(n_qubits, batch_size=1)

Generates the one state for a specified number of qubits.

PARAMETER DESCRIPTION
n_qubits

The number of qubits.

TYPE: int

batch_size

The batch size.

TYPE: int DEFAULT: 1

RETURNS DESCRIPTION
Tensor

A torch.Tensor.

Examples:

from qadence.states import one_state

state = one_state(n_qubits=2)
print(state)
tensor([[0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j]])

Source code in qadence/states.py
def one_state(n_qubits: int, batch_size: int = 1) -> Tensor:
    """
    Generates the one state for a specified number of qubits.

    Arguments:
        n_qubits (int): The number of qubits.
        batch_size (int): The batch size.

    Returns:
        A torch.Tensor.

    Examples:
    ```python exec="on" source="material-block" result="json"
    from qadence.states import one_state

    state = one_state(n_qubits=2)
    print(state)
    ```
    """
    bitstring = "1" * n_qubits
    return _state_from_bitstring(bitstring, batch_size)

overlap(s0, s1)

Computes the exact overlap between two statevectors.

PARAMETER DESCRIPTION
s0

A statevector or batch of statevectors.

TYPE: Tensor

s1

A statevector or batch of statevectors.

TYPE: Tensor

RETURNS DESCRIPTION
Tensor

A torch.Tensor with the result.

Examples:

from qadence.states import rand_bitstring

print(rand_bitstring(N=8))
01111101

Source code in qadence/states.py
def overlap(s0: torch.Tensor, s1: torch.Tensor) -> torch.Tensor:
    """
    Computes the exact overlap between two statevectors.

    Arguments:
        s0 (torch.Tensor): A statevector or batch of statevectors.
        s1 (torch.Tensor): A statevector or batch of statevectors.

    Returns:
        A torch.Tensor with the result.

    Examples:
    ```python exec="on" source="material-block" result="json"
    from qadence.states import rand_bitstring

    print(rand_bitstring(N=8))
    ```
    """
    from qadence.overlap import overlap_exact

    return overlap_exact(s0, s1)

partial_trace(rho, keep_indices)

Compute the partial trace of a density matrix for a system of several qubits with batch size.

This function also permutes qubits according to the order specified in keep_indices.

PARAMETER DESCRIPTION
rho

Density matrix of shape [batch_size, 2n_qubits, 2n_qubits].

TYPE: DensityMatrix)

keep_indices

Index of the qubit subsystems to keep.

TYPE: list[int]

RETURNS DESCRIPTION
DensityMatrix

Reduced density matrix after the partial trace,

TYPE: DensityMatrix

DensityMatrix

of shape [batch_size, 2n_keep, 2n_keep].

Source code in qadence/states.py
def partial_trace(rho: DensityMatrix, keep_indices: list[int]) -> DensityMatrix:
    """
    Compute the partial trace of a density matrix for a system of several qubits with batch size.

    This function also permutes qubits according to the order specified in keep_indices.

    Args:
        rho (DensityMatrix) : Density matrix of shape [batch_size, 2**n_qubits, 2**n_qubits].
        keep_indices (list[int]): Index of the qubit subsystems to keep.

    Returns:
        DensityMatrix: Reduced density matrix after the partial trace,
        of shape [batch_size, 2**n_keep, 2**n_keep].
    """
    from pyqtorch.utils import dm_partial_trace

    return dm_partial_trace(rho.permute((1, 2, 0)), keep_indices).permute((2, 0, 1))

pmf(wf)

Converts a wave function into a torch Distribution.

PARAMETER DESCRIPTION
wf

The wave function as a torch tensor.

TYPE: Tensor

RETURNS DESCRIPTION
Distribution

A torch.distributions.Distribution.

Examples:

from qadence.states import uniform_state, pmf

print(pmf(uniform_state(2)).probs)
tensor([[0.2500, 0.2500, 0.2500, 0.2500]])

Source code in qadence/states.py
def pmf(wf: Tensor) -> Distribution:
    """
    Converts a wave function into a torch Distribution.

    Arguments:
        wf (torch.Tensor): The wave function as a torch tensor.

    Returns:
        A torch.distributions.Distribution.

    Examples:
    ```python exec="on" source="material-block" result="json"
    from qadence.states import uniform_state, pmf

    print(pmf(uniform_state(2)).probs)
    ```
    """
    return Categorical(torch.abs(torch.pow(wf, 2)))

product_block(bitstring)

Creates an abstract product state from a bitstring.

PARAMETER DESCRIPTION
bitstring

A bitstring.

TYPE: str

RETURNS DESCRIPTION
KronBlock

A KronBlock representing the product state.

Examples:

from qadence.states import product_block

print(product_block("1100"))
KronBlock(0,1,2,3)
├── X(0)
├── X(1)
├── I(2)
└── I(3)

Source code in qadence/states.py
def product_block(bitstring: str) -> KronBlock:
    """
    Creates an abstract product state from a bitstring.

    Arguments:
        bitstring (str): A bitstring.

    Returns:
        A KronBlock representing the product state.

    Examples:
    ```python exec="on" source="material-block" result="json"
    from qadence.states import product_block

    print(product_block("1100"))
    ```
    """
    return _block_from_bitstring(bitstring)

product_state(bitstring, batch_size=1, endianness=Endianness.BIG, backend=BackendName.PYQTORCH)

Creates a product state from a bitstring.

PARAMETER DESCRIPTION
bitstring

A bitstring.

TYPE: str

batch_size

Batch size.

TYPE: int) DEFAULT: 1

backend

The backend to use. Default is "pyqtorch".

TYPE: BackendName DEFAULT: PYQTORCH

RETURNS DESCRIPTION
ArrayLike

A torch.Tensor.

Examples:

from qadence.states import product_state

print(product_state("1100", backend="pyqtorch"))
print(product_state("1100", backend="horqrux"))
tensor([[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, 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 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]

Source code in qadence/states.py
@singledispatch
def product_state(
    bitstring: str,
    batch_size: int = 1,
    endianness: Endianness = Endianness.BIG,
    backend: BackendName = BackendName.PYQTORCH,
) -> ArrayLike:
    """
    Creates a product state from a bitstring.

    Arguments:
        bitstring (str): A bitstring.
        batch_size (int) : Batch size.
        backend (BackendName): The backend to use. Default is "pyqtorch".

    Returns:
        A torch.Tensor.

    Examples:
    ```python exec="on" source="material-block" result="json"
    from qadence.states import product_state

    print(product_state("1100", backend="pyqtorch"))
    print(product_state("1100", backend="horqrux"))
    ```
    """
    if batch_size:
        logger.debug(
            "The input `batch_size` is going to be deprecated. "
            "For now, default batch_size is set to 1."
        )
    return run(product_block(bitstring), backend=backend, endianness=endianness)

purity(rho, order=2)

Compute the n-th purity of a density matrix.

PARAMETER DESCRIPTION
rho

Density matrix.

TYPE: DensityMatrix

order

Exponent n.

TYPE: int DEFAULT: 2

RETURNS DESCRIPTION
Tensor

Tr[rho ** n]

TYPE: Tensor

Source code in qadence/states.py
def purity(rho: DensityMatrix, order: int = 2) -> Tensor:
    """Compute the n-th purity of a density matrix.

    Args:
        rho (DensityMatrix): Density matrix.
        order (int, optional): Exponent n.

    Returns:
        Tensor: Tr[rho ** n]
    """
    # Compute eigenvalues
    eigenvalues = torch.linalg.eigvalsh(rho)

    # Compute the sum of eigenvalues raised to power n
    return torch.sum(eigenvalues**order, dim=1)

rand_bitstring(N)

Creates a random bistring.

PARAMETER DESCRIPTION
N

The length of the bitstring.

TYPE: int

RETURNS DESCRIPTION
str

A string.

Examples:

from qadence.states import rand_bitstring

print(rand_bitstring(N=8))
11000111

Source code in qadence/states.py
def rand_bitstring(N: int) -> str:
    """
    Creates a random bistring.

    Arguments:
        N (int): The length of the bitstring.

    Returns:
        A string.

    Examples:
    ```python exec="on" source="material-block" result="json"
    from qadence.states import rand_bitstring

    print(rand_bitstring(N=8))
    ```
    """
    return "".join(str(random.randint(0, 1)) for _ in range(N))

rand_product_block(n_qubits)

Creates a block representing a random abstract product state.

PARAMETER DESCRIPTION
n_qubits

The number of qubits.

TYPE: int

RETURNS DESCRIPTION
KronBlock

A KronBlock representing the product state.

Examples:

from qadence.states import rand_product_block

print(rand_product_block(n_qubits=2))
KronBlock(0,1)
├── X(0)
└── I(1)

Source code in qadence/states.py
def rand_product_block(n_qubits: int) -> KronBlock:
    """
    Creates a block representing a random abstract product state.

    Arguments:
        n_qubits (int): The number of qubits.

    Returns:
        A KronBlock representing the product state.

    Examples:
    ```python exec="on" source="material-block" result="json"
    from qadence.states import rand_product_block

    print(rand_product_block(n_qubits=2))
    ```
    """
    return product_block(rand_bitstring(n_qubits))

rand_product_state(n_qubits, batch_size=1)

Creates a random product state.

PARAMETER DESCRIPTION
n_qubits

The number of qubits.

TYPE: int

batch_size

How many bitstrings to use.

TYPE: int DEFAULT: 1

RETURNS DESCRIPTION
Tensor

A torch.Tensor.

Examples:

from qadence.states import rand_product_state

print(rand_product_state(n_qubits=2, batch_size=2))
tensor([[0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],
        [0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j]])

Source code in qadence/states.py
def rand_product_state(n_qubits: int, batch_size: int = 1) -> Tensor:
    """
    Creates a random product state.

    Arguments:
        n_qubits (int): The number of qubits.
        batch_size (int): How many bitstrings to use.

    Returns:
        A torch.Tensor.

    Examples:
    ```python exec="on" source="material-block" result="json"
    from qadence.states import rand_product_state

    print(rand_product_state(n_qubits=2, batch_size=2))
    ```
    """
    wf_batch = torch.zeros(batch_size, 2**n_qubits, dtype=DTYPE)
    rand_pos = torch.randint(0, 2**n_qubits, (batch_size,))
    wf_batch[torch.arange(batch_size), rand_pos] = torch.tensor(1.0 + 0j, dtype=DTYPE)
    return wf_batch

random_state(n_qubits, batch_size=1, backend=BackendName.PYQTORCH, type=StateGeneratorType.HAAR_MEASURE_FAST)

Generates a random state for a specified number of qubits.

PARAMETER DESCRIPTION
n_qubits

The number of qubits.

TYPE: int

backend

The backend to use.

TYPE: str DEFAULT: PYQTORCH

batch_size

The batch size.

TYPE: int DEFAULT: 1

type

StateGeneratorType.

DEFAULT: HAAR_MEASURE_FAST

RETURNS DESCRIPTION
Tensor

A torch.Tensor.

Examples:

from qadence.states import random_state, StateGeneratorType
from qadence.states import random_state, is_normalized, pmf
from qadence.types import BackendName
from torch.distributions import Distribution

### We have the following options:
print([g.value for g in StateGeneratorType])

n_qubits = 2
# The default is StateGeneratorType.HAAR_MEASURE_FAST
state = random_state(n_qubits=n_qubits)
print(state)

### Lets initialize a state using random rotations, i.e., StateGeneratorType.RANDOM_ROTATIONS.
random = random_state(n_qubits=n_qubits, type=StateGeneratorType.RANDOM_ROTATIONS)
print(random)
['RandomRotations', 'HaarMeasureFast', 'HaarMeasureSlow']
tensor([[ 0.2798-0.3356j, -0.1456+0.1289j, -0.4001+0.1541j,  0.3220-0.6955j]])
tensor([[ 0.6649+0.0613j, -0.0683+0.7413j,  0.0000+0.0000j,  0.0000+0.0000j]])

Source code in qadence/states.py
def random_state(
    n_qubits: int,
    batch_size: int = 1,
    backend: str = BackendName.PYQTORCH,
    type: StateGeneratorType = StateGeneratorType.HAAR_MEASURE_FAST,
) -> Tensor:
    """
    Generates a random state for a specified number of qubits.

    Arguments:
        n_qubits (int): The number of qubits.
        backend (str): The backend to use.
        batch_size (int): The batch size.
        type : StateGeneratorType.

    Returns:
        A torch.Tensor.

    Examples:
    ```python exec="on" source="material-block" result="json"
    from qadence.states import random_state, StateGeneratorType
    from qadence.states import random_state, is_normalized, pmf
    from qadence.types import BackendName
    from torch.distributions import Distribution

    ### We have the following options:
    print([g.value for g in StateGeneratorType])

    n_qubits = 2
    # The default is StateGeneratorType.HAAR_MEASURE_FAST
    state = random_state(n_qubits=n_qubits)
    print(state)

    ### Lets initialize a state using random rotations, i.e., StateGeneratorType.RANDOM_ROTATIONS.
    random = random_state(n_qubits=n_qubits, type=StateGeneratorType.RANDOM_ROTATIONS)
    print(random)
    ```
    """

    if type == StateGeneratorType.HAAR_MEASURE_FAST:
        state = concat(tuple(_rand_haar_fast(n_qubits) for _ in range(batch_size)), dim=0)
    elif type == StateGeneratorType.HAAR_MEASURE_SLOW:
        state = concat(tuple(_rand_haar_slow(n_qubits) for _ in range(batch_size)), dim=0)
    elif type == StateGeneratorType.RANDOM_ROTATIONS:
        state = run(_abstract_random_state(n_qubits, batch_size))  # type: ignore
    assert all(list(map(is_normalized, state)))
    return state

uniform_block(n_qubits)

Generates the abstract uniform state for a specified number of qubits.

PARAMETER DESCRIPTION
n_qubits

The number of qubits.

TYPE: int

RETURNS DESCRIPTION
KronBlock

A KronBlock representing the uniform state.

Examples:

from qadence.states import uniform_block

block = uniform_block(n_qubits=2)
print(block)
KronBlock(0,1)
├── H(0)
└── H(1)

Source code in qadence/states.py
def uniform_block(n_qubits: int) -> KronBlock:
    """
    Generates the abstract uniform state for a specified number of qubits.

    Arguments:
        n_qubits (int): The number of qubits.

    Returns:
        A KronBlock representing the uniform state.

    Examples:
    ```python exec="on" source="material-block" result="json"
    from qadence.states import uniform_block

    block = uniform_block(n_qubits=2)
    print(block)
    ```
    """
    return _from_op(H, n_qubits=n_qubits)

uniform_state(n_qubits, batch_size=1)

Generates the uniform state for a specified number of qubits.

PARAMETER DESCRIPTION
n_qubits

The number of qubits.

TYPE: int

batch_size

The batch size.

TYPE: int DEFAULT: 1

RETURNS DESCRIPTION
Tensor

A torch.Tensor.

Examples:

from qadence.states import uniform_state

state = uniform_state(n_qubits=2)
print(state)
tensor([[0.5000+0.j, 0.5000+0.j, 0.5000+0.j, 0.5000+0.j]])

Source code in qadence/states.py
def uniform_state(n_qubits: int, batch_size: int = 1) -> Tensor:
    """
    Generates the uniform state for a specified number of qubits.

    Arguments:
        n_qubits (int): The number of qubits.
        batch_size (int): The batch size.

    Returns:
        A torch.Tensor.

    Examples:
    ```python exec="on" source="material-block" result="json"
    from qadence.states import uniform_state

    state = uniform_state(n_qubits=2)
    print(state)
    ```
    """
    norm = 1 / torch.sqrt(torch.tensor(2**n_qubits))
    return norm * torch.ones(batch_size, 2**n_qubits, dtype=DTYPE)

von_neumann_entropy(rho, eps=1e-12)

Calculate the von Neumann entropy of a quantum density matrix.

The von Neumann entropy is defined as S(ρ) = -Tr(ρ log₂ ρ) = -∑ᵢ λᵢ log₂ λᵢ, where λᵢ are the eigenvalues of ρ.

PARAMETER DESCRIPTION
rho

Density matrix of shape [batch_size, dim, dim]

TYPE: DensityMatrix

eps

Small value to avoid log(0) for zero eigenvalues

TYPE: float DEFAULT: 1e-12

RETURNS DESCRIPTION
Tensor

Von Neumann entropy for each density matrix in the batch, shape [batch_size]

Source code in qadence/states.py
def von_neumann_entropy(rho: DensityMatrix, eps: float = 1e-12) -> torch.Tensor:
    """Calculate the von Neumann entropy of a quantum density matrix.

    The von Neumann entropy is defined as S(ρ) = -Tr(ρ log₂ ρ) = -∑ᵢ λᵢ log₂ λᵢ,
    where λᵢ are the eigenvalues of ρ.

    Args:
        rho: Density matrix of shape [batch_size, dim, dim]
        eps: Small value to avoid log(0) for zero eigenvalues

    Returns:
        Von Neumann entropy for each density matrix in the batch, shape [batch_size]
    """

    # Compute eigenvalues for each density matrix in the batch
    # For a Hermitian density matrix, eigenvalues should be real and non-negative
    eigenvalues = torch.linalg.eigvalsh(rho)

    # Normalize eigenvalues to ensure they sum to 1 (trace preservation)
    # This step might be redundant but helps with numerical stability
    eigenvalues = eigenvalues / torch.sum(eigenvalues, dim=1, keepdim=True)

    # Filter out very small eigenvalues to avoid numerical issues
    valid_eigenvalues = eigenvalues.clone()
    valid_eigenvalues[valid_eigenvalues < eps] = eps

    # Compute the entropy: -∑ᵢ λᵢ log₂ λᵢ
    # Using natural logarithm and converting to base 2
    log_base_conversion = torch.log(torch.tensor(2.0, device=rho.device))
    entropy = -torch.sum(
        valid_eigenvalues * torch.log(valid_eigenvalues) / log_base_conversion, dim=1
    )

    return entropy

zero_block(n_qubits)

Generates the abstract zero state for a specified number of qubits.

PARAMETER DESCRIPTION
n_qubits

The number of qubits.

TYPE: int

RETURNS DESCRIPTION
KronBlock

A KronBlock representing the zero state.

Examples:

from qadence.states import zero_block

block = zero_block(n_qubits=2)
print(block)
KronBlock(0,1)
├── I(0)
└── I(1)

Source code in qadence/states.py
def zero_block(n_qubits: int) -> KronBlock:
    """
    Generates the abstract zero state for a specified number of qubits.

    Arguments:
        n_qubits (int): The number of qubits.

    Returns:
        A KronBlock representing the zero state.

    Examples:
    ```python exec="on" source="material-block" result="json"
    from qadence.states import zero_block

    block = zero_block(n_qubits=2)
    print(block)
    ```
    """
    return _from_op(I, n_qubits=n_qubits)

zero_state(n_qubits, batch_size=1)

Generates the zero state for a specified number of qubits.

PARAMETER DESCRIPTION
n_qubits

The number of qubits for which the zero state is to be generated.

TYPE: int

batch_size

The batch size for the zero state.

TYPE: int DEFAULT: 1

RETURNS DESCRIPTION
Tensor

A torch.Tensor.

Examples:

from qadence.states import zero_state

state = zero_state(n_qubits=2)
print(state)
tensor([[1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j]])

Source code in qadence/states.py
def zero_state(n_qubits: int, batch_size: int = 1) -> Tensor:
    """
    Generates the zero state for a specified number of qubits.

    Arguments:
        n_qubits (int): The number of qubits for which the zero state is to be generated.
        batch_size (int): The batch size for the zero state.

    Returns:
        A torch.Tensor.

    Examples:
    ```python exec="on" source="material-block" result="json"
    from qadence.states import zero_state

    state = zero_state(n_qubits=2)
    print(state)
    ```
    """
    bitstring = "0" * n_qubits
    return _state_from_bitstring(bitstring, batch_size)