Add the `attribution/pagerank` module (#455)
This module exposes a method, `pagerank`, which is a convenient entry point for taking a `Graph` and returning a `PagerankResult`. This obviates the need for `src/v1/app/credExplorer/basicPagerank.js`. Test plan: Unit tests included.
This commit is contained in:
parent
5c93085430
commit
fe64377194
|
@ -0,0 +1,59 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`core/attribution/pagerank respects explicit arguments 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"parts": Array [
|
||||
"dst",
|
||||
],
|
||||
"probability": 0.25,
|
||||
},
|
||||
Object {
|
||||
"parts": Array [
|
||||
"isolated",
|
||||
],
|
||||
"probability": 0.25,
|
||||
},
|
||||
Object {
|
||||
"parts": Array [
|
||||
"loop",
|
||||
],
|
||||
"probability": 0.25,
|
||||
},
|
||||
Object {
|
||||
"parts": Array [
|
||||
"src",
|
||||
],
|
||||
"probability": 0.25,
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`core/attribution/pagerank snapshots as expected on the advanced graph 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"parts": Array [
|
||||
"dst",
|
||||
],
|
||||
"probability": 0.4999999999687968,
|
||||
},
|
||||
Object {
|
||||
"parts": Array [
|
||||
"isolated",
|
||||
],
|
||||
"probability": 0.25,
|
||||
},
|
||||
Object {
|
||||
"parts": Array [
|
||||
"loop",
|
||||
],
|
||||
"probability": 0.25,
|
||||
},
|
||||
Object {
|
||||
"parts": Array [
|
||||
"src",
|
||||
],
|
||||
"probability": 3.120317183596679e-11,
|
||||
},
|
||||
]
|
||||
`;
|
|
@ -0,0 +1,49 @@
|
|||
// @flow
|
||||
|
||||
import {type Edge, Graph} from "../graph";
|
||||
import {
|
||||
type PagerankResult,
|
||||
distributionToPagerankResult,
|
||||
graphToOrderedSparseMarkovChain,
|
||||
type EdgeWeight,
|
||||
} from "./graphToMarkovChain";
|
||||
|
||||
import {findStationaryDistribution} from "./markovChain";
|
||||
|
||||
export type PagerankOptions = {|
|
||||
+selfLoopWeight?: number,
|
||||
+verbose?: boolean,
|
||||
+convergenceThreshold?: number,
|
||||
+maxIterations?: number,
|
||||
|};
|
||||
|
||||
function defaultOptions(): PagerankOptions {
|
||||
return {
|
||||
verbose: false,
|
||||
selfLoopWeight: 1e-3,
|
||||
convergenceThreshold: 1e-7,
|
||||
maxIterations: 255,
|
||||
};
|
||||
}
|
||||
|
||||
export function pagerank(
|
||||
graph: Graph,
|
||||
edgeWeight: (Edge) => EdgeWeight,
|
||||
options?: PagerankOptions
|
||||
): PagerankResult {
|
||||
const fullOptions = {
|
||||
...defaultOptions(),
|
||||
...(options || {}),
|
||||
};
|
||||
const osmc = graphToOrderedSparseMarkovChain(
|
||||
graph,
|
||||
edgeWeight,
|
||||
fullOptions.selfLoopWeight
|
||||
);
|
||||
const distribution = findStationaryDistribution(osmc.chain, {
|
||||
verbose: fullOptions.verbose,
|
||||
convergenceThreshold: fullOptions.convergenceThreshold,
|
||||
maxIterations: fullOptions.maxIterations,
|
||||
});
|
||||
return distributionToPagerankResult(osmc.nodeOrder, distribution);
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
// @flow
|
||||
|
||||
import {pagerank} from "./pagerank";
|
||||
import {NodeAddress} from "../graph";
|
||||
import {advancedGraph} from "../graphTestUtil";
|
||||
|
||||
function snapshotPagerankResult(result) {
|
||||
const partsToProbability = [];
|
||||
const sortedKeys = Array.from(result.keys()).sort();
|
||||
for (const key of sortedKeys) {
|
||||
const probability = result.get(key);
|
||||
const parts = NodeAddress.toParts((key: any));
|
||||
partsToProbability.push({parts, probability});
|
||||
}
|
||||
expect(partsToProbability).toMatchSnapshot();
|
||||
}
|
||||
|
||||
describe("core/attribution/pagerank", () => {
|
||||
function edgeWeight(_unused_edge) {
|
||||
return {toWeight: 1, froWeight: 0};
|
||||
}
|
||||
it("snapshots as expected on the advanced graph", () => {
|
||||
const pagerankResult = pagerank(advancedGraph().graph1(), edgeWeight);
|
||||
snapshotPagerankResult(pagerankResult);
|
||||
});
|
||||
it("respects explicit arguments", () => {
|
||||
const pagerankResult = pagerank(advancedGraph().graph1(), edgeWeight, {
|
||||
maxIterations: 0,
|
||||
});
|
||||
snapshotPagerankResult(pagerankResult);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue