@graphty/layout 1.2.6 → 1.2.8
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 +55 -5
- package/dist/layout.d.ts +17 -0
- package/dist/src/algorithms/index.d.ts +5 -0
- package/dist/src/algorithms/index.js +6 -0
- package/dist/src/algorithms/index.js.map +1 -0
- package/dist/src/algorithms/optimization/index.d.ts +7 -0
- package/dist/src/algorithms/optimization/index.js +7 -0
- package/dist/src/algorithms/optimization/index.js.map +1 -0
- package/dist/src/algorithms/optimization/kamada-kawai-solver.d.ts +32 -0
- package/dist/src/algorithms/optimization/kamada-kawai-solver.js +176 -0
- package/dist/src/algorithms/optimization/kamada-kawai-solver.js.map +1 -0
- package/dist/src/algorithms/optimization/lbfgs.d.ts +13 -0
- package/dist/src/algorithms/optimization/lbfgs.js +56 -0
- package/dist/src/algorithms/optimization/lbfgs.js.map +1 -0
- package/dist/src/algorithms/optimization/line-search.d.ts +15 -0
- package/dist/src/algorithms/optimization/line-search.js +37 -0
- package/dist/src/algorithms/optimization/line-search.js.map +1 -0
- package/dist/src/algorithms/optimization/types.d.ts +5 -0
- package/dist/src/algorithms/optimization/types.js +5 -0
- package/dist/src/algorithms/optimization/types.js.map +1 -0
- package/dist/src/algorithms/planarity/check.d.ts +17 -0
- package/dist/src/algorithms/planarity/check.js +30 -0
- package/dist/src/algorithms/planarity/check.js.map +1 -0
- package/dist/src/algorithms/planarity/embedding.d.ts +29 -0
- package/dist/src/algorithms/planarity/embedding.js +179 -0
- package/dist/src/algorithms/planarity/embedding.js.map +1 -0
- package/dist/src/algorithms/planarity/index.d.ts +7 -0
- package/dist/src/algorithms/planarity/index.js +8 -0
- package/dist/src/algorithms/planarity/index.js.map +1 -0
- package/dist/src/algorithms/planarity/lr-test.d.ts +15 -0
- package/dist/src/algorithms/planarity/lr-test.js +54 -0
- package/dist/src/algorithms/planarity/lr-test.js.map +1 -0
- package/dist/src/algorithms/planarity/special-graphs.d.ts +28 -0
- package/dist/src/algorithms/planarity/special-graphs.js +108 -0
- package/dist/src/algorithms/planarity/special-graphs.js.map +1 -0
- package/dist/src/generators/basic.d.ts +28 -0
- package/dist/src/generators/basic.js +79 -0
- package/dist/src/generators/basic.js.map +1 -0
- package/dist/src/generators/bipartite.d.ts +16 -0
- package/dist/src/generators/bipartite.js +40 -0
- package/dist/src/generators/bipartite.js.map +1 -0
- package/dist/src/generators/grid.d.ts +11 -0
- package/dist/src/generators/grid.js +37 -0
- package/dist/src/generators/grid.js.map +1 -0
- package/dist/src/generators/index.d.ts +8 -0
- package/dist/src/generators/index.js +9 -0
- package/dist/src/generators/index.js.map +1 -0
- package/dist/src/generators/random.d.ts +12 -0
- package/dist/src/generators/random.js +34 -0
- package/dist/src/generators/random.js.map +1 -0
- package/dist/src/generators/scale-free.d.ts +12 -0
- package/dist/src/generators/scale-free.js +62 -0
- package/dist/src/generators/scale-free.js.map +1 -0
- package/dist/src/index.d.ts +10 -0
- package/dist/src/index.js +15 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/layouts/basic/index.d.ts +4 -0
- package/dist/src/layouts/basic/index.js +5 -0
- package/dist/src/layouts/basic/index.js.map +1 -0
- package/dist/src/layouts/basic/random.d.ts +14 -0
- package/dist/src/layouts/basic/random.js +27 -0
- package/dist/src/layouts/basic/random.js.map +1 -0
- package/dist/src/layouts/force-directed/arf.d.ts +13 -0
- package/dist/src/layouts/force-directed/arf.js +103 -0
- package/dist/src/layouts/force-directed/arf.js.map +1 -0
- package/dist/src/layouts/force-directed/forceatlas2.d.ts +22 -0
- package/dist/src/layouts/force-directed/forceatlas2.js +340 -0
- package/dist/src/layouts/force-directed/forceatlas2.js.map +1 -0
- package/dist/src/layouts/force-directed/fruchterman-reingold.d.ts +19 -0
- package/dist/src/layouts/force-directed/fruchterman-reingold.js +131 -0
- package/dist/src/layouts/force-directed/fruchterman-reingold.js.map +1 -0
- package/dist/src/layouts/force-directed/index.d.ts +8 -0
- package/dist/src/layouts/force-directed/index.js +9 -0
- package/dist/src/layouts/force-directed/index.js.map +1 -0
- package/dist/src/layouts/force-directed/kamada-kawai.d.ts +15 -0
- package/dist/src/layouts/force-directed/kamada-kawai.js +87 -0
- package/dist/src/layouts/force-directed/kamada-kawai.js.map +1 -0
- package/dist/src/layouts/force-directed/spring.d.ts +19 -0
- package/dist/src/layouts/force-directed/spring.js +23 -0
- package/dist/src/layouts/force-directed/spring.js.map +1 -0
- package/dist/src/layouts/geometric/circular.d.ts +14 -0
- package/dist/src/layouts/geometric/circular.js +67 -0
- package/dist/src/layouts/geometric/circular.js.map +1 -0
- package/dist/src/layouts/geometric/index.d.ts +6 -0
- package/dist/src/layouts/geometric/index.js +7 -0
- package/dist/src/layouts/geometric/index.js.map +1 -0
- package/dist/src/layouts/geometric/shell.d.ts +15 -0
- package/dist/src/layouts/geometric/shell.js +67 -0
- package/dist/src/layouts/geometric/shell.js.map +1 -0
- package/dist/src/layouts/geometric/spiral.d.ts +16 -0
- package/dist/src/layouts/geometric/spiral.js +73 -0
- package/dist/src/layouts/geometric/spiral.js.map +1 -0
- package/dist/src/layouts/hierarchical/bfs.d.ts +12 -0
- package/dist/src/layouts/hierarchical/bfs.js +62 -0
- package/dist/src/layouts/hierarchical/bfs.js.map +1 -0
- package/dist/src/layouts/hierarchical/bipartite.d.ts +16 -0
- package/dist/src/layouts/hierarchical/bipartite.js +72 -0
- package/dist/src/layouts/hierarchical/bipartite.js.map +1 -0
- package/dist/src/layouts/hierarchical/index.d.ts +6 -0
- package/dist/src/layouts/hierarchical/index.js +7 -0
- package/dist/src/layouts/hierarchical/index.js.map +1 -0
- package/dist/src/layouts/hierarchical/multipartite.d.ts +12 -0
- package/dist/src/layouts/hierarchical/multipartite.js +73 -0
- package/dist/src/layouts/hierarchical/multipartite.js.map +1 -0
- package/dist/src/layouts/index.d.ts +8 -0
- package/dist/src/layouts/index.js +9 -0
- package/dist/src/layouts/index.js.map +1 -0
- package/dist/src/layouts/specialized/index.d.ts +5 -0
- package/dist/src/layouts/specialized/index.js +6 -0
- package/dist/src/layouts/specialized/index.js.map +1 -0
- package/dist/src/layouts/specialized/planar.d.ts +14 -0
- package/dist/src/layouts/specialized/planar.js +47 -0
- package/dist/src/layouts/specialized/planar.js.map +1 -0
- package/dist/src/layouts/specialized/spectral.d.ts +14 -0
- package/dist/src/layouts/specialized/spectral.js +106 -0
- package/dist/src/layouts/specialized/spectral.js.map +1 -0
- package/dist/src/types/embedding.d.ts +9 -0
- package/dist/src/types/embedding.js +5 -0
- package/dist/src/types/embedding.js.map +1 -0
- package/dist/src/types/graph.d.ts +10 -0
- package/dist/src/types/graph.js +5 -0
- package/dist/src/types/graph.js.map +1 -0
- package/dist/src/types/index.d.ts +6 -0
- package/dist/src/types/index.js +7 -0
- package/dist/src/types/index.js.map +1 -0
- package/dist/src/types/layout.d.ts +6 -0
- package/dist/src/types/layout.js +5 -0
- package/dist/src/types/layout.js.map +1 -0
- package/dist/src/utils/graph.d.ts +34 -0
- package/dist/src/utils/graph.js +69 -0
- package/dist/src/utils/graph.js.map +1 -0
- package/dist/src/utils/index.d.ts +8 -0
- package/dist/src/utils/index.js +9 -0
- package/dist/src/utils/index.js.map +1 -0
- package/dist/src/utils/numpy.d.ts +17 -0
- package/dist/src/utils/numpy.js +101 -0
- package/dist/src/utils/numpy.js.map +1 -0
- package/dist/src/utils/params.d.ts +17 -0
- package/dist/src/utils/params.js +22 -0
- package/dist/src/utils/params.js.map +1 -0
- package/dist/src/utils/random.d.ts +14 -0
- package/dist/src/utils/random.js +42 -0
- package/dist/src/utils/random.js.map +1 -0
- package/dist/src/utils/rescale.d.ts +21 -0
- package/dist/src/utils/rescale.js +194 -0
- package/dist/src/utils/rescale.js.map +1 -0
- package/dist/vitest.config.d.ts +2 -0
- package/dist/vitest.config.js +30 -0
- package/dist/vitest.config.js.map +1 -0
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
[](https://coveralls.io/github/graphty-org/layout?branch=main)
|
|
5
5
|
[](https://badge.fury.io/js/%40graphty%2Flayout)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
|
-
[](https://graphty-org.github.io/layout/)
|
|
7
|
+
[](https://graphty-org.github.io/layout/examples/index.html)
|
|
8
8
|
|
|
9
|
-
**[View Interactive Examples →](https://graphty-org.github.io/layout/index.html)**
|
|
9
|
+
**[View Interactive Examples →](https://graphty-org.github.io/layout/examples/index.html)**
|
|
10
10
|
|
|
11
11
|
Layout is a TypeScript library for positioning nodes in graphs. It's a TypeScript port of the [layout algorithms](https://networkx.org/documentation/stable/reference/drawing.html) from the Python [NetworkX](https://networkx.org/documentation/stable/) library.
|
|
12
12
|
|
|
@@ -51,6 +51,12 @@ Additionally, the library includes:
|
|
|
51
51
|
- **combineLayouts** - Blend multiple layout algorithms
|
|
52
52
|
- **interpolateLayouts** - Smooth animation between layouts
|
|
53
53
|
|
|
54
|
+
## Installation
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npm install @graphty/layout
|
|
58
|
+
```
|
|
59
|
+
|
|
54
60
|
## How to Use
|
|
55
61
|
|
|
56
62
|
Import the library in your TypeScript/JavaScript project:
|
|
@@ -91,7 +97,7 @@ import {
|
|
|
91
97
|
layoutQuality,
|
|
92
98
|
combineLayouts,
|
|
93
99
|
interpolateLayouts
|
|
94
|
-
} from '
|
|
100
|
+
} from '@graphty/layout'
|
|
95
101
|
```
|
|
96
102
|
|
|
97
103
|
## Quick Start
|
|
@@ -476,12 +482,30 @@ if (detected) {
|
|
|
476
482
|
}
|
|
477
483
|
```
|
|
478
484
|
|
|
485
|
+
## 3D Support
|
|
486
|
+
|
|
487
|
+
All layout algorithms support 3D positioning by setting the `dim` parameter to 3:
|
|
488
|
+
|
|
489
|
+
```typescript
|
|
490
|
+
// Any layout algorithm in 3D
|
|
491
|
+
const positions3D = springLayout(graph, null, null, null, 50, 1, [0, 0, 0], 3)
|
|
492
|
+
// Returns: { node1: [x, y, z], node2: [x, y, z], ... }
|
|
493
|
+
|
|
494
|
+
// ForceAtlas2 in 3D
|
|
495
|
+
const fa3D = forceatlas2Layout(graph, null, 100, 1, 2, 1, false, false, null, null, null, false, false, 42, 3)
|
|
496
|
+
|
|
497
|
+
// Circular layout in 3D (creates a sphere)
|
|
498
|
+
const circular3D = circularLayout(graph, 1, [0, 0, 0], 3)
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
When using 3D layouts, positions will have three coordinates `[x, y, z]` instead of two.
|
|
502
|
+
|
|
479
503
|
## Common Parameters
|
|
480
504
|
|
|
481
505
|
Most layout functions share these parameters:
|
|
482
506
|
|
|
483
507
|
- **scale** (number): Scale factor for positions (default: 1)
|
|
484
|
-
- **center** (number[]): Center coordinates around which to center the layout (default: [0, 0])
|
|
508
|
+
- **center** (number[]): Center coordinates around which to center the layout (default: [0, 0] for 2D, [0, 0, 0] for 3D)
|
|
485
509
|
- **dim** (number): Layout dimension - 2D or 3D (default: 2)
|
|
486
510
|
- **seed** (number): Seed for random generation (for reproducible layouts)
|
|
487
511
|
|
|
@@ -722,7 +746,26 @@ const positions = forceatlas2Layout(
|
|
|
722
746
|
true, // dissuadeHubs: good for scale-free
|
|
723
747
|
false, // linlog: logarithmic attraction
|
|
724
748
|
42, // seed
|
|
725
|
-
2 // dim
|
|
749
|
+
2 // dim: 2 for 2D, 3 for 3D
|
|
750
|
+
)
|
|
751
|
+
|
|
752
|
+
// 3D layout example
|
|
753
|
+
const positions3D = forceatlas2Layout(
|
|
754
|
+
graph,
|
|
755
|
+
null,
|
|
756
|
+
100,
|
|
757
|
+
1.0,
|
|
758
|
+
2.0,
|
|
759
|
+
1.0,
|
|
760
|
+
false,
|
|
761
|
+
false,
|
|
762
|
+
null,
|
|
763
|
+
null,
|
|
764
|
+
null,
|
|
765
|
+
false,
|
|
766
|
+
false,
|
|
767
|
+
42,
|
|
768
|
+
3 // 3D mode - returns [x, y, z] coordinates
|
|
726
769
|
)
|
|
727
770
|
```
|
|
728
771
|
|
|
@@ -1098,6 +1141,13 @@ To deploy to GitHub Pages, see `gh-pages/DEPLOY.md` after building.
|
|
|
1098
1141
|
4. **Build for production** with `npm run build:all`
|
|
1099
1142
|
5. **Deploy examples** with `npm run build:gh-pages`
|
|
1100
1143
|
|
|
1144
|
+
## Recent Updates
|
|
1145
|
+
|
|
1146
|
+
### Version 1.2.7 (Latest)
|
|
1147
|
+
- **Fixed**: ForceAtlas2 now correctly returns numeric Z coordinates in 3D mode (previously returned NaN)
|
|
1148
|
+
- **Fixed**: NPM package now uses the correct bundled entry point (`dist/layout.js`)
|
|
1149
|
+
- **Added**: Full 3D support documentation and examples
|
|
1150
|
+
|
|
1101
1151
|
## Contributing
|
|
1102
1152
|
|
|
1103
1153
|
This project is a TypeScript port of the NetworkX Python library. For contributions and issues, visit the [GitHub repository](https://github.com/graphty-org/layout).
|
package/dist/layout.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript declarations for @graphty/layout
|
|
3
|
+
*
|
|
4
|
+
* This file provides type information for the bundled dist/layout.js module.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Re-export all types
|
|
8
|
+
export * from './src/types/index';
|
|
9
|
+
|
|
10
|
+
// Re-export utilities that are part of the public API
|
|
11
|
+
export { rescaleLayout, rescaleLayoutDict } from './src/utils/rescale';
|
|
12
|
+
|
|
13
|
+
// Re-export all layout algorithms
|
|
14
|
+
export * from './src/layouts/index';
|
|
15
|
+
|
|
16
|
+
// Re-export all graph generation functions
|
|
17
|
+
export * from './src/generators/index';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/algorithms/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-export all optimization algorithms
|
|
3
|
+
*/
|
|
4
|
+
export type { DistanceMap } from './types';
|
|
5
|
+
export { _computeShortestPathDistances, _kamadaKawaiSolve, _kamadaKawaiCostfn } from './kamada-kawai-solver';
|
|
6
|
+
export { _lbfgsDirection } from './lbfgs';
|
|
7
|
+
export { _backtrackingLineSearch } from './line-search';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-export all optimization algorithms
|
|
3
|
+
*/
|
|
4
|
+
export { _computeShortestPathDistances, _kamadaKawaiSolve, _kamadaKawaiCostfn } from './kamada-kawai-solver';
|
|
5
|
+
export { _lbfgsDirection } from './lbfgs';
|
|
6
|
+
export { _backtrackingLineSearch } from './line-search';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/algorithms/optimization/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EACL,6BAA6B,EAC7B,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kamada-Kawai layout algorithm optimization functions
|
|
3
|
+
*/
|
|
4
|
+
import { Graph } from '../../types';
|
|
5
|
+
import { DistanceMap } from './types';
|
|
6
|
+
/**
|
|
7
|
+
* Compute all-pairs shortest path distances for the graph
|
|
8
|
+
*
|
|
9
|
+
* @param G - NetworkX graph
|
|
10
|
+
* @param weight - Edge attribute for weight
|
|
11
|
+
* @returns Dictionary of dictionaries of shortest path distances
|
|
12
|
+
*/
|
|
13
|
+
export declare function _computeShortestPathDistances(G: Graph, weight: string): DistanceMap;
|
|
14
|
+
/**
|
|
15
|
+
* Solve the Kamada-Kawai layout optimization problem
|
|
16
|
+
*
|
|
17
|
+
* @param distMatrix - Matrix of desired distances between nodes
|
|
18
|
+
* @param positions - Initial node positions
|
|
19
|
+
* @param dim - Dimension of layout
|
|
20
|
+
* @returns Optimized node positions
|
|
21
|
+
*/
|
|
22
|
+
export declare function _kamadaKawaiSolve(distMatrix: number[][], positions: number[][], dim: number): number[][];
|
|
23
|
+
/**
|
|
24
|
+
* Cost function and gradient for Kamada-Kawai layout algorithm
|
|
25
|
+
*
|
|
26
|
+
* @param posVec - Flattened position array
|
|
27
|
+
* @param invDist - Inverse distance matrix
|
|
28
|
+
* @param meanWeight - Weight for centering positions
|
|
29
|
+
* @param dim - Dimension of layout
|
|
30
|
+
* @returns Array with [cost, gradient]
|
|
31
|
+
*/
|
|
32
|
+
export declare function _kamadaKawaiCostfn(posVec: number[], invDist: number[][], meanWeight: number, dim: number): [number, number[]];
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kamada-Kawai layout algorithm optimization functions
|
|
3
|
+
*/
|
|
4
|
+
import { _lbfgsDirection } from './lbfgs';
|
|
5
|
+
import { _backtrackingLineSearch } from './line-search';
|
|
6
|
+
import { getNodesFromGraph, getEdgesFromGraph } from '../../utils/graph';
|
|
7
|
+
/**
|
|
8
|
+
* Compute all-pairs shortest path distances for the graph
|
|
9
|
+
*
|
|
10
|
+
* @param G - NetworkX graph
|
|
11
|
+
* @param weight - Edge attribute for weight
|
|
12
|
+
* @returns Dictionary of dictionaries of shortest path distances
|
|
13
|
+
*/
|
|
14
|
+
export function _computeShortestPathDistances(G, weight) {
|
|
15
|
+
const distances = {};
|
|
16
|
+
const nodes = getNodesFromGraph(G);
|
|
17
|
+
const edges = getEdgesFromGraph(G);
|
|
18
|
+
// Initialize distances with direct edges
|
|
19
|
+
for (const node of nodes) {
|
|
20
|
+
distances[node] = {};
|
|
21
|
+
distances[node][node] = 0;
|
|
22
|
+
for (const other of nodes) {
|
|
23
|
+
if (node !== other) {
|
|
24
|
+
distances[node][other] = Infinity;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// Add direct edges
|
|
29
|
+
for (const [source, target] of edges) {
|
|
30
|
+
// In a real implementation, we would get the weight from the graph
|
|
31
|
+
// For now, assume weight = 1 or use weight attribute if available
|
|
32
|
+
let edgeWeight = 1;
|
|
33
|
+
if (G.getEdgeData) {
|
|
34
|
+
edgeWeight = G.getEdgeData(source, target, weight) || 1;
|
|
35
|
+
}
|
|
36
|
+
distances[source][target] = edgeWeight;
|
|
37
|
+
distances[target][source] = edgeWeight; // Assuming undirected graph
|
|
38
|
+
}
|
|
39
|
+
// Floyd-Warshall algorithm for all-pairs shortest paths
|
|
40
|
+
for (const k of nodes) {
|
|
41
|
+
for (const i of nodes) {
|
|
42
|
+
for (const j of nodes) {
|
|
43
|
+
if (distances[i][k] + distances[k][j] < distances[i][j]) {
|
|
44
|
+
distances[i][j] = distances[i][k] + distances[k][j];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return distances;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Solve the Kamada-Kawai layout optimization problem
|
|
53
|
+
*
|
|
54
|
+
* @param distMatrix - Matrix of desired distances between nodes
|
|
55
|
+
* @param positions - Initial node positions
|
|
56
|
+
* @param dim - Dimension of layout
|
|
57
|
+
* @returns Optimized node positions
|
|
58
|
+
*/
|
|
59
|
+
export function _kamadaKawaiSolve(distMatrix, positions, dim) {
|
|
60
|
+
// Implementation of L-BFGS optimization for Kamada-Kawai
|
|
61
|
+
const nNodes = positions.length;
|
|
62
|
+
const meanWeight = 1e-3;
|
|
63
|
+
// Convert distances to inverse distances (with protection against division by zero)
|
|
64
|
+
const invDistMatrix = distMatrix.map(row => row.map(d => d === 0 ? 0 : 1 / (d + 1e-3)));
|
|
65
|
+
// Flatten positions for optimization
|
|
66
|
+
let posVec = positions.flat();
|
|
67
|
+
// Optimization parameters
|
|
68
|
+
const maxIter = 500;
|
|
69
|
+
const gtol = 1e-5;
|
|
70
|
+
const m = 10; // L-BFGS memory size
|
|
71
|
+
// Implement a simplified L-BFGS-B algorithm
|
|
72
|
+
let alpha = 1.0;
|
|
73
|
+
const oldValues = [];
|
|
74
|
+
const oldGrads = [];
|
|
75
|
+
for (let iter = 0; iter < maxIter; iter++) {
|
|
76
|
+
// Calculate cost and gradient
|
|
77
|
+
const [cost, grad] = _kamadaKawaiCostfn(posVec, invDistMatrix, meanWeight, dim);
|
|
78
|
+
// Compute search direction using L-BFGS approximation
|
|
79
|
+
const direction = _lbfgsDirection(grad, oldValues, oldGrads, m);
|
|
80
|
+
// Simple line search for step size
|
|
81
|
+
alpha = _backtrackingLineSearch(posVec, direction, cost, grad, (x) => _kamadaKawaiCostfn(x, invDistMatrix, meanWeight, dim)[0], alpha);
|
|
82
|
+
// Save current position and gradient for next iteration
|
|
83
|
+
const oldPos = [...posVec];
|
|
84
|
+
// Update position
|
|
85
|
+
for (let i = 0; i < posVec.length; i++) {
|
|
86
|
+
posVec[i] += alpha * direction[i];
|
|
87
|
+
}
|
|
88
|
+
// Calculate new gradient
|
|
89
|
+
const [, newGrad] = _kamadaKawaiCostfn(posVec, invDistMatrix, meanWeight, dim);
|
|
90
|
+
// Update L-BFGS memory
|
|
91
|
+
oldValues.push(posVec.map((val, i) => val - oldPos[i]));
|
|
92
|
+
oldGrads.push(newGrad.map((val, i) => val - grad[i]));
|
|
93
|
+
// Keep only m most recent updates
|
|
94
|
+
if (oldValues.length > m) {
|
|
95
|
+
oldValues.shift();
|
|
96
|
+
oldGrads.shift();
|
|
97
|
+
}
|
|
98
|
+
// Check convergence
|
|
99
|
+
const gradNorm = Math.sqrt(newGrad.reduce((sum, g) => sum + g * g, 0));
|
|
100
|
+
if (gradNorm < gtol) {
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// Reshape result back into positions array
|
|
105
|
+
const result = [];
|
|
106
|
+
for (let i = 0; i < nNodes; i++) {
|
|
107
|
+
result.push(posVec.slice(i * dim, (i + 1) * dim));
|
|
108
|
+
}
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Cost function and gradient for Kamada-Kawai layout algorithm
|
|
113
|
+
*
|
|
114
|
+
* @param posVec - Flattened position array
|
|
115
|
+
* @param invDist - Inverse distance matrix
|
|
116
|
+
* @param meanWeight - Weight for centering positions
|
|
117
|
+
* @param dim - Dimension of layout
|
|
118
|
+
* @returns Array with [cost, gradient]
|
|
119
|
+
*/
|
|
120
|
+
export function _kamadaKawaiCostfn(posVec, invDist, meanWeight, dim) {
|
|
121
|
+
const nNodes = invDist.length;
|
|
122
|
+
const positions = [];
|
|
123
|
+
// Reshape flat vector into positions array
|
|
124
|
+
for (let i = 0; i < nNodes; i++) {
|
|
125
|
+
positions.push(posVec.slice(i * dim, (i + 1) * dim));
|
|
126
|
+
}
|
|
127
|
+
// Calculate cost
|
|
128
|
+
let cost = 0;
|
|
129
|
+
// Add mean position penalty term
|
|
130
|
+
const sumPos = Array(dim).fill(0);
|
|
131
|
+
for (let i = 0; i < nNodes; i++) {
|
|
132
|
+
for (let d = 0; d < dim; d++) {
|
|
133
|
+
sumPos[d] += positions[i][d];
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
cost += 0.5 * meanWeight * sumPos.reduce((sum, val) => sum + val * val, 0);
|
|
137
|
+
// Add distance penalty terms
|
|
138
|
+
for (let i = 0; i < nNodes; i++) {
|
|
139
|
+
for (let j = i + 1; j < nNodes; j++) {
|
|
140
|
+
// Calculate actual distance
|
|
141
|
+
const diff = positions[i].map((val, d) => val - positions[j][d]);
|
|
142
|
+
const distance = Math.sqrt(diff.reduce((sum, d) => sum + d * d, 0));
|
|
143
|
+
// Add penalty for difference between actual and ideal distance
|
|
144
|
+
const idealInvDist = invDist[i][j];
|
|
145
|
+
const offset = distance * idealInvDist - 1.0;
|
|
146
|
+
cost += 0.5 * offset * offset;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// Calculate gradient
|
|
150
|
+
const grad = new Array(posVec.length).fill(0);
|
|
151
|
+
// Add gradient of mean position penalty
|
|
152
|
+
for (let i = 0; i < nNodes; i++) {
|
|
153
|
+
for (let d = 0; d < dim; d++) {
|
|
154
|
+
grad[i * dim + d] += meanWeight * sumPos[d];
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Add gradient of distance penalties
|
|
158
|
+
for (let i = 0; i < nNodes; i++) {
|
|
159
|
+
for (let j = i + 1; j < nNodes; j++) {
|
|
160
|
+
// Calculate actual distance and direction
|
|
161
|
+
const diff = positions[i].map((val, d) => val - positions[j][d]);
|
|
162
|
+
const distance = Math.sqrt(diff.reduce((sum, d) => sum + d * d, 0)) || 1e-10;
|
|
163
|
+
const direction = diff.map(d => d / distance);
|
|
164
|
+
// Calculate contribution to gradient
|
|
165
|
+
const idealInvDist = invDist[i][j];
|
|
166
|
+
const offset = distance * idealInvDist - 1.0;
|
|
167
|
+
for (let d = 0; d < dim; d++) {
|
|
168
|
+
const force = idealInvDist * offset * direction[d];
|
|
169
|
+
grad[i * dim + d] += force;
|
|
170
|
+
grad[j * dim + d] -= force;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return [cost, grad];
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=kamada-kawai-solver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kamada-kawai-solver.js","sourceRoot":"","sources":["../../../../src/algorithms/optimization/kamada-kawai-solver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L-BFGS optimization utilities
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Compute the search direction using L-BFGS approximation
|
|
6
|
+
*
|
|
7
|
+
* @param grad - Current gradient
|
|
8
|
+
* @param sList - List of position differences (s_k)
|
|
9
|
+
* @param yList - List of gradient differences (y_k)
|
|
10
|
+
* @param m - Memory size
|
|
11
|
+
* @returns Direction vector
|
|
12
|
+
*/
|
|
13
|
+
export declare function _lbfgsDirection(grad: number[], sList: number[][], yList: number[][], m: number): number[];
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L-BFGS optimization utilities
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Compute the search direction using L-BFGS approximation
|
|
6
|
+
*
|
|
7
|
+
* @param grad - Current gradient
|
|
8
|
+
* @param sList - List of position differences (s_k)
|
|
9
|
+
* @param yList - List of gradient differences (y_k)
|
|
10
|
+
* @param m - Memory size
|
|
11
|
+
* @returns Direction vector
|
|
12
|
+
*/
|
|
13
|
+
export function _lbfgsDirection(grad, sList, yList, m) {
|
|
14
|
+
if (sList.length === 0) {
|
|
15
|
+
// First iteration - use negative gradient
|
|
16
|
+
return grad.map(g => -g);
|
|
17
|
+
}
|
|
18
|
+
const q = grad.slice();
|
|
19
|
+
const alpha = Array(sList.length).fill(0);
|
|
20
|
+
const rho = [];
|
|
21
|
+
// Compute rho values
|
|
22
|
+
for (let i = 0; i < sList.length; i++) {
|
|
23
|
+
const s = sList[i];
|
|
24
|
+
const y = yList[i];
|
|
25
|
+
rho.push(1 / y.reduce((sum, val, j) => sum + val * s[j], 0));
|
|
26
|
+
}
|
|
27
|
+
// Forward pass
|
|
28
|
+
for (let i = sList.length - 1; i >= 0; i--) {
|
|
29
|
+
const s = sList[i];
|
|
30
|
+
alpha[i] = rho[i] * s.reduce((sum, val, j) => sum + val * q[j], 0);
|
|
31
|
+
for (let j = 0; j < q.length; j++) {
|
|
32
|
+
q[j] -= alpha[i] * yList[i][j];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// Scale initial Hessian approximation
|
|
36
|
+
let gamma = 1;
|
|
37
|
+
if (sList.length > 0 && yList.length > 0) {
|
|
38
|
+
const y = yList[yList.length - 1];
|
|
39
|
+
const s = sList[sList.length - 1];
|
|
40
|
+
gamma = s.reduce((sum, val, i) => sum + val * y[i], 0) /
|
|
41
|
+
y.reduce((sum, val) => sum + val * val, 0);
|
|
42
|
+
}
|
|
43
|
+
// Initialize direction with scaled negative gradient
|
|
44
|
+
const direction = q.map(val => -gamma * val);
|
|
45
|
+
// Backward pass
|
|
46
|
+
for (let i = 0; i < sList.length; i++) {
|
|
47
|
+
const s = sList[i];
|
|
48
|
+
const y = yList[i];
|
|
49
|
+
const beta = rho[i] * y.reduce((sum, val, j) => sum + val * direction[j], 0);
|
|
50
|
+
for (let j = 0; j < direction.length; j++) {
|
|
51
|
+
direction[j] += s[j] * (alpha[i] - beta);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return direction;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=lbfgs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lbfgs.js","sourceRoot":"","sources":["../../../../src/algorithms/optimization/lbfgs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Line search optimization utilities
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Backtracking line search to find step size
|
|
6
|
+
*
|
|
7
|
+
* @param x - Current position
|
|
8
|
+
* @param direction - Search direction
|
|
9
|
+
* @param f - Function value at current position
|
|
10
|
+
* @param grad - Gradient at current position
|
|
11
|
+
* @param func - Function to evaluate cost
|
|
12
|
+
* @param alpha0 - Initial step size
|
|
13
|
+
* @returns Optimal step size
|
|
14
|
+
*/
|
|
15
|
+
export declare function _backtrackingLineSearch(x: number[], direction: number[], f: number, grad: number[], func: (x: number[]) => number, alpha0: number): number;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Line search optimization utilities
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Backtracking line search to find step size
|
|
6
|
+
*
|
|
7
|
+
* @param x - Current position
|
|
8
|
+
* @param direction - Search direction
|
|
9
|
+
* @param f - Function value at current position
|
|
10
|
+
* @param grad - Gradient at current position
|
|
11
|
+
* @param func - Function to evaluate cost
|
|
12
|
+
* @param alpha0 - Initial step size
|
|
13
|
+
* @returns Optimal step size
|
|
14
|
+
*/
|
|
15
|
+
export function _backtrackingLineSearch(x, direction, f, grad, func, alpha0) {
|
|
16
|
+
const c1 = 1e-4;
|
|
17
|
+
const c2 = 0.9;
|
|
18
|
+
const initialSlope = grad.reduce((sum, g, i) => sum + g * direction[i], 0);
|
|
19
|
+
if (initialSlope >= 0) {
|
|
20
|
+
return 1e-8; // Direction is not a descent direction
|
|
21
|
+
}
|
|
22
|
+
let alpha = alpha0;
|
|
23
|
+
const maxIter = 20;
|
|
24
|
+
for (let i = 0; i < maxIter; i++) {
|
|
25
|
+
// Try step
|
|
26
|
+
const newX = x.map((val, i) => val + alpha * direction[i]);
|
|
27
|
+
const newF = func(newX);
|
|
28
|
+
// Check sufficient decrease condition (Armijo condition)
|
|
29
|
+
if (newF <= f + c1 * alpha * initialSlope) {
|
|
30
|
+
return alpha;
|
|
31
|
+
}
|
|
32
|
+
// Reduce step size
|
|
33
|
+
alpha *= c2;
|
|
34
|
+
}
|
|
35
|
+
return alpha; // Return last alpha even if not optimal
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=line-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"line-search.js","sourceRoot":"","sources":["../../../../src/algorithms/optimization/line-search.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;;GAUG;AACH,MAAM,UAAU,uBAAuB,CACrC,CAAW,EACX,SAAmB,EACnB,CAAS,EACT,IAAc,EACd,IAA6B,EAC7B,MAAc;IAEd,MAAM,EAAE,GAAG,IAAI,CAAC;IAChB,MAAM,EAAE,GAAG,GAAG,CAAC;IACf,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAE3E,IAAI,YAAY,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC,CAAE,uCAAuC;IACvD,CAAC;IAED,IAAI,KAAK,GAAG,MAAM,CAAC;IACnB,MAAM,OAAO,GAAG,EAAE,CAAC;IAEnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC;QACjC,WAAW;QACX,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;QAExB,yDAAyD;QACzD,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,YAAY,EAAE,CAAC;YAC1C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,mBAAmB;QACnB,KAAK,IAAI,EAAE,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC,CAAE,wCAAwC;AACzD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/algorithms/optimization/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main planarity checking function
|
|
3
|
+
*/
|
|
4
|
+
import { Graph, Node, Edge, Embedding } from '../../types';
|
|
5
|
+
/**
|
|
6
|
+
* Check if graph is planar using a simplified version of Boyer-Myrvold algorithm.
|
|
7
|
+
* Returns planarity and embedding information.
|
|
8
|
+
*
|
|
9
|
+
* @param G - Graph
|
|
10
|
+
* @param nodes - List of nodes
|
|
11
|
+
* @param edges - List of edges
|
|
12
|
+
* @returns Object containing isPlanar flag and embedding
|
|
13
|
+
*/
|
|
14
|
+
export declare function checkPlanarity(G: Graph, nodes: Node[], edges: Edge[]): {
|
|
15
|
+
isPlanar: boolean;
|
|
16
|
+
embedding: Embedding | null;
|
|
17
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main planarity checking function
|
|
3
|
+
*/
|
|
4
|
+
import { isK5, isK33 } from './special-graphs';
|
|
5
|
+
import { lrPlanarityTest } from './lr-test';
|
|
6
|
+
import { createTriangulationEmbedding } from './embedding';
|
|
7
|
+
/**
|
|
8
|
+
* Check if graph is planar using a simplified version of Boyer-Myrvold algorithm.
|
|
9
|
+
* Returns planarity and embedding information.
|
|
10
|
+
*
|
|
11
|
+
* @param G - Graph
|
|
12
|
+
* @param nodes - List of nodes
|
|
13
|
+
* @param edges - List of edges
|
|
14
|
+
* @returns Object containing isPlanar flag and embedding
|
|
15
|
+
*/
|
|
16
|
+
export function checkPlanarity(G, nodes, edges) {
|
|
17
|
+
// For small graphs (n <= 4), all are planar
|
|
18
|
+
if (nodes.length <= 4) {
|
|
19
|
+
return { isPlanar: true, embedding: createTriangulationEmbedding(nodes, edges) };
|
|
20
|
+
}
|
|
21
|
+
// For K5 (complete graph with 5 nodes) and K3,3 (complete bipartite with 3,3 nodes)
|
|
22
|
+
// these are not planar by Kuratowski's theorem
|
|
23
|
+
if (isK5(nodes, edges) || isK33(nodes, edges)) {
|
|
24
|
+
return { isPlanar: false, embedding: null };
|
|
25
|
+
}
|
|
26
|
+
// For other graphs, use LR algorithm (Left-Right Planarity Test)
|
|
27
|
+
const result = lrPlanarityTest(nodes, edges);
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../../../src/algorithms/planarity/check.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAE3D;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAC5B,CAAQ,EACR,KAAa,EACb,KAAa;IAEb,4CAA4C;IAC5C,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,4BAA4B,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;IACnF,CAAC;IAED,oFAAoF;IACpF,+CAA+C;IAC/C,IAAI,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;QAC9C,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAC9C,CAAC;IAED,iEAAiE;IACjE,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC7C,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedding functions for planar graphs
|
|
3
|
+
*/
|
|
4
|
+
import { Node, Edge, Embedding, PositionMap } from '../../types';
|
|
5
|
+
/**
|
|
6
|
+
* Create a triangulation-based embedding for a planar graph
|
|
7
|
+
*
|
|
8
|
+
* @param nodes - List of nodes
|
|
9
|
+
* @param edges - List of edges
|
|
10
|
+
* @returns Embedding object
|
|
11
|
+
*/
|
|
12
|
+
export declare function createTriangulationEmbedding(nodes: Node[], edges: Edge[]): Embedding;
|
|
13
|
+
/**
|
|
14
|
+
* Find a simple cycle in the graph (for outer face)
|
|
15
|
+
*
|
|
16
|
+
* @param nodes - List of nodes
|
|
17
|
+
* @param edges - List of edges
|
|
18
|
+
* @param adjMap - Adjacency map
|
|
19
|
+
* @returns Cycle as array of nodes, or null if none found
|
|
20
|
+
*/
|
|
21
|
+
export declare function findCycle(nodes: Node[], edges: Edge[], adjMap: Record<Node, Set<Node>>): Node[] | null;
|
|
22
|
+
/**
|
|
23
|
+
* Convert a combinatorial embedding to node positions
|
|
24
|
+
*
|
|
25
|
+
* @param embedding - The embedding object
|
|
26
|
+
* @param nodes - List of nodes
|
|
27
|
+
* @returns Dictionary mapping nodes to positions
|
|
28
|
+
*/
|
|
29
|
+
export declare function combinatorialEmbeddingToPos(embedding: Embedding, nodes: Node[]): PositionMap;
|