SPECIAL_ORTHO_GROUP
Overview
The SPECIAL_ORTHO_GROUP function generates random rotation matrices from the special orthogonal group SO(N), which is the group of all orthogonal N \times N matrices with determinant +1. These matrices represent proper rotations in N-dimensional Euclidean space, preserving both distances and orientation.
This implementation uses the scipy.stats.special_ortho_group distribution from SciPy. The function draws random samples from the Haar distribution, which is the unique uniform distribution on SO(N). The Haar measure, named after mathematician Alfréd Haar, provides a mathematically rigorous way to sample “uniformly at random” from continuous groups like SO(N). For more mathematical background, see the Wikipedia article on orthogonal groups.
An orthogonal matrix Q satisfies the property:
Q Q^T = Q^T Q = I
where I is the identity matrix and Q^T is the transpose of Q. For SO(N) specifically, the additional constraint \det(Q) = +1 ensures the transformation is a pure rotation without reflection.
The algorithm generates a Haar-distributed orthogonal matrix using scipy.stats.ortho_group, then adjusts the result to guarantee the determinant is +1. For 3D rotations specifically, SciPy also provides scipy.spatial.transform.Rotation.random as an alternative.
Random rotation matrices from SO(N) have applications in:
- 3D graphics and robotics: Generating random orientations for objects or sensors
- Monte Carlo simulations: Sampling over rotation spaces
- Statistical physics: Modeling spin systems and lattice gauge theories
- Machine learning: Random projections and data augmentation with rotational transformations
This example function is provided as-is without any representation of accuracy.
Excel Usage
=SPECIAL_ORTHO_GROUP(dim, size)
dim(int, required): Dimension of the square matrix (must be >= 2).size(int, optional, default: null): Number of matrices to generate (must be >= 1). If omitted, returns a single matrix.
Returns (list[list]): 2D orthogonal matrix, or error message string.
Examples
Example 1: Single 3x3 orthogonal matrix
Inputs:
| dim |
|---|
| 3 |
Excel formula:
=SPECIAL_ORTHO_GROUP(3)
Expected output:
"non-error"
Example 2: Two 3x3 orthogonal matrices stacked
Inputs:
| dim | size |
|---|---|
| 3 | 2 |
Excel formula:
=SPECIAL_ORTHO_GROUP(3, 2)
Expected output:
"non-error"
Example 3: Single 4x4 orthogonal matrix
Inputs:
| dim |
|---|
| 4 |
Excel formula:
=SPECIAL_ORTHO_GROUP(4)
Expected output:
"non-error"
Example 4: Three 4x4 orthogonal matrices stacked
Inputs:
| dim | size |
|---|---|
| 4 | 3 |
Excel formula:
=SPECIAL_ORTHO_GROUP(4, 3)
Expected output:
"non-error"
Python Code
import numpy as np
from scipy.stats import special_ortho_group as scipy_special_ortho_group
def special_ortho_group(dim, size=None):
"""
Draws random samples from the special orthogonal group SO(N), returning orthogonal matrices with determinant +1.
See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.special_ortho_group.html
This example function is provided as-is without any representation of accuracy.
Args:
dim (int): Dimension of the square matrix (must be >= 2).
size (int, optional): Number of matrices to generate (must be >= 1). If omitted, returns a single matrix. Default is None.
Returns:
list[list]: 2D orthogonal matrix, or error message string.
"""
def to_2d_list(arr):
"""Convert numpy arrays to 2D lists."""
arr = np.asarray(arr)
if arr.ndim == 2:
return arr.tolist()
elif arr.ndim == 3:
# Multiple matrices: flatten into a single 2D list
return [row for mat in arr for row in mat.tolist()]
else:
return "Invalid output shape from scipy.special_ortho_group."
def valid_matrix(matrix):
"""Check for invalid values in a 2D matrix."""
for row in matrix:
for val in row:
if not isinstance(val, (int, float)):
return False
if val != val or val in (float('inf'), float('-inf')):
return False
return True
# Validate dim - accept float if it represents an integer
if isinstance(dim, float) and dim.is_integer():
dim = int(dim)
if not isinstance(dim, int) or dim < 2:
return "Invalid input: dim must be an integer >= 2."
# Validate size - accept float if it represents an integer
if size is not None:
if isinstance(size, float) and size.is_integer():
size = int(size)
if not isinstance(size, int) or size < 1:
return "Invalid input: size must be an integer >= 1 or None."
try:
# Draw samples, only pass size if not None
if size is None:
result = scipy_special_ortho_group.rvs(dim)
else:
result = scipy_special_ortho_group.rvs(dim, size=size)
except Exception as e:
return f"scipy.special_ortho_group error: {e}"
out = to_2d_list(result)
if isinstance(out, list) and all(isinstance(row, list) for row in out):
if not valid_matrix(out):
return "Invalid output: matrix contains non-numeric or special values."
return out
return out