graphwise 1.2.0 → 1.3.1
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 +152 -2
- package/dist/index/index.cjs +65 -117
- package/dist/index/index.cjs.map +1 -1
- package/dist/index/index.js +61 -118
- package/dist/index/index.js.map +1 -1
- package/dist/ranking/mi/adamic-adar.d.ts.map +1 -1
- package/dist/ranking/mi/adaptive.d.ts +1 -1
- package/dist/ranking/mi/adaptive.d.ts.map +1 -1
- package/dist/ranking/mi/etch.d.ts.map +1 -1
- package/dist/ranking/mi/jaccard.d.ts.map +1 -1
- package/dist/ranking/mi/notch.d.ts.map +1 -1
- package/dist/ranking/mi/scale.d.ts.map +1 -1
- package/dist/ranking/mi/skew.d.ts.map +1 -1
- package/dist/ranking/mi/span.d.ts.map +1 -1
- package/dist/utils/index.cjs +82 -0
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +78 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/neighbours.d.ts +54 -0
- package/dist/utils/neighbours.d.ts.map +1 -0
- package/dist/utils/neighbours.unit.test.d.ts +5 -0
- package/dist/utils/neighbours.unit.test.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index/index.js
CHANGED
|
@@ -2,8 +2,8 @@ import { AdjacencyMapGraph } from "../graph/index.js";
|
|
|
2
2
|
import { bfs, bfsWithPath, dfs, dfsWithPath } from "../traversal/index.js";
|
|
3
3
|
import { PriorityQueue } from "../structures/index.js";
|
|
4
4
|
import { n as miniBatchKMeans, r as normaliseFeatures, t as _computeMean } from "../kmeans-87ExSUNZ.js";
|
|
5
|
+
import { approximateClusteringCoefficient, batchClusteringCoefficients, countEdgesOfType, countNodesOfType, entropyFromCounts, localClusteringCoefficient, localTypeEntropy, neighbourIntersection, neighbourOverlap, neighbourSet, normalisedEntropy, shannonEntropy } from "../utils/index.js";
|
|
5
6
|
import { grasp, stratified } from "../seeds/index.js";
|
|
6
|
-
import { approximateClusteringCoefficient, batchClusteringCoefficients, entropyFromCounts, localClusteringCoefficient, localTypeEntropy, normalisedEntropy, shannonEntropy } from "../utils/index.js";
|
|
7
7
|
import { GPUContext, GPUNotAvailableError, assertWebGPUAvailable, createGPUContext, createResultBuffer, csrToGPUBuffers, detectWebGPU, getGPUContext, graphToCSR, isWebGPUAvailable, readBufferToCPU } from "../gpu/index.js";
|
|
8
8
|
//#region src/expansion/base.ts
|
|
9
9
|
/**
|
|
@@ -298,15 +298,9 @@ function edge(graph, seeds, config) {
|
|
|
298
298
|
*/
|
|
299
299
|
function jaccard(graph, source, target, config) {
|
|
300
300
|
const { epsilon = 1e-10 } = config ?? {};
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
targetNeighbours.delete(source);
|
|
305
|
-
let intersectionSize = 0;
|
|
306
|
-
for (const neighbour of sourceNeighbours) if (targetNeighbours.has(neighbour)) intersectionSize++;
|
|
307
|
-
const unionSize = sourceNeighbours.size + targetNeighbours.size - intersectionSize;
|
|
308
|
-
if (unionSize === 0) return 0;
|
|
309
|
-
const score = intersectionSize / unionSize;
|
|
301
|
+
const { intersection, union } = neighbourOverlap(neighbourSet(graph, source, target), neighbourSet(graph, target, source));
|
|
302
|
+
if (union === 0) return 0;
|
|
303
|
+
const score = intersection / union;
|
|
310
304
|
return Math.max(epsilon, score);
|
|
311
305
|
}
|
|
312
306
|
//#endregion
|
|
@@ -686,19 +680,14 @@ function computePathSalience(graph, path, mi, epsilon) {
|
|
|
686
680
|
*/
|
|
687
681
|
function adamicAdar(graph, source, target, config) {
|
|
688
682
|
const { epsilon = 1e-10, normalise = true } = config ?? {};
|
|
689
|
-
const
|
|
690
|
-
const targetNeighbours = new Set(graph.neighbours(target));
|
|
691
|
-
sourceNeighbours.delete(target);
|
|
692
|
-
targetNeighbours.delete(source);
|
|
683
|
+
const commonNeighbours = neighbourIntersection(neighbourSet(graph, source, target), neighbourSet(graph, target, source));
|
|
693
684
|
let score = 0;
|
|
694
|
-
for (const neighbour of
|
|
685
|
+
for (const neighbour of commonNeighbours) {
|
|
695
686
|
const degree = graph.degree(neighbour);
|
|
696
|
-
|
|
687
|
+
score += 1 / Math.log(degree + 1);
|
|
697
688
|
}
|
|
698
|
-
if (normalise) {
|
|
699
|
-
const
|
|
700
|
-
if (commonCount === 0) return 0;
|
|
701
|
-
const maxScore = commonCount / Math.log(2);
|
|
689
|
+
if (normalise && commonNeighbours.size > 0) {
|
|
690
|
+
const maxScore = commonNeighbours.size / Math.log(2);
|
|
702
691
|
score = score / maxScore;
|
|
703
692
|
}
|
|
704
693
|
return Math.max(epsilon, score);
|
|
@@ -710,22 +699,15 @@ function adamicAdar(graph, source, target, config) {
|
|
|
710
699
|
*/
|
|
711
700
|
function scale(graph, source, target, config) {
|
|
712
701
|
const { epsilon = 1e-10 } = config ?? {};
|
|
713
|
-
const
|
|
714
|
-
const
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
const
|
|
718
|
-
const
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
const jaccard = unionSize > 0 ? intersectionSize / unionSize : 0;
|
|
723
|
-
const minDegree = Math.min(sourceDegree, targetDegree);
|
|
724
|
-
const maxDegree = Math.max(sourceDegree, targetDegree);
|
|
725
|
-
const degreeRatio = maxDegree > 0 ? minDegree / maxDegree : 0;
|
|
726
|
-
if (jaccard + degreeRatio === 0) return epsilon;
|
|
727
|
-
const score = 2 * jaccard * degreeRatio / (jaccard + degreeRatio);
|
|
728
|
-
return Math.max(epsilon, Math.min(1, score));
|
|
702
|
+
const { intersection, union } = neighbourOverlap(neighbourSet(graph, source, target), neighbourSet(graph, target, source));
|
|
703
|
+
const jaccard = union > 0 ? intersection / union : 0;
|
|
704
|
+
const n = graph.nodeCount;
|
|
705
|
+
const m = graph.edgeCount;
|
|
706
|
+
const densityNormaliser = graph.directed ? n * (n - 1) : 2 * n * (n - 1);
|
|
707
|
+
const density = densityNormaliser > 0 ? m / densityNormaliser : 0;
|
|
708
|
+
if (density === 0) return epsilon;
|
|
709
|
+
const score = jaccard / density;
|
|
710
|
+
return Math.max(epsilon, score);
|
|
729
711
|
}
|
|
730
712
|
//#endregion
|
|
731
713
|
//#region src/ranking/mi/skew.ts
|
|
@@ -734,23 +716,15 @@ function scale(graph, source, target, config) {
|
|
|
734
716
|
*/
|
|
735
717
|
function skew(graph, source, target, config) {
|
|
736
718
|
const { epsilon = 1e-10 } = config ?? {};
|
|
737
|
-
const
|
|
738
|
-
const
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
if (degree > 1) weightedIntersection += 1 / Math.log(degree);
|
|
747
|
-
}
|
|
748
|
-
if (commonCount === 0) return epsilon;
|
|
749
|
-
const sourceDegree = sourceNeighbours.size;
|
|
750
|
-
const targetDegree = targetNeighbours.size;
|
|
751
|
-
const maxScore = Math.min(sourceDegree, targetDegree) / Math.log(2);
|
|
752
|
-
const score = weightedIntersection / maxScore;
|
|
753
|
-
return Math.max(epsilon, Math.min(1, score));
|
|
719
|
+
const { intersection, union } = neighbourOverlap(neighbourSet(graph, source, target), neighbourSet(graph, target, source));
|
|
720
|
+
const jaccard = union > 0 ? intersection / union : 0;
|
|
721
|
+
const N = graph.nodeCount;
|
|
722
|
+
const sourceDegree = graph.degree(source);
|
|
723
|
+
const targetDegree = graph.degree(target);
|
|
724
|
+
const sourceIdf = Math.log(N / (sourceDegree + 1));
|
|
725
|
+
const targetIdf = Math.log(N / (targetDegree + 1));
|
|
726
|
+
const score = jaccard * sourceIdf * targetIdf;
|
|
727
|
+
return Math.max(epsilon, score);
|
|
754
728
|
}
|
|
755
729
|
//#endregion
|
|
756
730
|
//#region src/ranking/mi/span.ts
|
|
@@ -759,21 +733,12 @@ function skew(graph, source, target, config) {
|
|
|
759
733
|
*/
|
|
760
734
|
function span(graph, source, target, config) {
|
|
761
735
|
const { epsilon = 1e-10 } = config ?? {};
|
|
762
|
-
const
|
|
763
|
-
const
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
const
|
|
767
|
-
|
|
768
|
-
let intersectionSize = 0;
|
|
769
|
-
for (const neighbour of sourceNeighbours) if (targetNeighbours.has(neighbour)) intersectionSize++;
|
|
770
|
-
const unionSize = sourceDegree + targetDegree - intersectionSize;
|
|
771
|
-
const jaccard = unionSize > 0 ? intersectionSize / unionSize : 0;
|
|
772
|
-
const maxDegree = Math.max(sourceDegree, targetDegree);
|
|
773
|
-
const degreeDiff = Math.abs(sourceDegree - targetDegree);
|
|
774
|
-
const degreeSimilarity = maxDegree > 0 ? 1 - degreeDiff / maxDegree : 1;
|
|
775
|
-
const score = Math.sqrt(jaccard * degreeSimilarity);
|
|
776
|
-
return Math.max(epsilon, Math.min(1, score));
|
|
736
|
+
const { intersection, union } = neighbourOverlap(neighbourSet(graph, source, target), neighbourSet(graph, target, source));
|
|
737
|
+
const jaccard = union > 0 ? intersection / union : 0;
|
|
738
|
+
const sourceCc = localClusteringCoefficient(graph, source);
|
|
739
|
+
const targetCc = localClusteringCoefficient(graph, target);
|
|
740
|
+
const score = jaccard * (1 - Math.max(sourceCc, targetCc));
|
|
741
|
+
return Math.max(epsilon, score);
|
|
777
742
|
}
|
|
778
743
|
//#endregion
|
|
779
744
|
//#region src/ranking/mi/etch.ts
|
|
@@ -782,30 +747,14 @@ function span(graph, source, target, config) {
|
|
|
782
747
|
*/
|
|
783
748
|
function etch(graph, source, target, config) {
|
|
784
749
|
const { epsilon = 1e-10 } = config ?? {};
|
|
785
|
-
const
|
|
786
|
-
const
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
const
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
for (let i = 0; i < commonNeighbours.length; i++) for (let j = i + 1; j < commonNeighbours.length; j++) {
|
|
794
|
-
const ni = commonNeighbours[i];
|
|
795
|
-
const nj = commonNeighbours[j];
|
|
796
|
-
if (ni !== void 0 && nj !== void 0 && graph.getEdge(ni, nj) !== void 0) jointEdges++;
|
|
797
|
-
}
|
|
798
|
-
const maxJointEdges = commonNeighbours.length * (commonNeighbours.length - 1) / 2;
|
|
799
|
-
const jointDensity = maxJointEdges > 0 ? jointEdges / maxJointEdges : 0;
|
|
800
|
-
let commonEdges = 0;
|
|
801
|
-
for (const cn of commonNeighbours) {
|
|
802
|
-
if (graph.getEdge(source, cn) !== void 0) commonEdges++;
|
|
803
|
-
if (graph.getEdge(target, cn) !== void 0) commonEdges++;
|
|
804
|
-
}
|
|
805
|
-
const maxCommonEdges = commonNeighbours.length * 2;
|
|
806
|
-
const commonDensity = maxCommonEdges > 0 ? commonEdges / maxCommonEdges : 0;
|
|
807
|
-
const score = jointDensity * .7 + commonDensity * .3;
|
|
808
|
-
return Math.max(epsilon, Math.min(1, score));
|
|
750
|
+
const { intersection, union } = neighbourOverlap(neighbourSet(graph, source, target), neighbourSet(graph, target, source));
|
|
751
|
+
const jaccard = union > 0 ? intersection / union : 0;
|
|
752
|
+
const edge = graph.getEdge(source, target);
|
|
753
|
+
if (edge?.type === void 0) return Math.max(epsilon, jaccard);
|
|
754
|
+
const edgeTypeCount = countEdgesOfType(graph, edge.type);
|
|
755
|
+
if (edgeTypeCount === 0) return Math.max(epsilon, jaccard);
|
|
756
|
+
const score = jaccard * Math.log(graph.edgeCount / edgeTypeCount);
|
|
757
|
+
return Math.max(epsilon, score);
|
|
809
758
|
}
|
|
810
759
|
//#endregion
|
|
811
760
|
//#region src/ranking/mi/notch.ts
|
|
@@ -814,20 +763,18 @@ function etch(graph, source, target, config) {
|
|
|
814
763
|
*/
|
|
815
764
|
function notch(graph, source, target, config) {
|
|
816
765
|
const { epsilon = 1e-10 } = config ?? {};
|
|
817
|
-
const
|
|
818
|
-
const
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
const
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
const
|
|
826
|
-
const
|
|
827
|
-
const
|
|
828
|
-
|
|
829
|
-
const score = overlap * .6 + correlation * .4;
|
|
830
|
-
return Math.max(epsilon, Math.min(1, score));
|
|
766
|
+
const { intersection, union } = neighbourOverlap(neighbourSet(graph, source, target), neighbourSet(graph, target, source));
|
|
767
|
+
const jaccard = union > 0 ? intersection / union : 0;
|
|
768
|
+
const sourceNode = graph.getNode(source);
|
|
769
|
+
const targetNode = graph.getNode(target);
|
|
770
|
+
if (sourceNode?.type === void 0 || targetNode?.type === void 0) return Math.max(epsilon, jaccard);
|
|
771
|
+
const sourceTypeCount = countNodesOfType(graph, sourceNode.type);
|
|
772
|
+
const targetTypeCount = countNodesOfType(graph, targetNode.type);
|
|
773
|
+
if (sourceTypeCount === 0 || targetTypeCount === 0) return Math.max(epsilon, jaccard);
|
|
774
|
+
const sourceRarity = Math.log(graph.nodeCount / sourceTypeCount);
|
|
775
|
+
const targetRarity = Math.log(graph.nodeCount / targetTypeCount);
|
|
776
|
+
const score = jaccard * sourceRarity * targetRarity;
|
|
777
|
+
return Math.max(epsilon, score);
|
|
831
778
|
}
|
|
832
779
|
//#endregion
|
|
833
780
|
//#region src/ranking/mi/adaptive.ts
|
|
@@ -835,7 +782,7 @@ function notch(graph, source, target, config) {
|
|
|
835
782
|
* Compute unified adaptive MI between two connected nodes.
|
|
836
783
|
*
|
|
837
784
|
* Combines structural, degree, and overlap signals with
|
|
838
|
-
*
|
|
785
|
+
* configurable weighting.
|
|
839
786
|
*
|
|
840
787
|
* @param graph - Source graph
|
|
841
788
|
* @param source - Source node ID
|
|
@@ -850,17 +797,13 @@ function adaptive(graph, source, target, config) {
|
|
|
850
797
|
epsilon,
|
|
851
798
|
normalise: true
|
|
852
799
|
});
|
|
853
|
-
const sourceNeighbours =
|
|
854
|
-
const targetNeighbours =
|
|
855
|
-
sourceNeighbours.delete(target);
|
|
856
|
-
targetNeighbours.delete(source);
|
|
857
|
-
const sourceDegree = sourceNeighbours.size;
|
|
858
|
-
const targetDegree = targetNeighbours.size;
|
|
800
|
+
const sourceNeighbours = neighbourSet(graph, source, target);
|
|
801
|
+
const targetNeighbours = neighbourSet(graph, target, source);
|
|
859
802
|
let overlap;
|
|
860
|
-
if (
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
overlap =
|
|
803
|
+
if (sourceNeighbours.size > 0 && targetNeighbours.size > 0) {
|
|
804
|
+
const { intersection } = neighbourOverlap(sourceNeighbours, targetNeighbours);
|
|
805
|
+
const minDegree = Math.min(sourceNeighbours.size, targetNeighbours.size);
|
|
806
|
+
overlap = minDegree > 0 ? intersection / minDegree : epsilon;
|
|
864
807
|
} else overlap = epsilon;
|
|
865
808
|
const totalWeight = structuralWeight + degreeWeight + overlapWeight;
|
|
866
809
|
const score = (structuralWeight * structural + degreeWeight * degreeComponent + overlapWeight * overlap) / totalWeight;
|
|
@@ -2221,6 +2164,6 @@ function filterSubgraph(graph, options) {
|
|
|
2221
2164
|
return result;
|
|
2222
2165
|
}
|
|
2223
2166
|
//#endregion
|
|
2224
|
-
export { AdjacencyMapGraph, GPUContext, GPUNotAvailableError, PriorityQueue, _computeMean, adamicAdar, adaptive, approximateClusteringCoefficient, assertWebGPUAvailable, base, batchClusteringCoefficients, betweenness, bfs, bfsWithPath, communicability, computeTrussNumbers, createGPUContext, createResultBuffer, csrToGPUBuffers, degreeSum, detectWebGPU, dfs, dfsWithPath, dome, domeHighDegree, edge, entropyFromCounts, enumerateMotifs, enumerateMotifsWithInstances, etch, extractEgoNetwork, extractInducedSubgraph, extractKCore, extractKTruss, filterSubgraph, frontierBalanced, getGPUContext, getMotifName, graphToCSR, grasp, hae, isWebGPUAvailable, jaccard, jaccardArithmetic, katz, localClusteringCoefficient, localTypeEntropy, maze, miniBatchKMeans, normaliseFeatures, normaliseFeatures as zScoreNormalise, normalisedEntropy, notch, pagerank, parse, pipe, randomPriority, randomRanking, reach, readBufferToCPU, resistanceDistance, sage, scale, shannonEntropy, shortest, skew, span, standardBfs, stratified, widestPath };
|
|
2167
|
+
export { AdjacencyMapGraph, GPUContext, GPUNotAvailableError, PriorityQueue, _computeMean, adamicAdar, adaptive, approximateClusteringCoefficient, assertWebGPUAvailable, base, batchClusteringCoefficients, betweenness, bfs, bfsWithPath, communicability, computeTrussNumbers, countEdgesOfType, countNodesOfType, createGPUContext, createResultBuffer, csrToGPUBuffers, degreeSum, detectWebGPU, dfs, dfsWithPath, dome, domeHighDegree, edge, entropyFromCounts, enumerateMotifs, enumerateMotifsWithInstances, etch, extractEgoNetwork, extractInducedSubgraph, extractKCore, extractKTruss, filterSubgraph, frontierBalanced, getGPUContext, getMotifName, graphToCSR, grasp, hae, isWebGPUAvailable, jaccard, jaccardArithmetic, katz, localClusteringCoefficient, localTypeEntropy, maze, miniBatchKMeans, neighbourIntersection, neighbourOverlap, neighbourSet, normaliseFeatures, normaliseFeatures as zScoreNormalise, normalisedEntropy, notch, pagerank, parse, pipe, randomPriority, randomRanking, reach, readBufferToCPU, resistanceDistance, sage, scale, shannonEntropy, shortest, skew, span, standardBfs, stratified, widestPath };
|
|
2225
2168
|
|
|
2226
2169
|
//# sourceMappingURL=index.js.map
|