@uor-foundation/geometry
Version:
Layer 5: Geometric manifolds - the shape of mathematical space
220 lines • 8.17 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GeodesicCalculator = void 0;
const metric_1 = require("./metric");
class GeodesicCalculator {
constructor(fieldSubstrate, resonance, topology) {
this.fieldSubstrate = fieldSubstrate;
this.resonance = resonance;
this.topology = topology;
this.metric = new metric_1.ResonanceMetric(fieldSubstrate, resonance, topology);
}
findGeodesic(start, end) {
const path = this.dijkstraGeodesic(start, end);
const length = this.computePathLength(path);
const curvature = this.computePathCurvature(path);
return {
start,
end,
path,
length,
curvature,
};
}
dijkstraGeodesic(start, end) {
if (start === end)
return [start];
const visited = new Set();
const distances = new Map();
const previous = new Map();
const queue = new Set([start]);
distances.set(start.toString(), 0);
while (queue.size > 0) {
let current;
let minDist = Infinity;
for (const node of queue) {
const dist = distances.get(node.toString()) ?? Infinity;
if (dist < minDist) {
minDist = dist;
current = node;
}
}
if (current === undefined || current === end)
break;
queue.delete(current);
visited.add(current.toString());
const neighbors = this.getGeodesicNeighbors(current, end);
for (const neighbor of neighbors) {
if (visited.has(neighbor.toString()))
continue;
const alt = (distances.get(current.toString()) ?? 0) + this.metric.distance(current, neighbor);
if (alt < (distances.get(neighbor.toString()) ?? Infinity)) {
distances.set(neighbor.toString(), alt);
previous.set(neighbor.toString(), current);
queue.add(neighbor);
}
}
if (queue.size > 1000) {
break;
}
}
const path = [];
let current = end;
while (current !== undefined) {
path.unshift(current);
current = previous.get(current.toString());
if (current === start) {
path.unshift(start);
break;
}
}
if (path[0] !== start) {
return this.straightLineGeodesic(start, end);
}
return path;
}
straightLineGeodesic(start, end) {
const path = [];
const step = start < end ? 1n : -1n;
for (let n = start; n !== end; n += step) {
path.push(n);
}
path.push(end);
return path;
}
getGeodesicNeighbors(n, target) {
const neighbors = [];
neighbors.push(n - 1n, n + 1n);
const pageNumber = Number(n / 48n);
const targetPageNumber = Number(target / 48n);
const pageInfo = this.topology.getPageInfo(pageNumber);
const targetPageInfo = this.topology.getPageInfo(targetPageNumber);
const targetPage = targetPageInfo.pageNumber;
if (Math.abs(targetPage - pageInfo.pageNumber) > 1) {
const jumpDistance = 48n;
neighbors.push(n - jumpDistance, n + jumpDistance);
}
const gradient = this.metric.gradient(n);
const maxGradientIdx = gradient.indexOf(Math.max(...gradient.map(Math.abs)));
if (maxGradientIdx >= 0) {
const fieldJump = n + BigInt(1 << maxGradientIdx);
if (fieldJump !== n) {
neighbors.push(fieldJump);
}
}
return neighbors.filter((neighbor) => neighbor >= 0n);
}
computePathLength(path) {
if (path.length < 2)
return 0;
let length = 0;
for (let i = 0; i < path.length - 1; i++) {
length += this.metric.distance(path[i], path[i + 1]);
}
return length;
}
computePathCurvature(path) {
if (path.length < 3)
return [];
const curvatures = [];
for (let i = 1; i < path.length - 1; i++) {
const prev = path[i - 1];
const curr = path[i];
const next = path[i + 1];
const v1 = { x: Number(curr - prev), y: 0 };
const v2 = { x: Number(next - curr), y: 0 };
const angle = Math.atan2(v2.y - v1.y, v2.x - v1.x);
const curvature = angle / Math.sqrt(v1.x * v1.x + v1.y * v1.y);
curvatures.push(curvature);
}
return curvatures;
}
geodesicFlow(start, velocity, time) {
const position = start + BigInt(Math.floor(velocity * time));
const resonanceGradient = this.metric.gradient(position);
const acceleration = -resonanceGradient.reduce((sum, g) => sum + g * g, 0);
return {
position,
velocity: velocity + acceleration * time,
acceleration,
};
}
exponentialMap(basePoint, tangentVector, t) {
const displacement = tangentVector.reduce((sum, v, i) => {
return sum + BigInt(Math.floor(v * t * (1 << i)));
}, 0n);
return basePoint + displacement;
}
parallelTransport(vector, path) {
if (path.length < 2)
return vector;
let current = [...vector];
for (let i = 0; i < path.length - 1; i++) {
const from = path[i];
const to = path[i + 1];
const christoffel = this.metric.christoffelSymbols(from);
const transported = [...current];
for (let j = 0; j < 8; j++) {
let correction = 0;
for (let k = 0; k < 8; k++) {
for (let l = 0; l < 8; l++) {
correction += christoffel[j][k][l] * current[k] * current[l];
}
}
transported[j] -= correction * Number(to - from);
}
const norm = Math.sqrt(transported.reduce((sum, v) => sum + v * v, 0));
if (norm > 0) {
for (let j = 0; j < 8; j++) {
transported[j] /= norm;
}
}
current = transported;
}
return current;
}
isGeodesic(path) {
if (path.length < 2)
return true;
const direct = this.findGeodesic(path[0], path[path.length - 1]);
if (direct.path.length !== path.length)
return false;
const epsilon = 1e-6;
return direct.path.every((point, i) => {
const dist = this.metric.distance(point, path[i]);
return dist < epsilon;
});
}
geodesicDeviation(path1, path2) {
const minLength = Math.min(path1.length, path2.length);
const deviations = [];
for (let i = 0; i < minLength; i++) {
const dist = this.metric.distance(path1[i], path2[i]);
deviations.push(dist);
}
return deviations;
}
conjugatePoints(start, direction) {
const conjugates = [];
const maxDistance = 1000n;
for (let t = 1; t <= 100; t++) {
const point = this.exponentialMap(start, direction, t);
if (point - start > maxDistance)
break;
const jacobian = this.computeJacobian(start, point);
if (Math.abs(jacobian) < 1e-10) {
conjugates.push(point);
}
}
return conjugates;
}
computeJacobian(start, end) {
const h = 1n;
const geodesic = this.findGeodesic(start, end);
const perturbedGeodesic = this.findGeodesic(start + h, end + h);
const deviation = this.geodesicDeviation(geodesic.path, perturbedGeodesic.path);
return deviation.length > 0 ? deviation[deviation.length - 1] / Number(h) : 0;
}
}
exports.GeodesicCalculator = GeodesicCalculator;
//# sourceMappingURL=geodesics.js.map