Separate in-edge and out-edge contribution types (#491)
Summary: This change is motivated by the behavior of loops, but applies more generally to edges. Previously, a loop would induce two contributions with the same contributor, but possibly different weights: one with the to-weight of the edge and one with the fro-weight. For one, this is annoying to downstream clients, who would like to use the contributor as a superkey. But it is also somewhat strange that a single contributor could have two different weights. The same applies to edges in general: every edge induces two contributions with the same contributor, of type `NEIGHBOR`. As of this commit, we replace `NEIGHBOR` with `IN_EDGE` and `OUT_EDGE`, one of each induced by each edge. This has the effect that a contributor maps to at most one contribution. Test Plan: Existing unit tests updated. wchargin-branch: separate-in-out-edge-contributions
This commit is contained in:
parent
761a44c561
commit
47eecef7b2
|
@ -1,18 +1,13 @@
|
|||
// @flow
|
||||
|
||||
import {
|
||||
type Edge,
|
||||
type Graph,
|
||||
type Neighbor,
|
||||
type NodeAddressT,
|
||||
NodeAddress,
|
||||
} from "../graph";
|
||||
import {type Edge, type Graph, type NodeAddressT, NodeAddress} from "../graph";
|
||||
import type {Distribution, SparseMarkovChain} from "./markovChain";
|
||||
|
||||
export type Probability = number;
|
||||
export type Contributor =
|
||||
| {|+type: "SYNTHETIC_LOOP"|}
|
||||
| {|+type: "NEIGHBOR", +neighbor: Neighbor|};
|
||||
| {|+type: "IN_EDGE", +edge: Edge|}
|
||||
| {|+type: "OUT_EDGE", +edge: Edge|};
|
||||
export type Contribution = {|
|
||||
+contributor: Contributor,
|
||||
// This `weight` is a conditional probability: given that you're at
|
||||
|
@ -28,8 +23,10 @@ export function contributorSource(
|
|||
switch (contributor.type) {
|
||||
case "SYNTHETIC_LOOP":
|
||||
return target;
|
||||
case "NEIGHBOR":
|
||||
return contributor.neighbor.node;
|
||||
case "IN_EDGE":
|
||||
return contributor.edge.src;
|
||||
case "OUT_EDGE":
|
||||
return contributor.edge.dst;
|
||||
default:
|
||||
throw new Error((contributor.type: empty));
|
||||
}
|
||||
|
@ -104,11 +101,11 @@ export function createContributions(
|
|||
const {toWeight, froWeight} = edgeWeight(edge);
|
||||
const {src, dst} = edge;
|
||||
processContribution(dst, {
|
||||
contributor: {type: "NEIGHBOR", neighbor: {node: src, edge}},
|
||||
contributor: {type: "IN_EDGE", edge},
|
||||
weight: toWeight,
|
||||
});
|
||||
processContribution(src, {
|
||||
contributor: {type: "NEIGHBOR", neighbor: {node: dst, edge}},
|
||||
contributor: {type: "OUT_EDGE", edge},
|
||||
weight: froWeight,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -109,44 +109,42 @@ describe("core/attribution/graphToMarkovChain", () => {
|
|||
.set(n1, [
|
||||
{contributor: {type: "SYNTHETIC_LOOP"}, weight: 1 / 13},
|
||||
{
|
||||
contributor: {type: "NEIGHBOR", neighbor: {node: n2, edge: e1}},
|
||||
contributor: {type: "OUT_EDGE", edge: e1},
|
||||
weight: 3 / 10,
|
||||
},
|
||||
{
|
||||
contributor: {type: "NEIGHBOR", neighbor: {node: n3, edge: e3}},
|
||||
contributor: {type: "OUT_EDGE", edge: e3},
|
||||
weight: 3 / 16,
|
||||
},
|
||||
])
|
||||
.set(n2, [
|
||||
{contributor: {type: "SYNTHETIC_LOOP"}, weight: 1 / 10},
|
||||
{
|
||||
contributor: {type: "NEIGHBOR", neighbor: {node: n1, edge: e1}},
|
||||
contributor: {type: "IN_EDGE", edge: e1},
|
||||
weight: 6 / 13,
|
||||
},
|
||||
{
|
||||
contributor: {type: "NEIGHBOR", neighbor: {node: n3, edge: e2}},
|
||||
contributor: {type: "OUT_EDGE", edge: e2},
|
||||
weight: 3 / 16,
|
||||
},
|
||||
])
|
||||
.set(n3, [
|
||||
{contributor: {type: "SYNTHETIC_LOOP"}, weight: 1 / 16},
|
||||
{
|
||||
contributor: {type: "NEIGHBOR", neighbor: {node: n2, edge: e2}},
|
||||
contributor: {type: "IN_EDGE", edge: e2},
|
||||
weight: 6 / 10,
|
||||
},
|
||||
{
|
||||
contributor: {type: "NEIGHBOR", neighbor: {node: n1, edge: e3}},
|
||||
contributor: {type: "IN_EDGE", edge: e3},
|
||||
weight: 6 / 13,
|
||||
},
|
||||
{
|
||||
contributor: {type: "NEIGHBOR", neighbor: {node: n3, edge: e4}},
|
||||
// this loop, as an out-edge
|
||||
weight: 3 / 16,
|
||||
contributor: {type: "IN_EDGE", edge: e4},
|
||||
weight: 6 / 16,
|
||||
},
|
||||
{
|
||||
contributor: {type: "NEIGHBOR", neighbor: {node: n3, edge: e4}},
|
||||
// this loop, as an in-edge
|
||||
weight: 6 / 16,
|
||||
contributor: {type: "OUT_EDGE", edge: e4},
|
||||
weight: 3 / 16,
|
||||
},
|
||||
]);
|
||||
const canonicalize = (map) =>
|
||||
|
|
Loading…
Reference in New Issue