Special Relativity in Financial Modeling 1.0.0
Lorentz transforms, spacetime classification, and geodesic price paths for quantitative finance
Loading...
Searching...
No Matches
metric_tensor.cpp
Go to the documentation of this file.
1/// @file src/tensor/metric_tensor.cpp
2/// @brief Implementation of MetricTensor — AGT-04
3
4#include "srfm/tensor.hpp"
5#include "srfm/constants.hpp"
6
7#include <Eigen/Eigenvalues>
8#include <cstdio> // std::fprintf for regularization warning
9
10namespace srfm::tensor {
11
12// ─── Tikhonov regularization constant ────────────────────────────────────────
13// When the metric matrix is near-singular, we add λI to stabilise the
14// LU decomposition before inverting. The value λ = 1e-10 is small enough
15// to preserve the geometry to full double precision for well-conditioned
16// metrics while rescuing degenerate (zero-volatility) configurations.
17static constexpr double TIKHONOV_LAMBDA = 1e-10;
18/// Relative pivot threshold below which inverse() regularizes the metric.
19static constexpr double TIKHONOV_CONDITION = 1e-10;
20
21// ─── Construction ─────────────────────────────────────────────────────────────
22
24 : metric_fn_(std::move(metric_fn)) {}
25
26// ─── Core Operations ──────────────────────────────────────────────────────────
27
29 return metric_fn_(x);
30}
31
32std::optional<MetricMatrix> MetricTensor::inverse(const SpacetimePoint& x) const {
34
35 // Use full-pivoting LU decomposition for numerical robustness.
36 // Full-pivoting is slower than partial but detects near-singularity reliably.
37 Eigen::FullPivLU<MetricMatrix> lu(g);
38 // Treat the metric as singular when its pivots span more than
39 // 1 / TIKHONOV_CONDITION orders of magnitude, not only when a pivot is
40 // exactly zero: a 1e-12 spatial scale next to a unit time scale inverts to
41 // 1e12 entries that swamp every Christoffel symbol computed from it.
42 lu.setThreshold(TIKHONOV_CONDITION);
43
44 if (!lu.isInvertible()) {
45 // FIX (Task 4): Replace hard nullopt on singular metric with Tikhonov
46 // regularization. Adding λI to a singular matrix shifts all eigenvalues
47 // by λ, making the matrix invertible while introducing only O(λ) error
48 // in the geometry. This prevents geodesic integrations from silently
49 // returning zero Christoffel symbols when the covariance matrix has a
50 // zero-volatility direction (e.g. a perfectly correlated asset pair).
51 //
52 // λ = TIKHONOV_LAMBDA = 1e-10 is chosen to be:
53 // - Large enough to regularise numerically zero eigenvalues
54 // - Small enough to be negligible for well-conditioned markets (σ ~ 0.01)
55 std::fprintf(stderr,
56 "[srfm::tensor::MetricTensor::inverse] WARNING: singular metric "
57 "detected at x = (%.4g, %.4g, %.4g, %.4g); applying Tikhonov "
58 "regularization λ = %.2e\n",
59 x(0), x(1), x(2), x(3), TIKHONOV_LAMBDA);
60
61 MetricMatrix g_reg = g;
62 g_reg += TIKHONOV_LAMBDA * MetricMatrix::Identity();
63
64 Eigen::FullPivLU<MetricMatrix> lu_reg(g_reg);
65 if (!lu_reg.isInvertible()) {
66 // Even after regularization the matrix is degenerate — return nullopt.
67 return std::nullopt;
68 }
69 return lu_reg.inverse();
70 }
71
72 return lu.inverse();
73}
74
77
78 // Count eigenvalue signs. SelfAdjointEigenSolver assumes symmetric input,
79 // which the metric always is.
80 Eigen::SelfAdjointEigenSolver<MetricMatrix> solver(g,
81 Eigen::EigenvaluesOnly);
82
83 int neg = 0;
84 int pos = 0;
85 const auto& ev = solver.eigenvalues();
86
87 for (int i = 0; i < SPACETIME_DIM; ++i) {
89 ++neg;
90 } else if (ev(i) > constants::METRIC_SINGULARITY_EPSILON) {
91 ++pos;
92 }
93 }
94
95 // Lorentzian signature: exactly one negative eigenvalue, three positive.
96 return (neg == 1) && (pos == 3);
97}
98
100 const FourVelocity& dx) const {
101 MetricMatrix g = evaluate(x);
102 // ds² = g_μν dx^μ dx^ν (bilinear form)
103 return dx.dot(g * dx);
104}
105
106// ─── Factories ────────────────────────────────────────────────────────────────
107
109 double spatial_scale) {
110 return MetricTensor([time_scale, spatial_scale](const SpacetimePoint& /*x*/) {
111 MetricMatrix g = MetricMatrix::Zero();
112 g(0, 0) = -(time_scale * time_scale);
113 g(1, 1) = (spatial_scale * spatial_scale);
114 g(2, 2) = (spatial_scale * spatial_scale);
115 g(3, 3) = (spatial_scale * spatial_scale);
116 return g;
117 });
118}
119
121 const std::array<double, 3>& vol) {
122 return MetricTensor([time_scale, vol](const SpacetimePoint& /*x*/) {
123 MetricMatrix g = MetricMatrix::Zero();
124 g(0, 0) = -(time_scale * time_scale);
125 for (int i = 0; i < 3; ++i) {
126 g(i + 1, i + 1) = vol[i] * vol[i];
127 }
128 return g;
129 });
130}
131
133 const Eigen::Matrix3d& cov) {
134 return MetricTensor([time_scale, cov](const SpacetimePoint& /*x*/) {
135 MetricMatrix g = MetricMatrix::Zero();
136 g(0, 0) = -(time_scale * time_scale);
137 g.block<3, 3>(1, 1) = cov;
138 return g;
139 });
140}
141
142} // namespace srfm::tensor
double spacetime_interval(const SpacetimePoint &x, const FourVelocity &dx) const
std::optional< MetricMatrix > inverse(const SpacetimePoint &x) const
bool is_lorentzian(const SpacetimePoint &x) const
static MetricTensor make_from_covariance(double time_scale, const Eigen::Matrix3d &cov)
static MetricTensor make_diagonal(double time_scale, const std::array< double, 3 > &vol)
static MetricTensor make_minkowski(double time_scale=1.0, double spatial_scale=1.0)
MetricMatrix evaluate(const SpacetimePoint &x) const
MetricTensor(MetricFunction metric_fn)
Construct from an arbitrary position-dependent metric function.
Physical and financial constants for the SRFM system.
static constexpr double METRIC_SINGULARITY_EPSILON
Epsilon for metric invertibility check (det(g) must exceed this).
Definition constants.hpp:28
static constexpr double TIKHONOV_CONDITION
Relative pivot threshold below which inverse() regularizes the metric.
std::function< MetricMatrix(const SpacetimePoint &)> MetricFunction
Definition tensor.hpp:144
static constexpr double TIKHONOV_LAMBDA
Eigen::Vector< double, SPACETIME_DIM > FourVelocity
A tangent vector at a spacetime point (four-velocity: dx^μ/dτ).
Definition types.hpp:44
Eigen::Matrix< double, SPACETIME_DIM, SPACETIME_DIM > MetricMatrix
The covariant metric tensor g_μν: a 4×4 symmetric matrix.
Definition types.hpp:47
Eigen::Vector< double, SPACETIME_DIM > SpacetimePoint
Definition types.hpp:41
static constexpr int SPACETIME_DIM
Dimensionality of the financial spacetime manifold (1 time + 3 assets).
Definition types.hpp:21
Tensor Calculus & Covariance Engine — AGT-04 public API.