@justinelliottcobb/amari-wasm 0.15.1 → 0.17.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 +441 -1
- package/amari_wasm.d.ts +283 -2
- package/amari_wasm.js +680 -20
- package/amari_wasm_bg.wasm +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# @justinelliottcobb/amari-wasm v0.
|
|
1
|
+
# @justinelliottcobb/amari-wasm v0.17.0
|
|
2
2
|
|
|
3
3
|
**Unified Mathematical Computing Library with High-Precision WebAssembly Support**
|
|
4
4
|
|
|
@@ -19,6 +19,8 @@ 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
|
|
23
|
+
- **Dynamical Systems** *(v0.17.0)*: ODE solvers, stability analysis, bifurcation diagrams, Lyapunov exponents, and phase portraits
|
|
22
24
|
- **Probability Theory** *(v0.13.0)*: Distributions on multivector spaces, MCMC sampling, and Monte Carlo estimation
|
|
23
25
|
- **Relativistic Physics**: Spacetime algebra (Cl(1,3)) with WebAssembly-compatible precision
|
|
24
26
|
- **Spacecraft Orbital Mechanics**: Full-precision trajectory calculations in browsers
|
|
@@ -570,6 +572,408 @@ async function opticalDemo() {
|
|
|
570
572
|
opticalDemo();
|
|
571
573
|
```
|
|
572
574
|
|
|
575
|
+
### Computational Topology *(v0.16.0)*
|
|
576
|
+
|
|
577
|
+
Compute homology groups, persistent homology, and analyze topological features of data:
|
|
578
|
+
|
|
579
|
+
```typescript
|
|
580
|
+
import init, {
|
|
581
|
+
WasmSimplex,
|
|
582
|
+
WasmSimplicialComplex,
|
|
583
|
+
WasmFiltration,
|
|
584
|
+
WasmPersistentHomology,
|
|
585
|
+
ripsFromDistances,
|
|
586
|
+
findCriticalPoints2D,
|
|
587
|
+
WasmMorseComplex
|
|
588
|
+
} from '@justinelliottcobb/amari-wasm';
|
|
589
|
+
|
|
590
|
+
async function topologyDemo() {
|
|
591
|
+
await init();
|
|
592
|
+
|
|
593
|
+
// ========================================
|
|
594
|
+
// Simplicial Complexes and Homology
|
|
595
|
+
// ========================================
|
|
596
|
+
|
|
597
|
+
// Create a triangle (2-simplex with all faces)
|
|
598
|
+
const complex = new WasmSimplicialComplex();
|
|
599
|
+
complex.addSimplex([0, 1, 2]); // Triangle
|
|
600
|
+
|
|
601
|
+
// Closure property: edges and vertices automatically added
|
|
602
|
+
console.log(`Vertices: ${complex.vertexCount()}`); // 3
|
|
603
|
+
console.log(`Edges: ${complex.edgeCount()}`); // 3
|
|
604
|
+
console.log(`Triangles: ${complex.simplexCount(2)}`); // 1
|
|
605
|
+
|
|
606
|
+
// Compute Betti numbers (topological invariants)
|
|
607
|
+
const betti = complex.bettiNumbers();
|
|
608
|
+
console.log(`β₀ = ${betti[0]}`); // 1 (one connected component)
|
|
609
|
+
console.log(`β₁ = ${betti[1]}`); // 0 (no holes - filled triangle)
|
|
610
|
+
|
|
611
|
+
// Euler characteristic: χ = V - E + F
|
|
612
|
+
console.log(`χ = ${complex.eulerCharacteristic()}`); // 1
|
|
613
|
+
|
|
614
|
+
// ========================================
|
|
615
|
+
// Circle (unfilled triangle boundary)
|
|
616
|
+
// ========================================
|
|
617
|
+
|
|
618
|
+
const circle = new WasmSimplicialComplex();
|
|
619
|
+
circle.addSimplex([0, 1]); // Edge 0-1
|
|
620
|
+
circle.addSimplex([1, 2]); // Edge 1-2
|
|
621
|
+
circle.addSimplex([2, 0]); // Edge 2-0
|
|
622
|
+
|
|
623
|
+
const circleBetti = circle.bettiNumbers();
|
|
624
|
+
console.log(`Circle β₀ = ${circleBetti[0]}`); // 1 (connected)
|
|
625
|
+
console.log(`Circle β₁ = ${circleBetti[1]}`); // 1 (one hole!)
|
|
626
|
+
|
|
627
|
+
// ========================================
|
|
628
|
+
// Persistent Homology
|
|
629
|
+
// ========================================
|
|
630
|
+
|
|
631
|
+
// Build a filtration (simplices appearing over time)
|
|
632
|
+
const filt = new WasmFiltration();
|
|
633
|
+
filt.add(0.0, [0]); // Point 0 at t=0
|
|
634
|
+
filt.add(0.0, [1]); // Point 1 at t=0
|
|
635
|
+
filt.add(0.0, [2]); // Point 2 at t=0
|
|
636
|
+
filt.add(1.0, [0, 1]); // Edge 0-1 at t=1
|
|
637
|
+
filt.add(2.0, [1, 2]); // Edge 1-2 at t=2
|
|
638
|
+
filt.add(3.0, [0, 2]); // Edge 0-2 at t=3 (creates loop)
|
|
639
|
+
|
|
640
|
+
// Compute persistent homology
|
|
641
|
+
const ph = WasmPersistentHomology.compute(filt);
|
|
642
|
+
|
|
643
|
+
// Get persistence diagram as [dim, birth, death] triples
|
|
644
|
+
const diagram = ph.getDiagram();
|
|
645
|
+
for (let i = 0; i < diagram.length; i += 3) {
|
|
646
|
+
const dim = diagram[i];
|
|
647
|
+
const birth = diagram[i + 1];
|
|
648
|
+
const death = diagram[i + 2];
|
|
649
|
+
console.log(`H${dim}: born at ${birth}, dies at ${death === Infinity ? '∞' : death}`);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
// Betti numbers at different times
|
|
653
|
+
console.log(`Betti at t=0.5: ${ph.bettiAt(0.5)}`); // [3, 0] - 3 components
|
|
654
|
+
console.log(`Betti at t=3.5: ${ph.bettiAt(3.5)}`); // [1, 1] - 1 component, 1 loop
|
|
655
|
+
|
|
656
|
+
// ========================================
|
|
657
|
+
// Vietoris-Rips Filtration from Point Cloud
|
|
658
|
+
// ========================================
|
|
659
|
+
|
|
660
|
+
// 3 points forming an equilateral triangle
|
|
661
|
+
// Distances: d(0,1)=1, d(1,2)=1, d(0,2)=1
|
|
662
|
+
const numPoints = 3;
|
|
663
|
+
const maxDim = 2;
|
|
664
|
+
// Upper triangular pairwise distances: [d(0,1), d(0,2), d(1,2)]
|
|
665
|
+
const distances = [1.0, 1.0, 1.0];
|
|
666
|
+
|
|
667
|
+
const ripsFilt = ripsFromDistances(numPoints, maxDim, distances);
|
|
668
|
+
const ripsPH = WasmPersistentHomology.compute(ripsFilt);
|
|
669
|
+
console.log(`Rips intervals in H0: ${ripsPH.intervalCount(0)}`);
|
|
670
|
+
console.log(`Rips intervals in H1: ${ripsPH.intervalCount(1)}`);
|
|
671
|
+
|
|
672
|
+
// ========================================
|
|
673
|
+
// Morse Theory (Critical Points)
|
|
674
|
+
// ========================================
|
|
675
|
+
|
|
676
|
+
// Precompute f(x,y) = x² + y² on a grid
|
|
677
|
+
const resolution = 20;
|
|
678
|
+
const values = [];
|
|
679
|
+
for (let i = 0; i <= resolution; i++) {
|
|
680
|
+
const x = -1.0 + (2.0 * i) / resolution;
|
|
681
|
+
for (let j = 0; j <= resolution; j++) {
|
|
682
|
+
const y = -1.0 + (2.0 * j) / resolution;
|
|
683
|
+
values.push(x * x + y * y);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
const criticalPoints = findCriticalPoints2D(
|
|
688
|
+
resolution,
|
|
689
|
+
-1.0, 1.0, // x range
|
|
690
|
+
-1.0, 1.0, // y range
|
|
691
|
+
0.1, // tolerance
|
|
692
|
+
values
|
|
693
|
+
);
|
|
694
|
+
|
|
695
|
+
console.log(`Found ${criticalPoints.length} critical points`);
|
|
696
|
+
for (const cp of criticalPoints) {
|
|
697
|
+
console.log(` ${cp.criticalType} at (${cp.position[0].toFixed(2)}, ${cp.position[1].toFixed(2)}), value=${cp.value.toFixed(2)}`);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
// Morse complex analysis
|
|
701
|
+
const morse = new WasmMorseComplex(criticalPoints);
|
|
702
|
+
const counts = morse.countsByIndex();
|
|
703
|
+
console.log(`Critical points by index: ${counts}`);
|
|
704
|
+
|
|
705
|
+
// Verify Morse inequalities: c_k >= β_k
|
|
706
|
+
const complexBetti = complex.bettiNumbers();
|
|
707
|
+
console.log(`Weak Morse inequalities hold: ${morse.checkWeakMorseInequalities(complexBetti)}`);
|
|
708
|
+
|
|
709
|
+
// Clean up WASM memory
|
|
710
|
+
complex.free();
|
|
711
|
+
circle.free();
|
|
712
|
+
filt.free();
|
|
713
|
+
ph.free();
|
|
714
|
+
ripsFilt.free();
|
|
715
|
+
ripsPH.free();
|
|
716
|
+
morse.free();
|
|
717
|
+
criticalPoints.forEach(cp => cp.free());
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
topologyDemo();
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
### Dynamical Systems *(v0.17.0)*
|
|
724
|
+
|
|
725
|
+
Analyze chaotic systems, compute bifurcation diagrams, and explore phase space:
|
|
726
|
+
|
|
727
|
+
```typescript
|
|
728
|
+
import init, {
|
|
729
|
+
WasmLorenzSystem,
|
|
730
|
+
WasmVanDerPolOscillator,
|
|
731
|
+
WasmDuffingOscillator,
|
|
732
|
+
WasmRungeKutta4,
|
|
733
|
+
WasmLyapunovSpectrum,
|
|
734
|
+
WasmBifurcationDiagram,
|
|
735
|
+
WasmPhasePortrait,
|
|
736
|
+
WasmStabilityAnalysis,
|
|
737
|
+
computeLyapunovExponents,
|
|
738
|
+
findFixedPoints
|
|
739
|
+
} from '@justinelliottcobb/amari-wasm';
|
|
740
|
+
|
|
741
|
+
async function dynamicsDemo() {
|
|
742
|
+
await init();
|
|
743
|
+
|
|
744
|
+
// ========================================
|
|
745
|
+
// Lorenz Attractor
|
|
746
|
+
// ========================================
|
|
747
|
+
|
|
748
|
+
// Create classic Lorenz system (sigma=10, rho=28, beta=8/3)
|
|
749
|
+
const lorenz = WasmLorenzSystem.classic();
|
|
750
|
+
console.log(`Lorenz parameters: σ=${lorenz.sigma}, ρ=${lorenz.rho}, β=${lorenz.beta}`);
|
|
751
|
+
|
|
752
|
+
// Create RK4 solver
|
|
753
|
+
const solver = new WasmRungeKutta4();
|
|
754
|
+
|
|
755
|
+
// Integrate trajectory from initial condition
|
|
756
|
+
const initial = [1.0, 1.0, 1.0];
|
|
757
|
+
const trajectory = solver.solve(lorenz, initial, 0.0, 50.0, 5000);
|
|
758
|
+
|
|
759
|
+
console.log(`Trajectory has ${trajectory.length} points`);
|
|
760
|
+
|
|
761
|
+
// Get final state
|
|
762
|
+
const finalState = trajectory[trajectory.length - 1];
|
|
763
|
+
console.log(`Final state: (${finalState[0].toFixed(3)}, ${finalState[1].toFixed(3)}, ${finalState[2].toFixed(3)})`);
|
|
764
|
+
|
|
765
|
+
// ========================================
|
|
766
|
+
// Van der Pol Limit Cycle
|
|
767
|
+
// ========================================
|
|
768
|
+
|
|
769
|
+
// Create Van der Pol oscillator with mu = 1.0
|
|
770
|
+
const vdp = WasmVanDerPolOscillator.new(1.0);
|
|
771
|
+
|
|
772
|
+
// Small initial displacement
|
|
773
|
+
const vdpTrajectory = solver.solve(vdp, [0.1, 0.0], 0.0, 50.0, 5000);
|
|
774
|
+
|
|
775
|
+
// Check limit cycle amplitude
|
|
776
|
+
const vdpFinal = vdpTrajectory[vdpTrajectory.length - 1];
|
|
777
|
+
console.log(`Van der Pol final amplitude: ${Math.abs(vdpFinal[0]).toFixed(3)}`);
|
|
778
|
+
|
|
779
|
+
// ========================================
|
|
780
|
+
// Lyapunov Exponents
|
|
781
|
+
// ========================================
|
|
782
|
+
|
|
783
|
+
// Compute Lyapunov spectrum for Lorenz system
|
|
784
|
+
const lyapunov = computeLyapunovExponents(lorenz, initial, 10000, 0.01);
|
|
785
|
+
|
|
786
|
+
console.log(`Lyapunov exponents: [${lyapunov.exponents.map(e => e.toFixed(4)).join(', ')}]`);
|
|
787
|
+
console.log(`Sum: ${lyapunov.sum().toFixed(4)} (negative = dissipative)`);
|
|
788
|
+
|
|
789
|
+
if (lyapunov.exponents[0] > 0) {
|
|
790
|
+
console.log('System is chaotic!');
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// Kaplan-Yorke dimension
|
|
794
|
+
console.log(`Kaplan-Yorke dimension: ${lyapunov.kaplanYorkeDimension().toFixed(3)}`);
|
|
795
|
+
|
|
796
|
+
// ========================================
|
|
797
|
+
// Bifurcation Diagram
|
|
798
|
+
// ========================================
|
|
799
|
+
|
|
800
|
+
// Compute bifurcation diagram for logistic map
|
|
801
|
+
const bifurcation = WasmBifurcationDiagram.compute(
|
|
802
|
+
'logistic',
|
|
803
|
+
2.5, // r_min
|
|
804
|
+
4.0, // r_max
|
|
805
|
+
1000, // num_parameters
|
|
806
|
+
500, // transient iterations
|
|
807
|
+
100 // sample points per parameter
|
|
808
|
+
);
|
|
809
|
+
|
|
810
|
+
console.log(`Bifurcation diagram: ${bifurcation.parameterCount()} parameter values`);
|
|
811
|
+
|
|
812
|
+
// Get attractor points at specific parameter
|
|
813
|
+
const attractorAt3_5 = bifurcation.attractorPoints(3.5);
|
|
814
|
+
console.log(`Attractor at r=3.5: ${attractorAt3_5.length} points`);
|
|
815
|
+
|
|
816
|
+
// ========================================
|
|
817
|
+
// Stability Analysis
|
|
818
|
+
// ========================================
|
|
819
|
+
|
|
820
|
+
// Find fixed points of Van der Pol oscillator
|
|
821
|
+
const fixedPoints = findFixedPoints(vdp, [[0.0, 0.0]], 1e-10);
|
|
822
|
+
|
|
823
|
+
for (const fp of fixedPoints) {
|
|
824
|
+
console.log(`Fixed point: (${fp.point[0].toFixed(6)}, ${fp.point[1].toFixed(6)})`);
|
|
825
|
+
|
|
826
|
+
// Analyze stability
|
|
827
|
+
const stability = WasmStabilityAnalysis.analyze(vdp, fp.point);
|
|
828
|
+
console.log(` Stability: ${stability.stabilityType}`);
|
|
829
|
+
console.log(` Eigenvalues: ${stability.eigenvalues.map(e => `${e.real.toFixed(4)}+${e.imag.toFixed(4)}i`).join(', ')}`);
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
// ========================================
|
|
833
|
+
// Phase Portrait
|
|
834
|
+
// ========================================
|
|
835
|
+
|
|
836
|
+
// Generate phase portrait for Duffing oscillator
|
|
837
|
+
const duffing = WasmDuffingOscillator.new(1.0, -1.0, 0.2, 0.3, 1.2);
|
|
838
|
+
const portrait = WasmPhasePortrait.generate(
|
|
839
|
+
duffing,
|
|
840
|
+
[-2.0, 2.0], // x range
|
|
841
|
+
[-2.0, 2.0], // y range
|
|
842
|
+
20, // grid resolution
|
|
843
|
+
5.0, // integration time
|
|
844
|
+
0.01 // dt
|
|
845
|
+
);
|
|
846
|
+
|
|
847
|
+
console.log(`Phase portrait: ${portrait.trajectoryCount()} trajectories`);
|
|
848
|
+
|
|
849
|
+
// Get nullclines
|
|
850
|
+
const nullclines = portrait.nullclines();
|
|
851
|
+
console.log(`x-nullcline: ${nullclines.x.length} points`);
|
|
852
|
+
console.log(`y-nullcline: ${nullclines.y.length} points`);
|
|
853
|
+
|
|
854
|
+
// Clean up WASM memory
|
|
855
|
+
lorenz.free();
|
|
856
|
+
vdp.free();
|
|
857
|
+
duffing.free();
|
|
858
|
+
solver.free();
|
|
859
|
+
bifurcation.free();
|
|
860
|
+
portrait.free();
|
|
861
|
+
fixedPoints.forEach(fp => fp.free());
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
dynamicsDemo();
|
|
865
|
+
```
|
|
866
|
+
|
|
867
|
+
#### Dynamics API
|
|
868
|
+
|
|
869
|
+
**WasmLorenzSystem:**
|
|
870
|
+
- `classic()`: Create with σ=10, ρ=28, β=8/3
|
|
871
|
+
- `new(sigma, rho, beta)`: Create with custom parameters
|
|
872
|
+
- `sigma`, `rho`, `beta`: Parameter getters
|
|
873
|
+
- `vectorField(state)`: Evaluate dx/dt at state
|
|
874
|
+
|
|
875
|
+
**WasmVanDerPolOscillator:**
|
|
876
|
+
- `new(mu)`: Create with damping parameter μ
|
|
877
|
+
- `mu`: Parameter getter
|
|
878
|
+
- `vectorField(state)`: Evaluate dx/dt at state
|
|
879
|
+
|
|
880
|
+
**WasmDuffingOscillator:**
|
|
881
|
+
- `new(alpha, beta, delta, gamma, omega)`: Create driven Duffing oscillator
|
|
882
|
+
- `vectorField(state, t)`: Evaluate dx/dt at state and time t
|
|
883
|
+
|
|
884
|
+
**WasmRosslerSystem:**
|
|
885
|
+
- `new(a, b, c)`: Create Rossler attractor
|
|
886
|
+
- `classic()`: Create with a=0.2, b=0.2, c=5.7
|
|
887
|
+
|
|
888
|
+
**WasmHenonMap:**
|
|
889
|
+
- `new(a, b)`: Create Henon map
|
|
890
|
+
- `classic()`: Create with a=1.4, b=0.3
|
|
891
|
+
- `iterate(state)`: Apply one map iteration
|
|
892
|
+
|
|
893
|
+
**WasmRungeKutta4:**
|
|
894
|
+
- `new()`: Create RK4 solver
|
|
895
|
+
- `solve(system, initial, t0, t1, steps)`: Integrate trajectory
|
|
896
|
+
- `step(system, state, t, dt)`: Single integration step
|
|
897
|
+
|
|
898
|
+
**WasmAdaptiveSolver:**
|
|
899
|
+
- `rkf45()`: Create RKF45 adaptive solver
|
|
900
|
+
- `dormandPrince()`: Create Dormand-Prince solver
|
|
901
|
+
- `solve(system, initial, t0, t1, tolerance)`: Adaptive integration
|
|
902
|
+
|
|
903
|
+
**Lyapunov Functions:**
|
|
904
|
+
- `computeLyapunovExponents(system, initial, steps, dt)`: Compute spectrum
|
|
905
|
+
- Returns: `{ exponents, sum(), kaplanYorkeDimension(), isChaotic() }`
|
|
906
|
+
|
|
907
|
+
**WasmBifurcationDiagram:**
|
|
908
|
+
- `compute(systemType, paramMin, paramMax, numParams, transient, samples)`: Generate diagram
|
|
909
|
+
- `parameterCount()`: Number of parameter values
|
|
910
|
+
- `attractorPoints(param)`: Get attractor at specific parameter
|
|
911
|
+
- `branches()`: Get all (parameter, points) pairs
|
|
912
|
+
|
|
913
|
+
**WasmStabilityAnalysis:**
|
|
914
|
+
- `analyze(system, point)`: Analyze stability at point
|
|
915
|
+
- `stabilityType`: 'stable_node', 'stable_spiral', 'unstable_node', 'unstable_spiral', 'saddle', 'center'
|
|
916
|
+
- `eigenvalues`: Array of {real, imag} pairs
|
|
917
|
+
- `isStable()`: True if asymptotically stable
|
|
918
|
+
|
|
919
|
+
**findFixedPoints:**
|
|
920
|
+
- `findFixedPoints(system, initialGuesses, tolerance)`: Find fixed points via Newton's method
|
|
921
|
+
- Returns array of `{ point, converged, iterations }`
|
|
922
|
+
|
|
923
|
+
**WasmPhasePortrait:**
|
|
924
|
+
- `generate(system, xRange, yRange, resolution, tMax, dt)`: Generate portrait
|
|
925
|
+
- `trajectoryCount()`: Number of trajectories
|
|
926
|
+
- `trajectories()`: Get all trajectory arrays
|
|
927
|
+
- `nullclines()`: Get {x, y} nullcline point arrays
|
|
928
|
+
|
|
929
|
+
#### Topology API
|
|
930
|
+
|
|
931
|
+
**WasmSimplex:**
|
|
932
|
+
- `new(vertices)`: Create simplex from vertex indices
|
|
933
|
+
- `dimension()`: Get dimension (vertices - 1)
|
|
934
|
+
- `getVertices()`: Get sorted vertex array
|
|
935
|
+
- `orientation()`: Get orientation sign (+1 or -1)
|
|
936
|
+
- `containsVertex(v)`: Check if vertex is in simplex
|
|
937
|
+
- `faces(k)`: Get all k-dimensional faces
|
|
938
|
+
- `boundaryFaces()`: Get boundary faces with signs
|
|
939
|
+
|
|
940
|
+
**WasmSimplicialComplex:**
|
|
941
|
+
- `new()`: Create empty complex
|
|
942
|
+
- `addSimplex(vertices)`: Add simplex and all its faces
|
|
943
|
+
- `contains(vertices)`: Check if simplex exists
|
|
944
|
+
- `dimension()`: Get maximum simplex dimension
|
|
945
|
+
- `simplexCount(dim)`: Count simplices in dimension
|
|
946
|
+
- `totalSimplexCount()`: Total simplex count
|
|
947
|
+
- `vertexCount()`: Count 0-simplices
|
|
948
|
+
- `edgeCount()`: Count 1-simplices
|
|
949
|
+
- `bettiNumbers()`: Compute [β₀, β₁, β₂, ...]
|
|
950
|
+
- `eulerCharacteristic()`: Compute χ = Σ(-1)^k f_k
|
|
951
|
+
- `fVector()`: Get face counts [f₀, f₁, f₂, ...]
|
|
952
|
+
- `isConnected()`: Check if complex is connected
|
|
953
|
+
- `connectedComponents()`: Count components
|
|
954
|
+
|
|
955
|
+
**WasmFiltration:**
|
|
956
|
+
- `new()`: Create empty filtration
|
|
957
|
+
- `add(time, vertices)`: Add simplex at filtration time
|
|
958
|
+
- `isEmpty()`: Check if filtration is empty
|
|
959
|
+
- `complexAt(time)`: Get complex at given time
|
|
960
|
+
- `bettiAt(time)`: Get Betti numbers at time
|
|
961
|
+
|
|
962
|
+
**WasmPersistentHomology:**
|
|
963
|
+
- `compute(filtration)`: Compute persistent homology
|
|
964
|
+
- `getDiagram()`: Get [dim, birth, death, ...] triples
|
|
965
|
+
- `bettiAt(time)`: Get Betti numbers at time
|
|
966
|
+
- `intervalCount(dim)`: Count intervals in dimension
|
|
967
|
+
|
|
968
|
+
**Standalone Functions:**
|
|
969
|
+
- `ripsFromDistances(numPoints, maxDim, distances)`: Create Rips filtration
|
|
970
|
+
- `findCriticalPoints2D(resolution, xMin, xMax, yMin, yMax, tolerance, values)`: Find critical points
|
|
971
|
+
|
|
972
|
+
**WasmMorseComplex:**
|
|
973
|
+
- `new(criticalPoints)`: Create from critical points
|
|
974
|
+
- `countsByIndex()`: Get counts by Morse index
|
|
975
|
+
- `checkWeakMorseInequalities(betti)`: Verify c_k >= β_k
|
|
976
|
+
|
|
573
977
|
#### Optical Field API
|
|
574
978
|
|
|
575
979
|
**WasmOpticalRotorField:**
|
|
@@ -681,6 +1085,12 @@ opticalDemo();
|
|
|
681
1085
|
- **Embedding Retrieval**: Content-addressable semantic search in vector databases
|
|
682
1086
|
- **Holographic Displays**: Lee hologram encoding for DMD and SLM devices
|
|
683
1087
|
- **Optical Computing**: Phase-encoded VSA operations for optical neural networks
|
|
1088
|
+
- **Topological Data Analysis**: Persistent homology for shape and feature detection
|
|
1089
|
+
- **Computational Biology**: Protein structure analysis via simplicial complexes
|
|
1090
|
+
- **Sensor Networks**: Coverage analysis using homology
|
|
1091
|
+
- **Chaos Theory**: Lorenz attractors, bifurcation diagrams, Lyapunov exponents
|
|
1092
|
+
- **Control Systems**: Stability analysis and phase portraits for dynamical systems
|
|
1093
|
+
- **Climate Modeling**: Sensitivity analysis via Lyapunov spectrum computation
|
|
684
1094
|
|
|
685
1095
|
## API Reference
|
|
686
1096
|
|
|
@@ -759,6 +1169,36 @@ opticalDemo();
|
|
|
759
1169
|
- `WasmOpticalCodebook.get(symbol)`: Get field for symbol
|
|
760
1170
|
- `WasmTropicalOpticalAlgebra.tropicalAdd(a, b)`: Pointwise minimum phase
|
|
761
1171
|
|
|
1172
|
+
### Topology Operations
|
|
1173
|
+
|
|
1174
|
+
- `WasmSimplex.new(vertices)`: Create simplex from vertex array
|
|
1175
|
+
- `WasmSimplex.dimension()`: Get simplex dimension
|
|
1176
|
+
- `WasmSimplex.faces(k)`: Get k-dimensional faces
|
|
1177
|
+
- `WasmSimplicialComplex.new()`: Create empty complex
|
|
1178
|
+
- `WasmSimplicialComplex.addSimplex(vertices)`: Add simplex with closure
|
|
1179
|
+
- `WasmSimplicialComplex.bettiNumbers()`: Compute Betti numbers
|
|
1180
|
+
- `WasmSimplicialComplex.eulerCharacteristic()`: Compute Euler characteristic
|
|
1181
|
+
- `WasmFiltration.add(time, vertices)`: Add simplex at filtration time
|
|
1182
|
+
- `WasmPersistentHomology.compute(filtration)`: Compute persistence
|
|
1183
|
+
- `WasmPersistentHomology.getDiagram()`: Get persistence diagram
|
|
1184
|
+
- `ripsFromDistances(n, dim, distances)`: Build Rips filtration
|
|
1185
|
+
- `findCriticalPoints2D(...)`: Find Morse critical points
|
|
1186
|
+
|
|
1187
|
+
### Dynamics Operations
|
|
1188
|
+
|
|
1189
|
+
- `WasmLorenzSystem.classic()`: Create classic Lorenz attractor
|
|
1190
|
+
- `WasmVanDerPolOscillator.new(mu)`: Create Van der Pol oscillator
|
|
1191
|
+
- `WasmDuffingOscillator.new(alpha, beta, delta, gamma, omega)`: Create Duffing oscillator
|
|
1192
|
+
- `WasmRosslerSystem.classic()`: Create Rossler attractor
|
|
1193
|
+
- `WasmHenonMap.classic()`: Create Henon map
|
|
1194
|
+
- `WasmRungeKutta4.solve(system, initial, t0, t1, steps)`: Integrate trajectory
|
|
1195
|
+
- `WasmAdaptiveSolver.rkf45()`: Create adaptive RKF45 solver
|
|
1196
|
+
- `computeLyapunovExponents(system, initial, steps, dt)`: Compute Lyapunov spectrum
|
|
1197
|
+
- `WasmBifurcationDiagram.compute(type, paramMin, paramMax, n, transient, samples)`: Generate bifurcation diagram
|
|
1198
|
+
- `WasmStabilityAnalysis.analyze(system, point)`: Analyze fixed point stability
|
|
1199
|
+
- `findFixedPoints(system, guesses, tolerance)`: Find fixed points
|
|
1200
|
+
- `WasmPhasePortrait.generate(system, xRange, yRange, res, tMax, dt)`: Generate phase portrait
|
|
1201
|
+
|
|
762
1202
|
## Examples
|
|
763
1203
|
|
|
764
1204
|
Check out the [examples directory](https://github.com/justinelliottcobb/Amari/tree/master/examples) for more detailed usage:
|