mirror of
https://github.com/status-im/sourcecred.git
synced 2025-02-05 17:24:24 +00:00
Add Weights.merge
(#1584)
This adds a `merge` method to the weights module, which allows combining multiple weights together. If any of the weights overlap (i.e. the same address is specified in multiple Weights), then an error will be thrown. In the future, we will likely extend the API so that the client can specify how to resolve cases where the same address is present in multiple weights. The method is thoroughly unit tested. This is part of work on #1557 (we'll want to be able to merge `WeightedGraph`s.) Test plan: Run `yarn test`
This commit is contained in:
parent
325487a3ea
commit
9784927402
@ -48,6 +48,21 @@ export function copy(w: Weights): Weights {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge multiple Weights together.
|
||||
*
|
||||
* The resultant Weights will have every weight specified by each of the
|
||||
* input weights. If there are any overlaps (i.e. the same address is present
|
||||
* in two or more of the input weights), an error will be thrown. In the future,
|
||||
* we will likely modify this function to add a resolver that determines how to
|
||||
* combine multiple overlapping weights.
|
||||
*/
|
||||
export function merge(ws: $ReadOnlyArray<Weights>): Weights {
|
||||
const nodeWeights = MapUtil.merge(ws.map((x) => x.nodeWeights));
|
||||
const edgeWeights = MapUtil.merge(ws.map((x) => x.edgeWeights));
|
||||
return {nodeWeights, edgeWeights};
|
||||
}
|
||||
|
||||
export type WeightsJSON = Compatible<{|
|
||||
+nodeWeights: {[NodeAddressT]: NodeWeight},
|
||||
+edgeWeights: {[EdgeAddressT]: EdgeWeight},
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
import stringify from "json-stable-stringify";
|
||||
import {NodeAddress, EdgeAddress} from "../core/graph";
|
||||
import {type Weights as WeightsT} from "./weights";
|
||||
import * as Weights from "./weights";
|
||||
|
||||
describe("core/weights", () => {
|
||||
@ -69,4 +70,71 @@ describe("core/weights", () => {
|
||||
expect(weights).toEqual(Weights.fromJSON(json));
|
||||
});
|
||||
});
|
||||
describe("merge", () => {
|
||||
function simpleWeights(
|
||||
nodeWeights: [string, number][],
|
||||
edgeWeights: [string, number, number][]
|
||||
): WeightsT {
|
||||
const w = Weights.empty();
|
||||
for (const [addrPart, weight] of nodeWeights) {
|
||||
w.nodeWeights.set(NodeAddress.fromParts([addrPart]), weight);
|
||||
}
|
||||
for (const [addrPart, forwards, backwards] of edgeWeights) {
|
||||
const weight = {forwards, backwards};
|
||||
w.edgeWeights.set(EdgeAddress.fromParts([addrPart]), weight);
|
||||
}
|
||||
return w;
|
||||
}
|
||||
it("produces empty weights when given an empty array", () => {
|
||||
expect(Weights.merge([])).toEqual(Weights.empty());
|
||||
});
|
||||
it("produces empty weights when given empty weights", () => {
|
||||
expect(Weights.merge([Weights.empty(), Weights.empty()])).toEqual(
|
||||
Weights.empty()
|
||||
);
|
||||
});
|
||||
it("returns a copy when given only one weights", () => {
|
||||
const w = simpleWeights([["foo", 3]], [["bar", 2, 3]]);
|
||||
const wc = Weights.copy(w);
|
||||
const merged = Weights.merge([w]);
|
||||
expect(merged).toEqual(wc);
|
||||
expect(merged).not.toBe(wc);
|
||||
});
|
||||
it("can merge two non-overlapping weights", () => {
|
||||
const w1 = simpleWeights([["foo", 3]], [["bar", 2, 3]]);
|
||||
const w2 = simpleWeights([["zod", 4]], [["zoink", 4, 5]]);
|
||||
const w3 = simpleWeights(
|
||||
[
|
||||
["foo", 3],
|
||||
["zod", 4],
|
||||
],
|
||||
[
|
||||
["bar", 2, 3],
|
||||
["zoink", 4, 5],
|
||||
]
|
||||
);
|
||||
const merged = Weights.merge([w1, w2]);
|
||||
expect(merged).toEqual(w3);
|
||||
});
|
||||
it("throws an error on overlapping weights with no conflicts", () => {
|
||||
const w1 = simpleWeights([["foo", 3]], [["bar", 2, 3]]);
|
||||
const w2 = simpleWeights([["foo", 3]], [["bar", 2, 3]]);
|
||||
expect(() => Weights.merge([w1, w2])).toThrowError("duplicate key");
|
||||
});
|
||||
it("errors on conflicting node weights", () => {
|
||||
const w1 = simpleWeights([["foo", 3]], []);
|
||||
const w2 = simpleWeights([["foo", 4]], []);
|
||||
expect(() => Weights.merge([w1, w2])).toThrowError("duplicate key");
|
||||
});
|
||||
it("errors on conflicting edge weights (forwards)", () => {
|
||||
const w1 = simpleWeights([], [["foo", 3, 4]]);
|
||||
const w2 = simpleWeights([], [["foo", 4, 4]]);
|
||||
expect(() => Weights.merge([w1, w2])).toThrowError("duplicate key");
|
||||
});
|
||||
it("errors on conflicting edge weights (backwards)", () => {
|
||||
const w1 = simpleWeights([], [["foo", 4, 4]]);
|
||||
const w2 = simpleWeights([], [["foo", 4, 5]]);
|
||||
expect(() => Weights.merge([w1, w2])).toThrowError("duplicate key");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user