From 17496764596082335b255952bcf9d7a7ec018ba2 Mon Sep 17 00:00:00 2001 From: William Chargin Date: Wed, 4 Jul 2018 18:24:34 -0700 Subject: [PATCH] Evaluate edge weight based on node and edge type (#486) Summary: PageRank wants an _edge evaluator_: a function mapping an edge to its to-weight and fro-weight. This commit provides functions for creating edge evaluators based on the high-level, coarse notions of node and edge types. We use [the formulation described in a comment on #476][1]. Paired with @decentralion. [1]: https://github.com/sourcecred/sourcecred/issues/476#issuecomment-402576435 Test Plan: None. We will add tests later. We promise! wchargin-branch: edge-weight-generators --- src/app/credExplorer/edgeWeights.js | 56 +++++++++++++++++++++++++++++ src/core/attribution/pagerank.js | 5 ++- 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/app/credExplorer/edgeWeights.js diff --git a/src/app/credExplorer/edgeWeights.js b/src/app/credExplorer/edgeWeights.js new file mode 100644 index 0000000..fab8db0 --- /dev/null +++ b/src/app/credExplorer/edgeWeights.js @@ -0,0 +1,56 @@ +// @flow +import { + type Edge, + type EdgeAddressT, + type NodeAddressT, + EdgeAddress, + NodeAddress, +} from "../../core/graph"; +import type {EdgeEvaluator} from "../../core/attribution/pagerank"; + +export function byEdgeType( + prefixes: $ReadOnlyArray<{| + +prefix: EdgeAddressT, + +weight: number, + +directionality: number, + |}> +): EdgeEvaluator { + return function evaluator(edge: Edge) { + const datum = prefixes.find(({prefix}) => + EdgeAddress.hasPrefix(edge.address, prefix) + ); + if (datum == null) { + throw new Error(EdgeAddress.toString(edge.address)); + } + const {weight, directionality} = datum; + return { + toWeight: directionality * weight, + froWeight: (1 - directionality) * weight, + }; + }; +} + +export function byNodeType( + base: EdgeEvaluator, + prefixes: $ReadOnlyArray<{| + +prefix: NodeAddressT, + +weight: number, + |}> +): EdgeEvaluator { + return function evaluator(edge: Edge) { + const srcDatum = prefixes.find(({prefix}) => + NodeAddress.hasPrefix(edge.src, prefix) + ); + const dstDatum = prefixes.find(({prefix}) => + NodeAddress.hasPrefix(edge.dst, prefix) + ); + if (srcDatum == null || dstDatum == null) { + throw new Error(EdgeAddress.toString(edge.address)); + } + const baseResult = base(edge); + return { + toWeight: dstDatum.weight * baseResult.toWeight, + froWeight: srcDatum.weight * baseResult.froWeight, + }; + }; +} diff --git a/src/core/attribution/pagerank.js b/src/core/attribution/pagerank.js index 4a56cee..864163d 100644 --- a/src/core/attribution/pagerank.js +++ b/src/core/attribution/pagerank.js @@ -18,6 +18,9 @@ export type PagerankOptions = {| +maxIterations?: number, |}; +export type {EdgeWeight} from "./graphToMarkovChain"; +export type EdgeEvaluator = (Edge) => EdgeWeight; + function defaultOptions(): PagerankOptions { return { verbose: false, @@ -29,7 +32,7 @@ function defaultOptions(): PagerankOptions { export function pagerank( graph: Graph, - edgeWeight: (Edge) => EdgeWeight, + edgeWeight: EdgeEvaluator, options?: PagerankOptions ): PagerankResult { const fullOptions = {