mirror of
https://github.com/status-im/sourcecred.git
synced 2025-02-18 07:26:28 +00:00
Remove types from TimelinePagerank (#1627)
This commit modifies the timelinePagerank module so that it no longer takes in node/edge types. Instead, the timelinePagerank just takes a WeightedGraph and uses weights from that WeightedGraph. This is a key part of decoupling the core cred computation logic from the plugin logic, as described in #1557. I also modified the timelinePagerank module's immediate dependencies (the weightEvaluator module) to do the same. Since the weight evaluators now have a simpler contract (no overriding, etc), the unit tests have been simplified. Test plan: It's a simple refactor, so `yarn test` should be sufficient. As a bit of added caution, I manually tested changing weights in the frontend, and verified that cred updates as expected.
This commit is contained in:
parent
9deeb93142
commit
5b2f38114b
@ -8,7 +8,7 @@ import {toCompat, fromCompat, type Compatible} from "../../util/compat";
|
|||||||
import {type Interval} from "./interval";
|
import {type Interval} from "./interval";
|
||||||
import {timelinePagerank} from "./timelinePagerank";
|
import {timelinePagerank} from "./timelinePagerank";
|
||||||
import {distributionToCred} from "./distributionToCred";
|
import {distributionToCred} from "./distributionToCred";
|
||||||
import {type PluginDeclaration, combineTypes} from "../pluginDeclaration";
|
import {type PluginDeclaration} from "../pluginDeclaration";
|
||||||
import {type NodeAddressT, NodeAddress, type Node} from "../../core/graph";
|
import {type NodeAddressT, NodeAddress, type Node} from "../../core/graph";
|
||||||
import * as WeightedGraph from "../../core/weightedGraph";
|
import * as WeightedGraph from "../../core/weightedGraph";
|
||||||
import {type Weights as WeightsT} from "../../core/weights";
|
import {type Weights as WeightsT} from "../../core/weights";
|
||||||
@ -189,16 +189,13 @@ export class TimelineCred {
|
|||||||
plugins: $ReadOnlyArray<PluginDeclaration>,
|
plugins: $ReadOnlyArray<PluginDeclaration>,
|
||||||
|}): Promise<TimelineCred> {
|
|}): Promise<TimelineCred> {
|
||||||
const {weightedGraph, params, plugins} = opts;
|
const {weightedGraph, params, plugins} = opts;
|
||||||
const {graph, weights} = weightedGraph;
|
const {graph} = weightedGraph;
|
||||||
const fullParams = params == null ? defaultParams() : partialParams(params);
|
const fullParams = params == null ? defaultParams() : partialParams(params);
|
||||||
const nodeOrder = Array.from(graph.nodes()).map((x) => x.address);
|
const nodeOrder = Array.from(graph.nodes()).map((x) => x.address);
|
||||||
const types = combineTypes(plugins);
|
|
||||||
const userTypes = [].concat(...plugins.map((x) => x.userTypes));
|
const userTypes = [].concat(...plugins.map((x) => x.userTypes));
|
||||||
const scorePrefixes = userTypes.map((x) => x.prefix);
|
const scorePrefixes = userTypes.map((x) => x.prefix);
|
||||||
const distribution = await timelinePagerank(
|
const distribution = await timelinePagerank(
|
||||||
graph,
|
weightedGraph,
|
||||||
types,
|
|
||||||
weights,
|
|
||||||
fullParams.intervalDecay,
|
fullParams.intervalDecay,
|
||||||
fullParams.alpha
|
fullParams.alpha
|
||||||
);
|
);
|
||||||
|
@ -7,8 +7,7 @@ import deepFreeze from "deep-freeze";
|
|||||||
import {sum} from "d3-array";
|
import {sum} from "d3-array";
|
||||||
import * as NullUtil from "../../util/null";
|
import * as NullUtil from "../../util/null";
|
||||||
import {Graph, type NodeAddressT, type Edge, type Node} from "../../core/graph";
|
import {Graph, type NodeAddressT, type Edge, type Node} from "../../core/graph";
|
||||||
import {type NodeAndEdgeTypes} from "../types";
|
import {type WeightedGraph} from "../../core/weightedGraph";
|
||||||
import {type Weights} from "../../core/weights";
|
|
||||||
import {type Interval, partitionGraph} from "./interval";
|
import {type Interval, partitionGraph} from "./interval";
|
||||||
import {
|
import {
|
||||||
nodeWeightEvaluator,
|
nodeWeightEvaluator,
|
||||||
@ -98,9 +97,7 @@ export type TimelineDistributions = $ReadOnlyArray<{|
|
|||||||
* the pieces and run PageRank for each interval.
|
* the pieces and run PageRank for each interval.
|
||||||
*/
|
*/
|
||||||
export async function timelinePagerank(
|
export async function timelinePagerank(
|
||||||
graph: Graph,
|
weightedGraph: WeightedGraph,
|
||||||
types: NodeAndEdgeTypes,
|
|
||||||
weights: Weights,
|
|
||||||
intervalDecay: number,
|
intervalDecay: number,
|
||||||
alpha: number
|
alpha: number
|
||||||
): Promise<TimelineDistributions> {
|
): Promise<TimelineDistributions> {
|
||||||
@ -112,24 +109,26 @@ export async function timelinePagerank(
|
|||||||
}
|
}
|
||||||
// Produce the evaluators we will use to get the baseline weight for each
|
// Produce the evaluators we will use to get the baseline weight for each
|
||||||
// node and edge
|
// node and edge
|
||||||
const nodeEvaluator = nodeWeightEvaluator(types.nodeTypes, weights);
|
const nodeEvaluator = nodeWeightEvaluator(weightedGraph.weights);
|
||||||
const edgeEvaluator = edgeWeightEvaluator(types.edgeTypes, weights);
|
const edgeEvaluator = edgeWeightEvaluator(weightedGraph.weights);
|
||||||
|
|
||||||
const graphPartitionSlices = partitionGraph(graph);
|
const graphPartitionSlices = partitionGraph(weightedGraph.graph);
|
||||||
if (graphPartitionSlices.length === 0) {
|
if (graphPartitionSlices.length === 0) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const intervals = graphPartitionSlices.map((x) => x.interval);
|
const intervals = graphPartitionSlices.map((x) => x.interval);
|
||||||
const nodeCreationHistory = graphPartitionSlices.map((x) => x.nodes);
|
const nodeCreationHistory = graphPartitionSlices.map((x) => x.nodes);
|
||||||
const edgeCreationHistory = graphPartitionSlices.map((x) => x.edges);
|
const edgeCreationHistory = graphPartitionSlices.map((x) => x.edges);
|
||||||
const nodeOrder = Array.from(graph.nodes()).map((x) => x.address);
|
const nodeOrder = Array.from(weightedGraph.graph.nodes()).map(
|
||||||
|
(x) => x.address
|
||||||
|
);
|
||||||
const nodeWeightIterator = _timelineNodeWeights(
|
const nodeWeightIterator = _timelineNodeWeights(
|
||||||
nodeCreationHistory,
|
nodeCreationHistory,
|
||||||
nodeEvaluator,
|
nodeEvaluator,
|
||||||
intervalDecay
|
intervalDecay
|
||||||
);
|
);
|
||||||
const markovChainIterator = _timelineMarkovChain(
|
const markovChainIterator = _timelineMarkovChain(
|
||||||
graph,
|
weightedGraph.graph,
|
||||||
edgeCreationHistory,
|
edgeCreationHistory,
|
||||||
edgeEvaluator,
|
edgeEvaluator,
|
||||||
intervalDecay
|
intervalDecay
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import type {NodeAddressT, EdgeAddressT} from "../core/graph";
|
import type {NodeAddressT, EdgeAddressT} from "../core/graph";
|
||||||
import type {NodeType, EdgeType} from "./types";
|
|
||||||
import type {
|
import type {
|
||||||
Weights as WeightsT,
|
Weights as WeightsT,
|
||||||
EdgeWeight,
|
EdgeWeight,
|
||||||
NodeWeight,
|
NodeWeight,
|
||||||
} from "../core/weights";
|
} from "../core/weights";
|
||||||
import * as Weights from "../core/weights";
|
|
||||||
import {NodeTrie, EdgeTrie} from "../core/trie";
|
import {NodeTrie, EdgeTrie} from "../core/trie";
|
||||||
|
|
||||||
export type NodeWeightEvaluator = (NodeAddressT) => NodeWeight;
|
export type NodeWeightEvaluator = (NodeAddressT) => NodeWeight;
|
||||||
@ -26,19 +24,9 @@ export type EdgeWeightEvaluator = (EdgeAddressT) => EdgeWeight;
|
|||||||
* legacy affordance; shortly we will remove the NodeTypes and require that the
|
* legacy affordance; shortly we will remove the NodeTypes and require that the
|
||||||
* plugins provide the type weights when the Weights object is constructed.
|
* plugins provide the type weights when the Weights object is constructed.
|
||||||
*/
|
*/
|
||||||
export function nodeWeightEvaluator(
|
export function nodeWeightEvaluator(weights: WeightsT): NodeWeightEvaluator {
|
||||||
types: $ReadOnlyArray<NodeType>,
|
|
||||||
weights: WeightsT
|
|
||||||
): NodeWeightEvaluator {
|
|
||||||
const {nodeWeights} = Weights.copy(weights);
|
|
||||||
|
|
||||||
for (const {prefix, defaultWeight} of types) {
|
|
||||||
if (!nodeWeights.has(prefix)) {
|
|
||||||
nodeWeights.set(prefix, defaultWeight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const nodeTrie: NodeTrie<NodeWeight> = new NodeTrie();
|
const nodeTrie: NodeTrie<NodeWeight> = new NodeTrie();
|
||||||
for (const [prefix, weight] of nodeWeights.entries()) {
|
for (const [prefix, weight] of weights.nodeWeights.entries()) {
|
||||||
nodeTrie.add(prefix, weight);
|
nodeTrie.add(prefix, weight);
|
||||||
}
|
}
|
||||||
return function nodeWeight(a: NodeAddressT): NodeWeight {
|
return function nodeWeight(a: NodeAddressT): NodeWeight {
|
||||||
@ -61,18 +49,9 @@ export function nodeWeightEvaluator(
|
|||||||
* directly in the weights object, so that producing weight evaluators will no
|
* directly in the weights object, so that producing weight evaluators will no
|
||||||
* longer depend on having plugin declarations on hand.
|
* longer depend on having plugin declarations on hand.
|
||||||
*/
|
*/
|
||||||
export function edgeWeightEvaluator(
|
export function edgeWeightEvaluator(weights: WeightsT): EdgeWeightEvaluator {
|
||||||
types: $ReadOnlyArray<EdgeType>,
|
|
||||||
weights: WeightsT
|
|
||||||
): EdgeWeightEvaluator {
|
|
||||||
const {edgeWeights} = Weights.copy(weights);
|
|
||||||
for (const {prefix, defaultWeight} of types) {
|
|
||||||
if (!edgeWeights.has(prefix)) {
|
|
||||||
edgeWeights.set(prefix, defaultWeight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const edgeTrie: EdgeTrie<EdgeWeight> = new EdgeTrie();
|
const edgeTrie: EdgeTrie<EdgeWeight> = new EdgeTrie();
|
||||||
for (const [prefix, weight] of edgeWeights.entries()) {
|
for (const [prefix, weight] of weights.edgeWeights.entries()) {
|
||||||
edgeTrie.add(prefix, weight);
|
edgeTrie.add(prefix, weight);
|
||||||
}
|
}
|
||||||
return function evaluator(address: EdgeAddressT): EdgeWeight {
|
return function evaluator(address: EdgeAddressT): EdgeWeight {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import deepFreeze from "deep-freeze";
|
|
||||||
import {NodeAddress, EdgeAddress} from "../core/graph";
|
import {NodeAddress, EdgeAddress} from "../core/graph";
|
||||||
import {nodeWeightEvaluator, edgeWeightEvaluator} from "./weightEvaluator";
|
import {nodeWeightEvaluator, edgeWeightEvaluator} from "./weightEvaluator";
|
||||||
import * as Weights from "../core/weights";
|
import * as Weights from "../core/weights";
|
||||||
@ -11,79 +10,33 @@ describe("src/analysis/weightEvaluator", () => {
|
|||||||
const foo = NodeAddress.fromParts(["foo"]);
|
const foo = NodeAddress.fromParts(["foo"]);
|
||||||
const foobar = NodeAddress.fromParts(["foo", "bar"]);
|
const foobar = NodeAddress.fromParts(["foo", "bar"]);
|
||||||
|
|
||||||
const fooNodeType = deepFreeze({
|
|
||||||
name: "",
|
|
||||||
pluralName: "",
|
|
||||||
prefix: foo,
|
|
||||||
defaultWeight: 2,
|
|
||||||
description: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
const fooBarNodeType = deepFreeze({
|
|
||||||
name: "",
|
|
||||||
pluralName: "",
|
|
||||||
prefix: foobar,
|
|
||||||
defaultWeight: 3,
|
|
||||||
description: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
const types = deepFreeze([fooNodeType, fooBarNodeType]);
|
|
||||||
|
|
||||||
it("gives every node weight 1 with empty types and weights", () => {
|
it("gives every node weight 1 with empty types and weights", () => {
|
||||||
const evaluator = nodeWeightEvaluator([], Weights.empty());
|
const evaluator = nodeWeightEvaluator(Weights.empty());
|
||||||
expect(evaluator(empty)).toEqual(1);
|
expect(evaluator(empty)).toEqual(1);
|
||||||
expect(evaluator(foo)).toEqual(1);
|
expect(evaluator(foo)).toEqual(1);
|
||||||
});
|
});
|
||||||
it("composes matching weights multiplicatively", () => {
|
it("composes matching weights multiplicatively", () => {
|
||||||
const evaluator = nodeWeightEvaluator(types, Weights.empty());
|
const weights = Weights.empty();
|
||||||
|
weights.nodeWeights.set(foo, 2);
|
||||||
|
weights.nodeWeights.set(foobar, 3);
|
||||||
|
const evaluator = nodeWeightEvaluator(weights);
|
||||||
expect(evaluator(empty)).toEqual(1);
|
expect(evaluator(empty)).toEqual(1);
|
||||||
expect(evaluator(foo)).toEqual(2);
|
expect(evaluator(foo)).toEqual(2);
|
||||||
expect(evaluator(foobar)).toEqual(6);
|
expect(evaluator(foobar)).toEqual(6);
|
||||||
});
|
});
|
||||||
it("explicitly set weights on type prefixes override the type weights", () => {
|
|
||||||
const weights = Weights.empty();
|
|
||||||
weights.nodeWeights.set(foo, 3);
|
|
||||||
weights.nodeWeights.set(foobar, 4);
|
|
||||||
const evaluator = nodeWeightEvaluator(types, weights);
|
|
||||||
expect(evaluator(empty)).toEqual(1);
|
|
||||||
expect(evaluator(foo)).toEqual(3);
|
|
||||||
expect(evaluator(foobar)).toEqual(12);
|
|
||||||
});
|
|
||||||
it("uses manually-specified weights", () => {
|
|
||||||
const weights = Weights.empty();
|
|
||||||
weights.nodeWeights.set(foo, 3);
|
|
||||||
const evaluator = nodeWeightEvaluator([], weights);
|
|
||||||
expect(evaluator(empty)).toEqual(1);
|
|
||||||
expect(evaluator(foo)).toEqual(3);
|
|
||||||
expect(evaluator(foobar)).toEqual(3);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
describe("edgeEvaluator", () => {
|
describe("edgeEvaluator", () => {
|
||||||
const foo = EdgeAddress.fromParts(["foo"]);
|
const foo = EdgeAddress.fromParts(["foo"]);
|
||||||
const foobar = EdgeAddress.fromParts(["foo", "bar"]);
|
const foobar = EdgeAddress.fromParts(["foo", "bar"]);
|
||||||
const fooType = deepFreeze({
|
|
||||||
forwardName: "",
|
|
||||||
backwardName: "",
|
|
||||||
defaultWeight: {forwards: 2, backwards: 3},
|
|
||||||
prefix: foo,
|
|
||||||
description: "",
|
|
||||||
});
|
|
||||||
const fooBarType = deepFreeze({
|
|
||||||
forwardName: "",
|
|
||||||
backwardName: "",
|
|
||||||
defaultWeight: {forwards: 4, backwards: 5},
|
|
||||||
prefix: foobar,
|
|
||||||
description: "",
|
|
||||||
});
|
|
||||||
it("gives default 1,1 weights if no matching type", () => {
|
it("gives default 1,1 weights if no matching type", () => {
|
||||||
const evaluator = edgeWeightEvaluator([], Weights.empty());
|
const evaluator = edgeWeightEvaluator(Weights.empty());
|
||||||
expect(evaluator(foo)).toEqual({forwards: 1, backwards: 1});
|
expect(evaluator(foo)).toEqual({forwards: 1, backwards: 1});
|
||||||
});
|
});
|
||||||
it("composes weights multiplicatively for all matching types", () => {
|
it("composes weights multiplicatively for all matching types", () => {
|
||||||
const evaluator = edgeWeightEvaluator(
|
const weights = Weights.empty();
|
||||||
[fooType, fooBarType],
|
weights.edgeWeights.set(foo, {forwards: 2, backwards: 3});
|
||||||
Weights.empty()
|
weights.edgeWeights.set(foobar, {forwards: 4, backwards: 5});
|
||||||
);
|
const evaluator = edgeWeightEvaluator(weights);
|
||||||
expect(evaluator(foo)).toEqual({forwards: 2, backwards: 3});
|
expect(evaluator(foo)).toEqual({forwards: 2, backwards: 3});
|
||||||
expect(evaluator(foobar)).toEqual({forwards: 8, backwards: 15});
|
expect(evaluator(foobar)).toEqual({forwards: 8, backwards: 15});
|
||||||
expect(evaluator(EdgeAddress.fromParts(["foo", "bar", "qox"]))).toEqual({
|
expect(evaluator(EdgeAddress.fromParts(["foo", "bar", "qox"]))).toEqual({
|
||||||
@ -91,12 +44,5 @@ describe("src/analysis/weightEvaluator", () => {
|
|||||||
backwards: 15,
|
backwards: 15,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("explicit weights override defaults from types", () => {
|
|
||||||
const weights = Weights.empty();
|
|
||||||
weights.edgeWeights.set(foo, {forwards: 99, backwards: 101});
|
|
||||||
const evaluator = edgeWeightEvaluator([fooType, fooBarType], weights);
|
|
||||||
expect(evaluator(foo)).toEqual({forwards: 99, backwards: 101});
|
|
||||||
expect(evaluator(foobar)).toEqual({forwards: 4 * 99, backwards: 5 * 101});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import type {Edge} from "../core/graph";
|
import type {Edge} from "../core/graph";
|
||||||
import type {NodeAndEdgeTypes} from "./types";
|
|
||||||
import type {Weights} from "../core/weights";
|
import type {Weights} from "../core/weights";
|
||||||
import type {EdgeEvaluator} from "./pagerank";
|
import type {EdgeEvaluator} from "./pagerank";
|
||||||
import {nodeWeightEvaluator, edgeWeightEvaluator} from "./weightEvaluator";
|
import {nodeWeightEvaluator, edgeWeightEvaluator} from "./weightEvaluator";
|
||||||
@ -27,12 +26,9 @@ import {nodeWeightEvaluator, edgeWeightEvaluator} from "./weightEvaluator";
|
|||||||
* cred weighting) rather than as a component of the edge weight. This method
|
* cred weighting) rather than as a component of the edge weight. This method
|
||||||
* will be removed when the 'legacy cred' UI is removed.
|
* will be removed when the 'legacy cred' UI is removed.
|
||||||
*/
|
*/
|
||||||
export function weightsToEdgeEvaluator(
|
export function weightsToEdgeEvaluator(weights: Weights): EdgeEvaluator {
|
||||||
weights: Weights,
|
const nodeWeight = nodeWeightEvaluator(weights);
|
||||||
types: NodeAndEdgeTypes
|
const edgeWeight = edgeWeightEvaluator(weights);
|
||||||
): EdgeEvaluator {
|
|
||||||
const nodeWeight = nodeWeightEvaluator(types.nodeTypes, weights);
|
|
||||||
const edgeWeight = edgeWeightEvaluator(types.edgeTypes, weights);
|
|
||||||
|
|
||||||
return function evaluator(edge: Edge) {
|
return function evaluator(edge: Edge) {
|
||||||
const srcWeight = nodeWeight(edge.src);
|
const srcWeight = nodeWeight(edge.src);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import deepFreeze from "deep-freeze";
|
|
||||||
import {NodeAddress, EdgeAddress} from "../core/graph";
|
import {NodeAddress, EdgeAddress} from "../core/graph";
|
||||||
import {type Weights as WeightsT} from "../core/weights";
|
import {type Weights as WeightsT} from "../core/weights";
|
||||||
import * as Weights from "../core/weights";
|
import * as Weights from "../core/weights";
|
||||||
@ -16,57 +15,19 @@ describe("analysis/weightsToEdgeEvaluator", () => {
|
|||||||
timestampMs: 0,
|
timestampMs: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const fallbackNodeType = deepFreeze({
|
|
||||||
name: "",
|
|
||||||
pluralName: "",
|
|
||||||
prefix: NodeAddress.empty,
|
|
||||||
defaultWeight: 1,
|
|
||||||
description: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
const srcNodeType = deepFreeze({
|
|
||||||
name: "",
|
|
||||||
pluralName: "",
|
|
||||||
prefix: src,
|
|
||||||
defaultWeight: 2,
|
|
||||||
description: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
const fallbackEdgeType = deepFreeze({
|
|
||||||
forwardName: "",
|
|
||||||
backwardName: "",
|
|
||||||
defaultWeight: {forwards: 1, backwards: 1},
|
|
||||||
prefix: EdgeAddress.empty,
|
|
||||||
description: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
function evaluateEdge(weights: WeightsT) {
|
function evaluateEdge(weights: WeightsT) {
|
||||||
const evaluator = weightsToEdgeEvaluator(weights, {
|
const evaluator = weightsToEdgeEvaluator(weights);
|
||||||
nodeTypes: [fallbackNodeType, srcNodeType],
|
|
||||||
edgeTypes: [fallbackEdgeType],
|
|
||||||
});
|
|
||||||
return evaluator(edge);
|
return evaluator(edge);
|
||||||
}
|
}
|
||||||
|
|
||||||
it("applies default weights when none are specified", () => {
|
it("applies default weights when none are specified", () => {
|
||||||
expect(evaluateEdge(Weights.empty())).toEqual({forwards: 1, backwards: 2});
|
expect(evaluateEdge(Weights.empty())).toEqual({forwards: 1, backwards: 1});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("matches all prefixes of the nodes in scope", () => {
|
it("matches all prefixes of the nodes in scope", () => {
|
||||||
const weights = Weights.empty();
|
const weights = Weights.empty();
|
||||||
weights.nodeWeights.set(NodeAddress.empty, 99);
|
weights.nodeWeights.set(NodeAddress.empty, 99);
|
||||||
expect(evaluateEdge(weights)).toEqual({forwards: 99, backwards: 2 * 99});
|
expect(evaluateEdge(weights)).toEqual({forwards: 99, backwards: 99});
|
||||||
});
|
|
||||||
|
|
||||||
it("takes manually specified edge type weights into account", () => {
|
|
||||||
const weights = Weights.empty();
|
|
||||||
// Note that here we grab the fallout edge type. This also verifies that
|
|
||||||
// we are doing prefix matching on the types (rather than exact matching).
|
|
||||||
weights.edgeWeights.set(EdgeAddress.empty, {
|
|
||||||
forwards: 6,
|
|
||||||
backwards: 12,
|
|
||||||
});
|
|
||||||
expect(evaluateEdge(weights)).toEqual({forwards: 6, backwards: 24});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("an explicit weight on a prefix overrides the type weight", () => {
|
it("an explicit weight on a prefix overrides the type weight", () => {
|
||||||
@ -76,10 +37,7 @@ describe("analysis/weightsToEdgeEvaluator", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("uses 1 as a default weight for unmatched nodes and edges", () => {
|
it("uses 1 as a default weight for unmatched nodes and edges", () => {
|
||||||
const evaluator = weightsToEdgeEvaluator(Weights.empty(), {
|
const evaluator = weightsToEdgeEvaluator(Weights.empty());
|
||||||
nodeTypes: [],
|
|
||||||
edgeTypes: [],
|
|
||||||
});
|
|
||||||
expect(evaluator(edge)).toEqual({forwards: 1, backwards: 1});
|
expect(evaluator(edge)).toEqual({forwards: 1, backwards: 1});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -15,10 +15,7 @@ import {TimelineCred} from "../../analysis/timeline/timelineCred";
|
|||||||
|
|
||||||
import type {Weights} from "../../core/weights";
|
import type {Weights} from "../../core/weights";
|
||||||
import {weightsToEdgeEvaluator} from "../../analysis/weightsToEdgeEvaluator";
|
import {weightsToEdgeEvaluator} from "../../analysis/weightsToEdgeEvaluator";
|
||||||
import {
|
import {type PluginDeclarations} from "../../analysis/pluginDeclaration";
|
||||||
combineTypes,
|
|
||||||
type PluginDeclarations,
|
|
||||||
} from "../../analysis/pluginDeclaration";
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This models the UI states of the credExplorer/App as a state machine.
|
This models the UI states of the credExplorer/App as a state machine.
|
||||||
@ -157,11 +154,10 @@ export class StateTransitionMachine implements StateTransitionMachineInterface {
|
|||||||
this.setState(loadingState);
|
this.setState(loadingState);
|
||||||
const graph = state.timelineCred.weightedGraph().graph;
|
const graph = state.timelineCred.weightedGraph().graph;
|
||||||
let newState: ?AppState;
|
let newState: ?AppState;
|
||||||
const types = combineTypes(state.pluginDeclarations);
|
|
||||||
try {
|
try {
|
||||||
const pagerankNodeDecomposition = await this.pagerank(
|
const pagerankNodeDecomposition = await this.pagerank(
|
||||||
graph,
|
graph,
|
||||||
weightsToEdgeEvaluator(weights, types),
|
weightsToEdgeEvaluator(weights),
|
||||||
{
|
{
|
||||||
verbose: true,
|
verbose: true,
|
||||||
totalScoreNodePrefix: totalScoreNodePrefix,
|
totalScoreNodePrefix: totalScoreNodePrefix,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user