@justinelliottcobb/amari-wasm 0.15.1 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +216 -1
- package/package.json +26 -21
- package/amari_wasm.d.ts +0 -4388
- package/amari_wasm.js +0 -10403
- package/amari_wasm_bg.wasm +0 -0
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# @justinelliottcobb/amari-wasm v0.
|
|
1
|
+
# @justinelliottcobb/amari-wasm v0.16.0
|
|
2
2
|
|
|
3
3
|
**Unified Mathematical Computing Library with High-Precision WebAssembly Support**
|
|
4
4
|
|
|
@@ -19,6 +19,7 @@ Amari is a comprehensive mathematical computing library that brings advanced alg
|
|
|
19
19
|
- **Holographic Memory** *(v0.12.3)*: Vector Symbolic Architecture for associative memory with binding and bundling operations
|
|
20
20
|
- **Functional Analysis** *(v0.15.0)*: Hilbert spaces, linear operators, spectral decomposition, and Sobolev spaces
|
|
21
21
|
- **Optical Field Operations** *(v0.15.1)*: GA-native Lee hologram encoding for DMD displays and VSA-based optical processing
|
|
22
|
+
- **Computational Topology** *(v0.16.0)*: Simplicial complexes, homology computation, persistent homology, and Morse theory
|
|
22
23
|
- **Probability Theory** *(v0.13.0)*: Distributions on multivector spaces, MCMC sampling, and Monte Carlo estimation
|
|
23
24
|
- **Relativistic Physics**: Spacetime algebra (Cl(1,3)) with WebAssembly-compatible precision
|
|
24
25
|
- **Spacecraft Orbital Mechanics**: Full-precision trajectory calculations in browsers
|
|
@@ -570,6 +571,202 @@ async function opticalDemo() {
|
|
|
570
571
|
opticalDemo();
|
|
571
572
|
```
|
|
572
573
|
|
|
574
|
+
### Computational Topology *(v0.16.0)*
|
|
575
|
+
|
|
576
|
+
Compute homology groups, persistent homology, and analyze topological features of data:
|
|
577
|
+
|
|
578
|
+
```typescript
|
|
579
|
+
import init, {
|
|
580
|
+
WasmSimplex,
|
|
581
|
+
WasmSimplicialComplex,
|
|
582
|
+
WasmFiltration,
|
|
583
|
+
WasmPersistentHomology,
|
|
584
|
+
ripsFromDistances,
|
|
585
|
+
findCriticalPoints2D,
|
|
586
|
+
WasmMorseComplex
|
|
587
|
+
} from '@justinelliottcobb/amari-wasm';
|
|
588
|
+
|
|
589
|
+
async function topologyDemo() {
|
|
590
|
+
await init();
|
|
591
|
+
|
|
592
|
+
// ========================================
|
|
593
|
+
// Simplicial Complexes and Homology
|
|
594
|
+
// ========================================
|
|
595
|
+
|
|
596
|
+
// Create a triangle (2-simplex with all faces)
|
|
597
|
+
const complex = new WasmSimplicialComplex();
|
|
598
|
+
complex.addSimplex([0, 1, 2]); // Triangle
|
|
599
|
+
|
|
600
|
+
// Closure property: edges and vertices automatically added
|
|
601
|
+
console.log(`Vertices: ${complex.vertexCount()}`); // 3
|
|
602
|
+
console.log(`Edges: ${complex.edgeCount()}`); // 3
|
|
603
|
+
console.log(`Triangles: ${complex.simplexCount(2)}`); // 1
|
|
604
|
+
|
|
605
|
+
// Compute Betti numbers (topological invariants)
|
|
606
|
+
const betti = complex.bettiNumbers();
|
|
607
|
+
console.log(`β₀ = ${betti[0]}`); // 1 (one connected component)
|
|
608
|
+
console.log(`β₁ = ${betti[1]}`); // 0 (no holes - filled triangle)
|
|
609
|
+
|
|
610
|
+
// Euler characteristic: χ = V - E + F
|
|
611
|
+
console.log(`χ = ${complex.eulerCharacteristic()}`); // 1
|
|
612
|
+
|
|
613
|
+
// ========================================
|
|
614
|
+
// Circle (unfilled triangle boundary)
|
|
615
|
+
// ========================================
|
|
616
|
+
|
|
617
|
+
const circle = new WasmSimplicialComplex();
|
|
618
|
+
circle.addSimplex([0, 1]); // Edge 0-1
|
|
619
|
+
circle.addSimplex([1, 2]); // Edge 1-2
|
|
620
|
+
circle.addSimplex([2, 0]); // Edge 2-0
|
|
621
|
+
|
|
622
|
+
const circleBetti = circle.bettiNumbers();
|
|
623
|
+
console.log(`Circle β₀ = ${circleBetti[0]}`); // 1 (connected)
|
|
624
|
+
console.log(`Circle β₁ = ${circleBetti[1]}`); // 1 (one hole!)
|
|
625
|
+
|
|
626
|
+
// ========================================
|
|
627
|
+
// Persistent Homology
|
|
628
|
+
// ========================================
|
|
629
|
+
|
|
630
|
+
// Build a filtration (simplices appearing over time)
|
|
631
|
+
const filt = new WasmFiltration();
|
|
632
|
+
filt.add(0.0, [0]); // Point 0 at t=0
|
|
633
|
+
filt.add(0.0, [1]); // Point 1 at t=0
|
|
634
|
+
filt.add(0.0, [2]); // Point 2 at t=0
|
|
635
|
+
filt.add(1.0, [0, 1]); // Edge 0-1 at t=1
|
|
636
|
+
filt.add(2.0, [1, 2]); // Edge 1-2 at t=2
|
|
637
|
+
filt.add(3.0, [0, 2]); // Edge 0-2 at t=3 (creates loop)
|
|
638
|
+
|
|
639
|
+
// Compute persistent homology
|
|
640
|
+
const ph = WasmPersistentHomology.compute(filt);
|
|
641
|
+
|
|
642
|
+
// Get persistence diagram as [dim, birth, death] triples
|
|
643
|
+
const diagram = ph.getDiagram();
|
|
644
|
+
for (let i = 0; i < diagram.length; i += 3) {
|
|
645
|
+
const dim = diagram[i];
|
|
646
|
+
const birth = diagram[i + 1];
|
|
647
|
+
const death = diagram[i + 2];
|
|
648
|
+
console.log(`H${dim}: born at ${birth}, dies at ${death === Infinity ? '∞' : death}`);
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// Betti numbers at different times
|
|
652
|
+
console.log(`Betti at t=0.5: ${ph.bettiAt(0.5)}`); // [3, 0] - 3 components
|
|
653
|
+
console.log(`Betti at t=3.5: ${ph.bettiAt(3.5)}`); // [1, 1] - 1 component, 1 loop
|
|
654
|
+
|
|
655
|
+
// ========================================
|
|
656
|
+
// Vietoris-Rips Filtration from Point Cloud
|
|
657
|
+
// ========================================
|
|
658
|
+
|
|
659
|
+
// 3 points forming an equilateral triangle
|
|
660
|
+
// Distances: d(0,1)=1, d(1,2)=1, d(0,2)=1
|
|
661
|
+
const numPoints = 3;
|
|
662
|
+
const maxDim = 2;
|
|
663
|
+
// Upper triangular pairwise distances: [d(0,1), d(0,2), d(1,2)]
|
|
664
|
+
const distances = [1.0, 1.0, 1.0];
|
|
665
|
+
|
|
666
|
+
const ripsFilt = ripsFromDistances(numPoints, maxDim, distances);
|
|
667
|
+
const ripsPH = WasmPersistentHomology.compute(ripsFilt);
|
|
668
|
+
console.log(`Rips intervals in H0: ${ripsPH.intervalCount(0)}`);
|
|
669
|
+
console.log(`Rips intervals in H1: ${ripsPH.intervalCount(1)}`);
|
|
670
|
+
|
|
671
|
+
// ========================================
|
|
672
|
+
// Morse Theory (Critical Points)
|
|
673
|
+
// ========================================
|
|
674
|
+
|
|
675
|
+
// Precompute f(x,y) = x² + y² on a grid
|
|
676
|
+
const resolution = 20;
|
|
677
|
+
const values = [];
|
|
678
|
+
for (let i = 0; i <= resolution; i++) {
|
|
679
|
+
const x = -1.0 + (2.0 * i) / resolution;
|
|
680
|
+
for (let j = 0; j <= resolution; j++) {
|
|
681
|
+
const y = -1.0 + (2.0 * j) / resolution;
|
|
682
|
+
values.push(x * x + y * y);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
const criticalPoints = findCriticalPoints2D(
|
|
687
|
+
resolution,
|
|
688
|
+
-1.0, 1.0, // x range
|
|
689
|
+
-1.0, 1.0, // y range
|
|
690
|
+
0.1, // tolerance
|
|
691
|
+
values
|
|
692
|
+
);
|
|
693
|
+
|
|
694
|
+
console.log(`Found ${criticalPoints.length} critical points`);
|
|
695
|
+
for (const cp of criticalPoints) {
|
|
696
|
+
console.log(` ${cp.criticalType} at (${cp.position[0].toFixed(2)}, ${cp.position[1].toFixed(2)}), value=${cp.value.toFixed(2)}`);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// Morse complex analysis
|
|
700
|
+
const morse = new WasmMorseComplex(criticalPoints);
|
|
701
|
+
const counts = morse.countsByIndex();
|
|
702
|
+
console.log(`Critical points by index: ${counts}`);
|
|
703
|
+
|
|
704
|
+
// Verify Morse inequalities: c_k >= β_k
|
|
705
|
+
const complexBetti = complex.bettiNumbers();
|
|
706
|
+
console.log(`Weak Morse inequalities hold: ${morse.checkWeakMorseInequalities(complexBetti)}`);
|
|
707
|
+
|
|
708
|
+
// Clean up WASM memory
|
|
709
|
+
complex.free();
|
|
710
|
+
circle.free();
|
|
711
|
+
filt.free();
|
|
712
|
+
ph.free();
|
|
713
|
+
ripsFilt.free();
|
|
714
|
+
ripsPH.free();
|
|
715
|
+
morse.free();
|
|
716
|
+
criticalPoints.forEach(cp => cp.free());
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
topologyDemo();
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
#### Topology API
|
|
723
|
+
|
|
724
|
+
**WasmSimplex:**
|
|
725
|
+
- `new(vertices)`: Create simplex from vertex indices
|
|
726
|
+
- `dimension()`: Get dimension (vertices - 1)
|
|
727
|
+
- `getVertices()`: Get sorted vertex array
|
|
728
|
+
- `orientation()`: Get orientation sign (+1 or -1)
|
|
729
|
+
- `containsVertex(v)`: Check if vertex is in simplex
|
|
730
|
+
- `faces(k)`: Get all k-dimensional faces
|
|
731
|
+
- `boundaryFaces()`: Get boundary faces with signs
|
|
732
|
+
|
|
733
|
+
**WasmSimplicialComplex:**
|
|
734
|
+
- `new()`: Create empty complex
|
|
735
|
+
- `addSimplex(vertices)`: Add simplex and all its faces
|
|
736
|
+
- `contains(vertices)`: Check if simplex exists
|
|
737
|
+
- `dimension()`: Get maximum simplex dimension
|
|
738
|
+
- `simplexCount(dim)`: Count simplices in dimension
|
|
739
|
+
- `totalSimplexCount()`: Total simplex count
|
|
740
|
+
- `vertexCount()`: Count 0-simplices
|
|
741
|
+
- `edgeCount()`: Count 1-simplices
|
|
742
|
+
- `bettiNumbers()`: Compute [β₀, β₁, β₂, ...]
|
|
743
|
+
- `eulerCharacteristic()`: Compute χ = Σ(-1)^k f_k
|
|
744
|
+
- `fVector()`: Get face counts [f₀, f₁, f₂, ...]
|
|
745
|
+
- `isConnected()`: Check if complex is connected
|
|
746
|
+
- `connectedComponents()`: Count components
|
|
747
|
+
|
|
748
|
+
**WasmFiltration:**
|
|
749
|
+
- `new()`: Create empty filtration
|
|
750
|
+
- `add(time, vertices)`: Add simplex at filtration time
|
|
751
|
+
- `isEmpty()`: Check if filtration is empty
|
|
752
|
+
- `complexAt(time)`: Get complex at given time
|
|
753
|
+
- `bettiAt(time)`: Get Betti numbers at time
|
|
754
|
+
|
|
755
|
+
**WasmPersistentHomology:**
|
|
756
|
+
- `compute(filtration)`: Compute persistent homology
|
|
757
|
+
- `getDiagram()`: Get [dim, birth, death, ...] triples
|
|
758
|
+
- `bettiAt(time)`: Get Betti numbers at time
|
|
759
|
+
- `intervalCount(dim)`: Count intervals in dimension
|
|
760
|
+
|
|
761
|
+
**Standalone Functions:**
|
|
762
|
+
- `ripsFromDistances(numPoints, maxDim, distances)`: Create Rips filtration
|
|
763
|
+
- `findCriticalPoints2D(resolution, xMin, xMax, yMin, yMax, tolerance, values)`: Find critical points
|
|
764
|
+
|
|
765
|
+
**WasmMorseComplex:**
|
|
766
|
+
- `new(criticalPoints)`: Create from critical points
|
|
767
|
+
- `countsByIndex()`: Get counts by Morse index
|
|
768
|
+
- `checkWeakMorseInequalities(betti)`: Verify c_k >= β_k
|
|
769
|
+
|
|
573
770
|
#### Optical Field API
|
|
574
771
|
|
|
575
772
|
**WasmOpticalRotorField:**
|
|
@@ -681,6 +878,9 @@ opticalDemo();
|
|
|
681
878
|
- **Embedding Retrieval**: Content-addressable semantic search in vector databases
|
|
682
879
|
- **Holographic Displays**: Lee hologram encoding for DMD and SLM devices
|
|
683
880
|
- **Optical Computing**: Phase-encoded VSA operations for optical neural networks
|
|
881
|
+
- **Topological Data Analysis**: Persistent homology for shape and feature detection
|
|
882
|
+
- **Computational Biology**: Protein structure analysis via simplicial complexes
|
|
883
|
+
- **Sensor Networks**: Coverage analysis using homology
|
|
684
884
|
|
|
685
885
|
## API Reference
|
|
686
886
|
|
|
@@ -759,6 +959,21 @@ opticalDemo();
|
|
|
759
959
|
- `WasmOpticalCodebook.get(symbol)`: Get field for symbol
|
|
760
960
|
- `WasmTropicalOpticalAlgebra.tropicalAdd(a, b)`: Pointwise minimum phase
|
|
761
961
|
|
|
962
|
+
### Topology Operations
|
|
963
|
+
|
|
964
|
+
- `WasmSimplex.new(vertices)`: Create simplex from vertex array
|
|
965
|
+
- `WasmSimplex.dimension()`: Get simplex dimension
|
|
966
|
+
- `WasmSimplex.faces(k)`: Get k-dimensional faces
|
|
967
|
+
- `WasmSimplicialComplex.new()`: Create empty complex
|
|
968
|
+
- `WasmSimplicialComplex.addSimplex(vertices)`: Add simplex with closure
|
|
969
|
+
- `WasmSimplicialComplex.bettiNumbers()`: Compute Betti numbers
|
|
970
|
+
- `WasmSimplicialComplex.eulerCharacteristic()`: Compute Euler characteristic
|
|
971
|
+
- `WasmFiltration.add(time, vertices)`: Add simplex at filtration time
|
|
972
|
+
- `WasmPersistentHomology.compute(filtration)`: Compute persistence
|
|
973
|
+
- `WasmPersistentHomology.getDiagram()`: Get persistence diagram
|
|
974
|
+
- `ripsFromDistances(n, dim, distances)`: Build Rips filtration
|
|
975
|
+
- `findCriticalPoints2D(...)`: Find Morse critical points
|
|
976
|
+
|
|
762
977
|
## Examples
|
|
763
978
|
|
|
764
979
|
Check out the [examples directory](https://github.com/justinelliottcobb/Amari/tree/master/examples) for more detailed usage:
|
package/package.json
CHANGED
|
@@ -1,32 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@justinelliottcobb/amari-wasm",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
"version": "0.16.0",
|
|
4
|
+
"description": "WebAssembly bindings for Amari mathematical computing library",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "wasm-pack build --target web --out-dir pkg --scope justinelliottcobb",
|
|
7
|
+
"build-all": "npm run build && npm run build:node && npm run build:bundler",
|
|
8
|
+
"build:node": "wasm-pack build --target nodejs --out-dir pkg-node --scope justinelliottcobb",
|
|
9
|
+
"build:bundler": "wasm-pack build --target bundler --out-dir pkg-bundler --scope justinelliottcobb",
|
|
10
|
+
"test": "wasm-pack test --node",
|
|
11
|
+
"clean": "rm -rf pkg pkg-node pkg-bundler"
|
|
12
|
+
},
|
|
10
13
|
"repository": {
|
|
11
14
|
"type": "git",
|
|
12
|
-
"url": "https://github.com/justinelliottcobb/Amari"
|
|
15
|
+
"url": "https://github.com/justinelliottcobb/Amari.git"
|
|
13
16
|
},
|
|
14
|
-
"
|
|
15
|
-
"amari_wasm_bg.wasm",
|
|
16
|
-
"amari_wasm.js",
|
|
17
|
-
"amari_wasm.d.ts"
|
|
18
|
-
],
|
|
19
|
-
"main": "amari_wasm.js",
|
|
20
|
-
"homepage": "https://github.com/justinelliottcobb/Amari",
|
|
21
|
-
"types": "amari_wasm.d.ts",
|
|
22
|
-
"sideEffects": [
|
|
23
|
-
"./snippets/*"
|
|
24
|
-
],
|
|
17
|
+
"license": "MIT OR Apache-2.0",
|
|
25
18
|
"keywords": [
|
|
26
19
|
"wasm",
|
|
27
20
|
"webassembly",
|
|
28
21
|
"geometric-algebra",
|
|
29
22
|
"tropical-algebra",
|
|
30
|
-
"autodiff"
|
|
31
|
-
|
|
23
|
+
"autodiff",
|
|
24
|
+
"mathematics",
|
|
25
|
+
"topology",
|
|
26
|
+
"persistent-homology"
|
|
27
|
+
],
|
|
28
|
+
"files": [
|
|
29
|
+
"pkg/",
|
|
30
|
+
"pkg-node/",
|
|
31
|
+
"pkg-bundler/"
|
|
32
|
+
],
|
|
33
|
+
"devDependencies": {},
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=16"
|
|
36
|
+
}
|
|
32
37
|
}
|