Add `weightsToEdgeEvaluator` (#785)
This commit adds `weightsToEdgeEvaluator`, a function for converting weighted node types into an `EdgeEvaluator`. This replaces the `edgeWeights` module (which was untested, and an outmoded API). Test plan: The new `weightsToEdgeEvaluator` method is well-tested. Since `WeightConfig` is still not tested, I manually verified that it still works as anticipated.
This commit is contained in:
parent
3dda4ab35c
commit
f7383bbc90
|
@ -3,7 +3,7 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import {type EdgeEvaluator} from "../../core/attribution/pagerank";
|
import {type EdgeEvaluator} from "../../core/attribution/pagerank";
|
||||||
import {byEdgeType, byNodeType} from "./edgeWeights";
|
import {weightsToEdgeEvaluator} from "./weights/weightsToEdgeEvaluator";
|
||||||
import type {StaticAdapterSet} from "../adapters/adapterSet";
|
import type {StaticAdapterSet} from "../adapters/adapterSet";
|
||||||
import {
|
import {
|
||||||
type WeightedTypes,
|
type WeightedTypes,
|
||||||
|
@ -104,18 +104,8 @@ export class WeightConfig extends React.Component<Props, State> {
|
||||||
edgeWeights = edgeWeights.concat(newEdgeWeights);
|
edgeWeights = edgeWeights.concat(newEdgeWeights);
|
||||||
}
|
}
|
||||||
|
|
||||||
const edgePrefixes = edgeWeights.map(
|
const weights = {nodes: nodeWeights, edges: edgeWeights};
|
||||||
({type, forwardWeight, backwardWeight}) => ({
|
const edgeEvaluator = weightsToEdgeEvaluator(weights);
|
||||||
prefix: type.prefix,
|
|
||||||
forwardWeight,
|
|
||||||
backwardWeight,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
const nodePrefixes = nodeWeights.map(({type, weight}) => ({
|
|
||||||
prefix: type.prefix,
|
|
||||||
weight,
|
|
||||||
}));
|
|
||||||
const edgeEvaluator = byNodeType(byEdgeType(edgePrefixes), nodePrefixes);
|
|
||||||
this.props.onChange(edgeEvaluator);
|
this.props.onChange(edgeEvaluator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
// @flow
|
|
||||||
import {
|
|
||||||
type Edge,
|
|
||||||
type EdgeAddressT,
|
|
||||||
type NodeAddressT,
|
|
||||||
} from "../../core/graph";
|
|
||||||
import {NodeTrie, EdgeTrie} from "../../core/trie";
|
|
||||||
import type {EdgeEvaluator} from "../../core/attribution/pagerank";
|
|
||||||
|
|
||||||
export function byEdgeType(
|
|
||||||
prefixes: $ReadOnlyArray<{|
|
|
||||||
+prefix: EdgeAddressT,
|
|
||||||
+forwardWeight: number,
|
|
||||||
+backwardWeight: number,
|
|
||||||
|}>
|
|
||||||
): EdgeEvaluator {
|
|
||||||
const trie = new EdgeTrie();
|
|
||||||
for (const {prefix, forwardWeight, backwardWeight} of prefixes) {
|
|
||||||
trie.add(prefix, {toWeight: forwardWeight, froWeight: backwardWeight});
|
|
||||||
}
|
|
||||||
return function evaluator(edge: Edge) {
|
|
||||||
return trie.getLast(edge.address);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function byNodeType(
|
|
||||||
base: EdgeEvaluator,
|
|
||||||
prefixes: $ReadOnlyArray<{|
|
|
||||||
+prefix: NodeAddressT,
|
|
||||||
+weight: number,
|
|
||||||
|}>
|
|
||||||
): EdgeEvaluator {
|
|
||||||
const trie = new NodeTrie();
|
|
||||||
for (const {weight, prefix} of prefixes) {
|
|
||||||
trie.add(prefix, weight);
|
|
||||||
}
|
|
||||||
return function evaluator(edge: Edge) {
|
|
||||||
const srcWeight = trie.getLast(edge.src);
|
|
||||||
const dstWeight = trie.getLast(edge.dst);
|
|
||||||
|
|
||||||
const baseResult = base(edge);
|
|
||||||
return {
|
|
||||||
toWeight: dstWeight * baseResult.toWeight,
|
|
||||||
froWeight: srcWeight * baseResult.froWeight,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import type {Edge} from "../../../core/graph";
|
||||||
|
import type {WeightedTypes} from "./PluginWeightConfig";
|
||||||
|
import type {EdgeEvaluator} from "../../../core/attribution/pagerank";
|
||||||
|
import {NodeTrie, EdgeTrie} from "../../../core/trie";
|
||||||
|
|
||||||
|
export function weightsToEdgeEvaluator(weights: WeightedTypes): EdgeEvaluator {
|
||||||
|
const nodeTrie = new NodeTrie();
|
||||||
|
for (const {type, weight} of weights.nodes) {
|
||||||
|
nodeTrie.add(type.prefix, weight);
|
||||||
|
}
|
||||||
|
const edgeTrie = new EdgeTrie();
|
||||||
|
for (const {type, forwardWeight, backwardWeight} of weights.edges) {
|
||||||
|
edgeTrie.add(type.prefix, {forwardWeight, backwardWeight});
|
||||||
|
}
|
||||||
|
|
||||||
|
return function evaluator(edge: Edge) {
|
||||||
|
const srcWeight = nodeTrie.getLast(edge.src);
|
||||||
|
const dstWeight = nodeTrie.getLast(edge.dst);
|
||||||
|
const {forwardWeight, backwardWeight} = edgeTrie.getLast(edge.address);
|
||||||
|
return {
|
||||||
|
toWeight: dstWeight * forwardWeight,
|
||||||
|
froWeight: srcWeight * backwardWeight,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import * as NullUtil from "../../../util/null";
|
||||||
|
import {
|
||||||
|
fallbackNodeType,
|
||||||
|
fallbackEdgeType,
|
||||||
|
} from "../../adapters/fallbackAdapter";
|
||||||
|
import {
|
||||||
|
inserterNodeType,
|
||||||
|
machineNodeType,
|
||||||
|
assemblesEdgeType,
|
||||||
|
factorioEdges,
|
||||||
|
} from "../../adapters/demoAdapters";
|
||||||
|
import {weightsToEdgeEvaluator} from "./weightsToEdgeEvaluator";
|
||||||
|
|
||||||
|
describe("app/credExplorer/weights/weightsToEdgeEvaluator", () => {
|
||||||
|
describe("weightsToEdgeEvaluator", () => {
|
||||||
|
type WeightArgs = {|
|
||||||
|
+assemblesForward?: number,
|
||||||
|
+assemblesBackward?: number,
|
||||||
|
+baseForward?: number,
|
||||||
|
+baseBackward?: number,
|
||||||
|
+inserter?: number,
|
||||||
|
+machine?: number,
|
||||||
|
+baseNode?: number,
|
||||||
|
|};
|
||||||
|
function weights({
|
||||||
|
assemblesForward,
|
||||||
|
assemblesBackward,
|
||||||
|
baseForward,
|
||||||
|
baseBackward,
|
||||||
|
inserter,
|
||||||
|
machine,
|
||||||
|
baseNode,
|
||||||
|
}: WeightArgs) {
|
||||||
|
const nodes = [
|
||||||
|
{weight: NullUtil.orElse(inserter, 1), type: inserterNodeType},
|
||||||
|
{weight: NullUtil.orElse(machine, 1), type: machineNodeType},
|
||||||
|
{weight: NullUtil.orElse(baseNode, 1), type: fallbackNodeType},
|
||||||
|
];
|
||||||
|
const edges = [
|
||||||
|
{
|
||||||
|
forwardWeight: NullUtil.orElse(assemblesForward, 1),
|
||||||
|
backwardWeight: NullUtil.orElse(assemblesBackward, 1),
|
||||||
|
type: assemblesEdgeType,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
forwardWeight: NullUtil.orElse(baseForward, 1),
|
||||||
|
backwardWeight: NullUtil.orElse(baseBackward, 1),
|
||||||
|
type: fallbackEdgeType,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return {nodes, edges};
|
||||||
|
}
|
||||||
|
function exampleEdgeWeights(weightArgs: WeightArgs) {
|
||||||
|
const ws = weights(weightArgs);
|
||||||
|
const ee = weightsToEdgeEvaluator(ws);
|
||||||
|
// src is a machine, dst is an inserter, edge type is assembles
|
||||||
|
return ee(factorioEdges.assembles1);
|
||||||
|
}
|
||||||
|
it("toWeight is affected by the edge's forwardWeight", () => {
|
||||||
|
expect(exampleEdgeWeights({assemblesForward: 2}).toWeight).toEqual(2);
|
||||||
|
});
|
||||||
|
it("froWeight is affected by the edge's backwardWeight", () => {
|
||||||
|
expect(exampleEdgeWeights({assemblesBackward: 3}).froWeight).toEqual(3);
|
||||||
|
});
|
||||||
|
it("toWeight is affected by the dst's weight", () => {
|
||||||
|
expect(exampleEdgeWeights({inserter: 4}).toWeight).toEqual(4);
|
||||||
|
});
|
||||||
|
it("froWeight is affected by the src's weight", () => {
|
||||||
|
expect(exampleEdgeWeights({machine: 5}).froWeight).toEqual(5);
|
||||||
|
});
|
||||||
|
it("only the closest-matching node prefix is considered", () => {
|
||||||
|
expect(exampleEdgeWeights({baseNode: 6})).toEqual({
|
||||||
|
toWeight: 1,
|
||||||
|
froWeight: 1,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("only the closest-matching edge prefix is considered", () => {
|
||||||
|
expect(exampleEdgeWeights({baseBackward: 7})).toEqual({
|
||||||
|
toWeight: 1,
|
||||||
|
froWeight: 1,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("node and edge weights compose via multiplication", () => {
|
||||||
|
expect(
|
||||||
|
exampleEdgeWeights({
|
||||||
|
inserter: 2,
|
||||||
|
machine: 3,
|
||||||
|
assemblesForward: 4,
|
||||||
|
assemblesBackward: 5,
|
||||||
|
})
|
||||||
|
).toEqual({toWeight: 8, froWeight: 15});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue