Содержание:
Фаза и прото-пространство.
Кватернионное представление.
Кватернионные роторы: R-поворот и D-буст.
Вращение Вигнера.
Прецессия Томаса.
Перепараметризация времени
Шпаргалка.
Алгоритм и пример.
Контроль по классической формуле.
Заключение.
Эта статья - продолжение разработки теории представления специальной теории относительности через вращение векторов градиента фазы в евклидовом фазовом пространстве с поледующей перепараметризацией времени.
В первой статье мы не упомянули, что сферически-гиперболический мост строится на отношении, найденном Кристофом Гудерманом (см. гудерманиан).
1. Фаза и прото-пространство
В самом общем смысле станем полагать фазу изменением скалярного поля в евклидовом пространстве неограниченной размерности. Эффекты наблюдаемого 3-пространственного характера тогда будут выражаться как изменение проекций вектора градиента фазы на пространственные оси наблюдателя, а проекция на остальные оси даст совокупно течение фазы объекта по времени.
Формально. Фазовое «прото-пространство» - евклидово (гильбертово) пространство ,
- евклидово скалярное произведение,
.
Фазовый поток задаётся вектором .
Наблюдатель фиксирует ортонормированную тройку пространственных осей
и соответствующее подпространство с ортогональными проекторами
и
.
Разложим фазовый вектор:
Наблюдаемая 3-компонента:
Остальные (ненаблюдаемые) компоненты суммируем по Пифагору в скаляр
Для ориентации вводим единичный
2. Кватернионное представление
Тогда кватернионное представление просто:
3. Кватернионные роторы: R-поворот и D-буст
R-поворот вокруг на угол
:
поворачивает только в .
D-вращение (буст) вдоль на угол
- обычный 2D-поворот в плоскости
:
Разложив по
(где
), получаем
Здесь геометрия дотошно.
Удобная связь с кинематикой:
Здесь подробно объяснена связь со специальной теорией относительности.
Скорость ⇄ D-ротор
Формулы. Пусть ,
,
. Тогда
Обратно, для единичного кватерниона :
4. Вращение Вигнера
Для двух D-роторoв положим
Они в общем случае не коммутируют. Выделим суммарный D-вклад как тот, который воспроизводит «наклон» временной оси:
Тогда ротор Вигнера - остаточный чистый R-поворот:
и наблюдаемое действие после компенсации :
Ось и угол. Пусть - мера коллинеарности бустов. Тогда
5. Прецессия Томаса
При медленно меняющемся направлении накопление D-вращений даёт угловую скорость
Для равномерной окружности: .
6. Перепараметризация времени
Геометрия роторов не меняется - меняется только «какие часы» ведут эволюцию. Достаточно выбрать параметр и использовать один из вариантов.
Варианты эволюции
По собственному времени
:
По лабораторному времени t:
По фазовой дуге
(евклидова норма в прото-пространстве):
Гиперболическая запись СТО
Для перехода к псевдоевклидовой метрике пространства Минковского:
где
Любые формулы с роторами
и
(включая Вигнера и Томаса) остаются теми же; меняются только
согласно выбранному режиму.
7. Шпаргалка
, где
,
.
R:
,
.
D:
,
,
,
.
Вигнер:
,
,
.
Томас:
.
8. Алгоритм и пример
Пусть D-роторы
Тогда
Пояснение кватернионного корня
Здесь — главная (principal) кватернионная корень-квадрат с неотрицательной скалярной частью; для единичного
:
Надёжная формула через . Для единичного кватерниона
:
Это устойчиво даже при (то есть
).
Python-скрипт (NumPy)
import numpy as np
# Кватернионы как массивы [w, x, y, z]; единичные роторы -> |q|=1
def qmul(a, b):
w1, x1, y1, z1 = a
w2, x2, y2, z2 = b
return np.array([
w1*w2 - x1*x2 - y1*y2 - z1*z2,
w1*x2 + x1*w2 + y1*z2 - z1*y2,
w1*y2 - x1*z2 + y1*w2 + z1*x2,
w1*z2 + x1*y2 - y1*x2 + z1*w2,
])
def qconj(q): # сопряжение (для единичных это же и обратный)
w, x, y, z = q
return np.array([w, -x, -y, -z])
def qnorm(q):
return np.linalg.norm(q)
def qnormalize(q, eps=1e-15):
n = qnorm(q)
return q if n < eps else q / n
def qsqrt_unit(q, eps=1e-15):
"""
Главная ветвь квадр. корня от единичного кватерниона q = [w, v].
Возвращает s, такое что s*s == q и Re(s) >= 0.
"""
w, x, y, z = q
w = float(w)
v = np.array([x, y, z], dtype=float)
n = qnorm(q)
if abs(n - 1.0) > 1e-9:
# На всякий случай нормируем
w, v = (w/n), (v/n)
if w > -1 + eps:
s = np.sqrt(0.5*(1.0 + w))
if s < eps:
# чисто векторный случай близко к w = -1 (редкий/неустойчивый)
# выберем ось v/|v| и полуугол = pi/2
axis = v / (np.linalg.norm(v) + eps)
return np.array([0.0, *(axis)]) # полуугол = pi/2 => [0, axis]
vec = v / (2.0*s)
return qnormalize(np.array([s, *vec]))
else:
# w ~ -1: корень почти чисто векторный; выберем ось v
axis = v / (np.linalg.norm(v) + eps)
return np.array([0.0, *(axis)])
def drotor(u, psi):
"""
D-ротор: d = cos(psi/2) + u * sin(psi/2), где u - единичный 3-вектор.
Возвращает кватернион [w, x, y, z].
"""
u = np.array(u, dtype=float)
un = u / (np.linalg.norm(u) + 1e-15)
c, s = np.cos(psi/2.0), np.sin(psi/2.0)
return np.array([c, *(s*un)])
def raxis_angle(r, eps=1e-15):
"""
Из ротора r (единичный кватернион) достать ось (3-вектор) и угол (рад).
Для r = [w, v], угол = 2*atan2(|v|, w); ось = v/|v|.
"""
r = qnormalize(r)
w, vx, vy, vz = r
v = np.array([vx, vy, vz])
vnorm = np.linalg.norm(v)
angle = 2.0*np.arctan2(vnorm, w)
axis = np.array([1.0, 0.0, 0.0]) if vnorm < eps else v / vnorm
return axis, angle
def wigner_rotor(u1, psi1, u2, psi2):
"""
Главная функция: по двум D-бустам вернуть ротор Вигнера r_W
и промежуточный суммарный D-ротор d_12.
"""
d1 = drotor(u1, psi1)
d2 = drotor(u2, psi2)
L12 = qmul(d2, d1)
L21 = qmul(d1, d2)
T = qmul(L12, L21) # T = L12 * L21 (т.к. e_t = 1 => d e_t d = d^2)
d12 = qsqrt_unit(T) # principal sqrt, Re(d12) >= 0
rW = qmul(qconj(d12), L12) # r_W = \bar d12 * L12
return qnormalize(rW), qnormalize(d12)
# Пример использования
if __name__ == "__main__":
deg = np.deg2rad
u1, psi1 = [1, 0, 0], deg(40) # буст 1: ось X, угол 40°
u2, psi2 = [0, 1, 0], deg(30) # буст 2: ось Y, угол 30°
rW, d12 = wigner_rotor(u1, psi1, u2, psi2)
axis, angle = raxis_angle(rW)
print("d12 (sum D-rotor) =", d12)
print("rW (Wigner) =", rW)
print("axis =", axis, "angle_deg =", np.rad2deg(angle))
# sanity-check: L12 == d12 * rW, L21 == rW^{-1} * d12 (с точностью до числ. погрешности)
d1 = drotor(u1, psi1)
d2 = drotor(u2, psi2)
L12 = qmul(d2, d1)
L21 = qmul(d1, d2)
lhs1 = L12
rhs1 = qmul(d12, rW)
lhs2 = L21
rhs2 = qmul(qconj(rW), d12)
print("||L12 - d12*rW|| =", qnorm(lhs1 - rhs1))
print("||L21 - rW^{-1}*d12|| =", qnorm(lhs2 - rhs2))
9. Контроль по классической формуле: формулы + Python-проверка
Классическая формула угла Вигнера (в рапидитах).
Пусть даны две скорости с модулями
и направлениями
.
Введём рапидиты , где
,
.
Угол между направлениями: .
Тогда ось Вигнера:
а угол:
Ниже - код, который:
строит
по униметрическому алгоритму (кватернионы/роторы),
считает
по формуле выше,
сравнивает ось/угол.
Python-скрипт (NumPy)
import numpy as np
# ----- базовая кватернионная алгебра -----
def qmul(a, b):
w1, x1, y1, z1 = a
w2, x2, y2, z2 = b
return np.array([
w1*w2 - x1*x2 - y1*y2 - z1*z2,
w1*x2 + x1*w2 + y1*z2 - z1*y2,
w1*y2 - x1*z2 + y1*w2 + z1*x2,
w1*z2 + x1*y2 - y1*x2 + z1*w2,
])
def qconj(q):
w, x, y, z = q
return np.array([w, -x, -y, -z])
def qnorm(q):
return np.linalg.norm(q)
def qnormalize(q, eps=1e-15):
n = qnorm(q)
return q if n < eps else q/n
def qsqrt_unit(q, eps=1e-15):
"""
Главная ветвь sqrt для единичного кватерниона q=[w,v], Re>=0.
"""
q = qnormalize(q)
w, vx, vy, vz = q
v = np.array([vx, vy, vz])
vnorm = np.linalg.norm(v)
if w >= 0:
s = np.sqrt(0.5*(1.0 + w))
vec = v/(2.0*s) if s > eps else (v/(vnorm+eps))
return qnormalize(np.array([s, *vec]))
else:
# w ~ отриц., корень почти чисто-векторный
axis = v/(vnorm+eps) if vnorm > eps else np.array([1.0,0.0,0.0])
return np.array([0.0, *axis])
def raxis_angle(r, eps=1e-15):
r = qnormalize(r)
w, x, y, z = r
v = np.array([x, y, z])
vnorm = np.linalg.norm(v)
angle = 2.0*np.arctan2(vnorm, w)
axis = np.array([1.0,0.0,0.0]) if vnorm < eps else v/vnorm
return axis, angle
# ----- параметризация D-ротора -----
def psi_from_beta(beta):
"""
Униметрический угол psi из β: β=sinψ, γ=1/cosψ.
Численно устойчиво через полуугол: tan(ψ/2) = γβ/(γ+1).
"""
beta = float(beta)
if not (0 <= beta < 1):
raise ValueError("beta must be in [0,1)")
gamma = 1.0/np.sqrt(1.0 - beta*beta)
t = (gamma*beta)/(gamma+1.0)
return 2.0*np.arctan(t)
def drotor_from_velocity(v, c=1.0):
v = np.array(v, dtype=float)
speed = np.linalg.norm(v)
if speed == 0:
return np.array([1.0, 0.0, 0.0, 0.0])
u = v/speed
beta = speed/float(c)
psi = psi_from_beta(beta)
c2, s2 = np.cos(psi/2.0), np.sin(psi/2.0)
return np.array([c2, *(s2*u)])
# ----- Wigner из двух скоростей по униметрии -----
def wigner_rotor_from_velocities(v1, v2, c=1.0):
d1 = drotor_from_velocity(v1, c)
d2 = drotor_from_velocity(v2, c)
L12 = qmul(d2, d1)
L21 = qmul(d1, d2)
# из условия d12 * e_t * d12 = L12 * e_t * L21, где e_t ≡ 1, получаем d12^2 = L12 L21
d12 = qsqrt_unit(qmul(L12, L21))
rW = qmul(qconj(d12), L12)
return qnormalize(rW)
# ----- Классическая формула угла -----
def wigner_angle_classic(v1, v2, c=1.0):
v1 = np.array(v1, float); v2 = np.array(v2, float)
u1 = v1/np.linalg.norm(v1) if np.linalg.norm(v1) > 0 else np.array([1.0,0.0,0.0])
u2 = v2/np.linalg.norm(v2) if np.linalg.norm(v2) > 0 else np.array([1.0,0.0,0.0])
cos_th = float(np.clip(np.dot(u2, u1), -1.0, 1.0))
sin_th = np.sqrt(1.0 - cos_th*cos_th)
beta1 = np.linalg.norm(v1)/float(c)
beta2 = np.linalg.norm(v2)/float(c)
eta1 = np.arctanh(beta1) # rapidities
eta2 = np.arctanh(beta2)
sh1 = np.sinh(eta1/2.0); ch1 = np.cosh(eta1/2.0)
sh2 = np.sinh(eta2/2.0); ch2 = np.cosh(eta2/2.0)
num = sin_th * sh1 * sh2
den = ch1*ch2 + cos_th * sh1 * sh2
return 2.0 * np.arctan2(num, den)
def axis_classic(v1, v2):
v1 = np.array(v1, float); v2 = np.array(v2, float)
u1 = v1/np.linalg.norm(v1) if np.linalg.norm(v1) > 0 else np.array([1.0,0.0,0.0])
u2 = v2/np.linalg.norm(v2) if np.linalg.norm(v2) > 0 else np.array([1.0,0.0,0.0])
a = np.cross(u2, u1)
n = np.linalg.norm(a)
return a/n if n > 0 else np.array([1.0,0.0,0.0])
# ----- Демонстрация -----
if __name__ == "__main__":
c = 1.0
v1 = np.array([0.6, 0.0, 0.0]) * c # 0.6c по X
v2 = np.array([0.0, 0.5, 0.0]) * c # 0.5c по Y
# униметрический расчёт
rW = wigner_rotor_from_velocities(v1, v2, c)
axis_u, phi_u = raxis_angle(rW)
# классическая формула
phi_cl = wigner_angle_classic(v1, v2, c)
axis_cl = axis_classic(v1, v2)
# сравнение (ось - до знака; сравниваем |dot|)
axis_align = abs(np.dot(axis_u, axis_cl))
angle_err = abs(phi_u - phi_cl)
print(f"phi_unimetry (deg) = {np.rad2deg(phi_u):.8f}")
print(f"phi_classic (deg) = {np.rad2deg(phi_cl):.8f}")
print(f"|axis dot| = {axis_align:.12f} (1.0 = совпало)")
print(f"|angle diff| (deg) = {np.rad2deg(angle_err):.12e}")
# простая проверка точности
assert axis_align > 1 - 1e-10, "Оси не совпадают (с точностью до знака)."
assert angle_err < 1e-10, "Углы не совпали в пределах машинной точности."
10. Заключение
Выгоды использования кватернионной алгебры для рассчётов:
1) Концептуально проще
Один объект для всего. R-повороты и D-«бусты» - это единичные кватернионы, различаются только плоскостью/осью действия; композиция - обычное умножение.
Вигнер получается «по определению»: остаток после компенсации суммарного D-вклада - сразу ротор
Ось и угол берутся из одного ротора
:
- без матриц и диагонализаций.
2) Алгоритмически короче
«Одна строка» реально работает (см. выше). Для матриц Лоренца пришлось бы городить полярную/QR-факторизацию.
Стоимость операций: умножение кватернионов -
16 умножений + 12 сложений; умножение
-
64 умножений + 48 сложений.
Память: 4 числа вместо 16.
3) Численно устойчивее
Нет сингулярностей Эйлера (gimbal lock), малые углы считаются стабильно.
Нормализация - одно деление на норму; «дрейф» ортогональности у матриц требует дорогой реортогонализации.
Корень «правильной ветви» фиксируется условием
, без эвристик.
4) Прямой мост к «классике» SR
Вся геометрия - в евклидовой
; «гиперболическая» запись - это просто замена параметра
, где
.
Сверка с классической формулой Вигнера - одна арктангента (см. блок «Контроль по классике»).
5) Инженерные плюсы
Легко векторизуется и GPU-дружелюбно: пачки роторных умножений тривиально параллелятся.
Инкрементальные расчёты (накопление малых D-вращений и
) стабильны: нормализуешь каждый шаг - и готово.
Удобные градиенты по параметрам ротора (ось/полуугол) для оптимизаций и фильтров.
Итог: кватернионные роторы сводят кинематику Лоренца к паре дешёвых, устойчивых операций «умножение + нормализация», а Вигнер и Томас получаются буквально в несколько строк.
Естественно, при написании статьи вежливо экплуатировался ChatGPT.
Этот пост — продолжение популярного изложения статьи, текст которой доступен как препринт: Unimetry: A Phase-Space Reformulation of Special Relativity (скачать), Zenodo (открыть), DOI:10.5281/zenodo.17347794. Материал адаптирован из препринта по лицензии CC-BY 4.0. Пожалуйста, цитируйте оригинальный препринт.