Skip to content

Conversation

@yaniccd
Copy link
Collaborator

@yaniccd yaniccd commented Dec 3, 2025

No description provided.

@codecov
Copy link

codecov bot commented Dec 3, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
haarpy/__init__.py 100.00% <ø> (ø)
haarpy/circular_ensembles.py 100.00% <100.00%> (ø)
haarpy/symplectic.py 100.00% <100.00%> (ø)
haarpy/tests/test_circular_ensembles.py 100.00% <100.00%> (ø)
haarpy/tests/test_symplectic.py 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment on lines 232 to 239
monte_carlo_integral = sum(
prod(
cse[i-1, j-1]
for i, j in zip(seq_i, seq_j)
)
for cse in cse_gen
) / sample_size

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would preferable to precalculate the values on separate notebook and harccode the answers here. I would suggest to not do Montecarlo inside the test.

Comment on lines 39 to 88
def generate_random_usp(d):
"""Generate a Haar-random USp(2d) matrix of size (2d x 2d)."""
# Step 1: Random quaternionic d x d matrix with i.i.d. N(0,1) components
A = np.random.normal(size=(d, d))
B = np.random.normal(size=(d, d))
C = np.random.normal(size=(d, d))
D = np.random.normal(size=(d, d))
# Prepare list to store orthonormal quaternion columns (each as 4 real component arrays)
basis = []
# Step 2: Quaternionic Gram-Schmidt
for j in range(d):
# j-th column as quaternion vector components
v0, v1, v2, v3 = A[:, j].copy(), B[:, j].copy(), C[:, j].copy(), D[:, j].copy()
# Make orthogonal to previous basis vectors
for (u0, u1, u2, u3) in basis:
# Compute quaternion inner product: q = <u, v> = sum_i conj(u_i)*v_i (a quaternion)
p0, p1, p2, p3 = u0, -u1, -u2, -u3 # components of conj(u)
q0 = p0 @ v0 - p1 @ v1 - p2 @ v2 - p3 @ v3 # (conj(u)·v)_real
q1 = p0 @ v1 + p1 @ v0 + p2 @ v3 - p3 @ v2 # (conj(u)·v)_i
q2 = p0 @ v2 - p1 @ v3 + p2 @ v0 + p3 @ v1 # (conj(u)·v)_j
q3 = p0 @ v3 + p1 @ v2 - p2 @ v1 + p3 @ v0 # (conj(u)·v)_k
# Subtract projection: v := v - u * q
t0 = u0 * q0 - u1 * q1 - u2 * q2 - u3 * q3
t1 = u0 * q1 + u1 * q0 + u2 * q3 - u3 * q2
t2 = u0 * q2 - u1 * q3 + u2 * q0 + u3 * q1
t3 = u0 * q3 + u1 * q2 - u2 * q1 + u3 * q0
v0 -= t0; v1 -= t1; v2 -= t2; v3 -= t3
# Normalize v (so that <v,v> = 1)
norm = np.sqrt(v0@v0 + v1@v1 + v2@v2 + v3@v3)
v0 /= norm; v1 /= norm; v2 /= norm; v3 /= norm
# Step 3: Multiply by a random unit quaternion (random phase)
q0, q1, q2, q3 = random_unit_quaternion()
t0 = v0*q0 - v1*q1 - v2*q2 - v3*q3
t1 = v0*q1 + v1*q0 + v2*q3 - v3*q2
t2 = v0*q2 - v1*q3 + v2*q0 + v3*q1
t3 = v0*q3 + v1*q2 - v2*q1 + v3*q0
v0, v1, v2, v3 = t0, t1, t2, t3
basis.append((v0, v1, v2, v3))
# Step 4: Assemble the complex 2d x 2d matrix from quaternion basis
d2 = 2 * d
U = np.zeros((d2, d2), dtype=np.complex128)
# Fill block entries for each quaternion column
for j, (u0, u1, u2, u3) in enumerate(basis):
U[:d, j] = u0 + 1j*u1 # top-left block
U[:d, j+d] = u2 + 1j*u3 # top-right block
U[d:, j] = -u2 + 1j*u3 # bottom-left block
U[d:, j+d] = u0 - 1j*u1 # bottom-right block
return U


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the code to generate symplectics should not be here. Instead we should separately Montecarlo teh answer and the just hardcode them here.

@nquesada nquesada self-requested a review December 4, 2025 21:30
@yaniccd yaniccd merged commit 17b546b into master Dec 8, 2025
2 checks passed
@yaniccd yaniccd deleted the symplectic_moments branch December 8, 2025 07:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants