mirror of https://gitee.com/bigwinds/arangodb
2074 lines
83 KiB
JavaScript
2074 lines
83 KiB
JavaScript
/*jslint indent: 2, nomen: true, maxlen: 100, white: true plusplus: true */
|
|
/*global beforeEach, afterEach, jasmine */
|
|
/*global runs, waitsFor */
|
|
/*global describe, it, expect, spyOn */
|
|
/*global window, eb, loadFixtures, document, console*/
|
|
/*global $, _, d3*/
|
|
/*global helper*/
|
|
/*global ModularityJoiner, WebWorkerWrapper*/
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief Graph functionality
|
|
///
|
|
/// @file
|
|
///
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
|
|
///
|
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|
/// you may not use this file except in compliance with the License.
|
|
/// You may obtain a copy of the License at
|
|
///
|
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
|
///
|
|
/// Unless required by applicable law or agreed to in writing, software
|
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
/// See the License for the specific language governing permissions and
|
|
/// limitations under the License.
|
|
///
|
|
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
|
///
|
|
/// @author Michael Hackstein
|
|
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
(function () {
|
|
"use strict";
|
|
|
|
describe('Modularity Joiner', function () {
|
|
|
|
beforeEach(function() {
|
|
this.addMatchers({
|
|
toContainNodes: function(ns) {
|
|
var com = this.actual,
|
|
check = true;
|
|
this.message = function() {
|
|
return "Expected " + com + " to contain " + ns;
|
|
};
|
|
if (com.length !== ns.length) {
|
|
return false;
|
|
}
|
|
_.each(ns, function(n) {
|
|
if(!_.contains(com, n)) {
|
|
check = false;
|
|
}
|
|
});
|
|
return check;
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('setup process', function() {
|
|
|
|
it('should not throw an error if mandatory information is given', function() {
|
|
expect(function() {
|
|
var s = new ModularityJoiner();
|
|
}).not.toThrow();
|
|
});
|
|
|
|
it('should be possible to create it as a worker', function() {
|
|
|
|
var called, created, error;
|
|
|
|
|
|
runs(function() {
|
|
error = "";
|
|
created = false;
|
|
called = false;
|
|
var n = [],
|
|
e = [],
|
|
cb = function(d) {
|
|
var data = d.data;
|
|
called = true;
|
|
if (data.cmd === "construct") {
|
|
created = data.result;
|
|
error = data.error;
|
|
}
|
|
},
|
|
w = new WebWorkerWrapper(ModularityJoiner, cb);
|
|
});
|
|
|
|
waitsFor(function() {
|
|
return called;
|
|
});
|
|
|
|
runs(function() {
|
|
expect(created).toBeTruthy();
|
|
expect(error).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
});
|
|
|
|
describe('setup correctly', function() {
|
|
|
|
var joiner,
|
|
nodes,
|
|
edges,
|
|
testNetFour;
|
|
|
|
beforeEach(function () {
|
|
nodes = [];
|
|
edges = [];
|
|
joiner = new ModularityJoiner();
|
|
testNetFour = function() {
|
|
helper.insertSimpleNodes(nodes, ["0", "1", "2", "3"]);
|
|
edges.push(helper.createSimpleEdge(nodes, 0, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 0, 3));
|
|
edges.push(helper.createSimpleEdge(nodes, 1, 2));
|
|
edges.push(helper.createSimpleEdge(nodes, 2, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 2, 3));
|
|
edges.push(helper.createSimpleEdge(nodes, 3, 0));
|
|
edges.push(helper.createSimpleEdge(nodes, 3, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 3, 2));
|
|
joiner.insertEdge("0", "1");
|
|
joiner.insertEdge("0", "3");
|
|
joiner.insertEdge("1", "2");
|
|
joiner.insertEdge("2", "1");
|
|
joiner.insertEdge("2", "3");
|
|
joiner.insertEdge("3", "0");
|
|
joiner.insertEdge("3", "1");
|
|
joiner.insertEdge("3", "2");
|
|
};
|
|
});
|
|
|
|
|
|
describe('getters', function() {
|
|
|
|
beforeEach(function() {
|
|
this.addMatchers({
|
|
toBeGetter: function() {
|
|
var func = joiner[this.actual];
|
|
if (!func) {
|
|
this.message = function() {
|
|
return "Expected " + this.actual + " to be defined.";
|
|
};
|
|
return false;
|
|
}
|
|
if ("function" !== typeof func) {
|
|
this.message = function() {
|
|
return "Expected " + this.actual + " to be a function.";
|
|
};
|
|
return false;
|
|
}
|
|
if (func.length !== 0) {
|
|
this.message = function() {
|
|
return "Expected " + this.actual + " to be a getter function.";
|
|
};
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
});
|
|
});
|
|
|
|
it('should offer the adjacency matrix', function() {
|
|
expect("getAdjacencyMatrix").toBeGetter();
|
|
});
|
|
|
|
it('should offer the heap', function() {
|
|
expect("getHeap").toBeGetter();
|
|
});
|
|
|
|
it('should offer the delta qs', function() {
|
|
expect("getDQ").toBeGetter();
|
|
});
|
|
|
|
it('should offer the degrees', function() {
|
|
expect("getDegrees").toBeGetter();
|
|
});
|
|
|
|
it('should offer the best join', function() {
|
|
expect("getBest").toBeGetter();
|
|
});
|
|
|
|
it('should offer the community list', function() {
|
|
expect("getCommunities").toBeGetter();
|
|
});
|
|
|
|
});
|
|
|
|
describe('checking the interface', function() {
|
|
|
|
it('should offer a function to insert an edge', function() {
|
|
expect(joiner.insertEdge).toBeDefined();
|
|
expect(joiner.insertEdge).toEqual(jasmine.any(Function));
|
|
expect(joiner.insertEdge.length).toEqual(2);
|
|
});
|
|
|
|
it('should offer a function to delete an edge', function() {
|
|
expect(joiner.deleteEdge).toBeDefined();
|
|
expect(joiner.deleteEdge).toEqual(jasmine.any(Function));
|
|
expect(joiner.deleteEdge.length).toEqual(2);
|
|
});
|
|
|
|
it('should offer a setup function', function() {
|
|
expect(joiner.setup).toBeDefined();
|
|
expect(joiner.setup).toEqual(jasmine.any(Function));
|
|
expect(joiner.setup.length).toEqual(0);
|
|
});
|
|
|
|
it('should offer a function to join two communities', function() {
|
|
expect(joiner.joinCommunity).toBeDefined();
|
|
expect(joiner.joinCommunity).toEqual(jasmine.any(Function));
|
|
expect(joiner.joinCommunity.length).toEqual(1);
|
|
});
|
|
|
|
it('should offer a function to identify a far away community', function() {
|
|
expect(joiner.getCommunity).toBeDefined();
|
|
expect(joiner.getCommunity).toEqual(jasmine.any(Function));
|
|
expect(joiner.getCommunity.length).toEqual(2);
|
|
});
|
|
|
|
});
|
|
|
|
describe('after setup', function() {
|
|
|
|
beforeEach(function() {
|
|
testNetFour();
|
|
joiner.setup();
|
|
});
|
|
|
|
describe('the adjacency matrix', function() {
|
|
|
|
it('should be created', function() {
|
|
expect(joiner.getAdjacencyMatrix()).toEqual({
|
|
"0": {
|
|
"1": 1,
|
|
"3": 1
|
|
},
|
|
"1": {
|
|
"2": 1
|
|
},
|
|
"2": {
|
|
"1": 1,
|
|
"3": 1
|
|
},
|
|
"3": {
|
|
"0": 1,
|
|
"1": 1,
|
|
"2": 1
|
|
}
|
|
});
|
|
});
|
|
|
|
it('should react to insert edge', function() {
|
|
joiner.insertEdge("a", "b");
|
|
|
|
expect(joiner.getAdjacencyMatrix()).toEqual({
|
|
"0": {
|
|
"1": 1,
|
|
"3": 1
|
|
},
|
|
"1": {
|
|
"2": 1
|
|
},
|
|
"2": {
|
|
"1": 1,
|
|
"3": 1
|
|
},
|
|
"3": {
|
|
"0": 1,
|
|
"1": 1,
|
|
"2": 1
|
|
},
|
|
"a": {
|
|
"b": 1
|
|
}
|
|
});
|
|
});
|
|
|
|
it('should react to delete edge', function() {
|
|
joiner.deleteEdge("0", "1");
|
|
|
|
expect(joiner.getAdjacencyMatrix()).toEqual({
|
|
"0": {
|
|
"3": 1
|
|
},
|
|
"1": {
|
|
"2": 1
|
|
},
|
|
"2": {
|
|
"1": 1,
|
|
"3": 1
|
|
},
|
|
"3": {
|
|
"0": 1,
|
|
"1": 1,
|
|
"2": 1
|
|
}
|
|
});
|
|
});
|
|
|
|
it('should remove empty lines on delete', function() {
|
|
joiner.deleteEdge("1", "2");
|
|
|
|
expect(joiner.getAdjacencyMatrix()).toEqual({
|
|
"0": {
|
|
"1": 1,
|
|
"3": 1
|
|
},
|
|
"2": {
|
|
"1": 1,
|
|
"3": 1
|
|
},
|
|
"3": {
|
|
"0": 1,
|
|
"1": 1,
|
|
"2": 1
|
|
}
|
|
});
|
|
});
|
|
|
|
it('should only remove one of the edges on delete', function() {
|
|
joiner.insertEdge("1", "2");
|
|
joiner.insertEdge("1", "2");
|
|
|
|
joiner.deleteEdge("1", "2");
|
|
expect(joiner.getAdjacencyMatrix()).toEqual({
|
|
"0": {
|
|
"1": 1,
|
|
"3": 1
|
|
},
|
|
"1": {
|
|
"2": 2
|
|
},
|
|
"2": {
|
|
"1": 1,
|
|
"3": 1
|
|
},
|
|
"3": {
|
|
"0": 1,
|
|
"1": 1,
|
|
"2": 1
|
|
}
|
|
});
|
|
});
|
|
|
|
});
|
|
|
|
describe('the degrees', function() {
|
|
|
|
var m, one, two, three, initDeg;
|
|
|
|
|
|
beforeEach(function() {
|
|
m = edges.length;
|
|
one = 1 / m;
|
|
two = 2 / m;
|
|
three = 3 / m;
|
|
initDeg = {
|
|
"0": {
|
|
_in: one,
|
|
_out: two
|
|
},
|
|
"1": {
|
|
_in: three,
|
|
_out: one
|
|
},
|
|
"2": {
|
|
_in: two,
|
|
_out: two
|
|
},
|
|
"3": {
|
|
_in: two,
|
|
_out: three
|
|
}
|
|
};
|
|
});
|
|
|
|
it('should initialy be populated', function() {
|
|
expect(joiner.getDegrees()).toEqual(initDeg);
|
|
});
|
|
|
|
|
|
it('should be updated after a joining step', function() {
|
|
var toJoin = joiner.getBest(),
|
|
expected = {};
|
|
//Make sure we join the right ones:
|
|
expect(toJoin.sID).toEqual("0");
|
|
expect(toJoin.lID).toEqual("3");
|
|
|
|
expected["0"] = {
|
|
_in: initDeg["0"]._in + initDeg["3"]._in,
|
|
_out: initDeg["0"]._out + initDeg["3"]._out
|
|
};
|
|
expected["1"] = initDeg["1"];
|
|
expected["2"] = initDeg["2"];
|
|
|
|
joiner.joinCommunity(toJoin);
|
|
|
|
expect(joiner.getDegrees()).toEqual(expected);
|
|
});
|
|
|
|
});
|
|
|
|
describe('the deltaQ', function() {
|
|
|
|
var m, zero, one, two, three, initDQ,
|
|
cleanDQ = function(dq) {
|
|
_.each(dq, function(list, s) {
|
|
_.each(list, function(v, t) {
|
|
if (v < 0) {
|
|
delete list[t];
|
|
}
|
|
});
|
|
if (_.isEmpty(list)) {
|
|
delete dq[s];
|
|
}
|
|
});
|
|
};
|
|
|
|
beforeEach(function() {
|
|
m = edges.length;
|
|
zero = {
|
|
_in: 1/m,
|
|
_out: 2/m
|
|
};
|
|
one = {
|
|
_in: 3/m,
|
|
_out: 1/m
|
|
};
|
|
two = {
|
|
_in: 2/m,
|
|
_out: 2/m
|
|
};
|
|
three = {
|
|
_in: 2/m,
|
|
_out: 3/m
|
|
};
|
|
initDQ = {
|
|
"0": {
|
|
"1": 1/m - zero._in * one._out - zero._out * one._in,
|
|
"2": - zero._in * two._out - zero._out * two._in,
|
|
"3": 2/m - zero._in * three._out - zero._out * three._in
|
|
},
|
|
"1": {
|
|
"2": 2/m - one._in * two._out - one._out * two._in,
|
|
"3": 1/m - one._in * three._out - one._out * three._in
|
|
},
|
|
"2": {
|
|
"3": 2/m - two._in * three._out - two._out * three._in
|
|
}
|
|
};
|
|
cleanDQ(initDQ);
|
|
});
|
|
|
|
it('should initialy be populated', function() {
|
|
expect(joiner.getDQ()).toEqual(initDQ);
|
|
});
|
|
|
|
it('should be updated after a joining step', function() {
|
|
var toJoin = joiner.getBest(),
|
|
expected = {};
|
|
//Make sure we join the right ones:
|
|
expect(toJoin.sID).toEqual("0");
|
|
expect(toJoin.lID).toEqual("3");
|
|
|
|
expected["0"] = {};
|
|
if (initDQ["0"]["1"] && initDQ["1"]["3"]) {
|
|
expected["0"]["1"] = initDQ["0"]["1"] + initDQ["1"]["3"];
|
|
}
|
|
if (initDQ["0"]["2"] && initDQ["2"]["3"]) {
|
|
expected["0"]["2"] = initDQ["0"]["2"] + initDQ["2"]["3"];
|
|
}
|
|
expected["1"] = {};
|
|
if (initDQ["1"]["2"]) {
|
|
expected["1"]["2"] = initDQ["1"]["2"];
|
|
}
|
|
cleanDQ(expected);
|
|
joiner.joinCommunity(toJoin);
|
|
expect(joiner.getDQ()).toEqual(expected);
|
|
});
|
|
|
|
it('should be ordered', function() {
|
|
this.addMatchers({
|
|
toBeOrdered: function() {
|
|
var dQ = this.actual,
|
|
notFailed = true,
|
|
msg = "The pointers: ";
|
|
_.each(dQ, function(list, pointer) {
|
|
_.each(list, function(val, target) {
|
|
if (target < pointer) {
|
|
notFailed = false;
|
|
msg += pointer + " -> " + target + ", ";
|
|
}
|
|
});
|
|
});
|
|
this.message = function() {
|
|
return msg + "are not correct";
|
|
};
|
|
return notFailed;
|
|
}
|
|
});
|
|
|
|
|
|
|
|
var firstID = nodes.length;
|
|
helper.insertSimpleNodes(nodes, ["9", "20", "10", "99", "12"]);
|
|
|
|
edges.push(helper.createSimpleEdge(nodes, 0, firstID));
|
|
joiner.insertEdge("0", "9");
|
|
edges.push(helper.createSimpleEdge(nodes, firstID, firstID + 1));
|
|
joiner.insertEdge("9", "20");
|
|
edges.push(helper.createSimpleEdge(nodes, firstID + 1, firstID + 2));
|
|
joiner.insertEdge("20", "10");
|
|
edges.push(helper.createSimpleEdge(nodes, firstID + 2, firstID + 3));
|
|
joiner.insertEdge("10", "99");
|
|
edges.push(helper.createSimpleEdge(nodes, firstID + 3, firstID + 4));
|
|
joiner.insertEdge("99", "12");
|
|
edges.push(helper.createSimpleEdge(nodes, firstID + 4, firstID));
|
|
joiner.insertEdge("12", "9");
|
|
edges.push(helper.createSimpleEdge(nodes, firstID + 3, firstID));
|
|
joiner.insertEdge("99", "9");
|
|
|
|
|
|
joiner.setup();
|
|
expect(joiner.getDQ()).toBeOrdered();
|
|
});
|
|
|
|
});
|
|
|
|
describe('the heap', function() {
|
|
|
|
var m, zero, one, two, three;
|
|
|
|
beforeEach(function() {
|
|
m = edges.length;
|
|
zero = {
|
|
_in: 1/m,
|
|
_out: 2/m
|
|
};
|
|
one = {
|
|
_in: 3/m,
|
|
_out: 1/m
|
|
};
|
|
two = {
|
|
_in: 2/m,
|
|
_out: 2/m
|
|
};
|
|
three = {
|
|
_in: 2/m,
|
|
_out: 3/m
|
|
};
|
|
});
|
|
|
|
it('should initialy by populated', function() {
|
|
expect(joiner.getHeap()).toEqual({
|
|
"0": "3",
|
|
"1": "2",
|
|
"2": "3"
|
|
});
|
|
});
|
|
|
|
it('should return the largest value', function() {
|
|
expect(joiner.getBest()).toEqual({
|
|
sID: "0",
|
|
lID: "3",
|
|
val: 2/m - zero._in * three._out - zero._out * three._in
|
|
});
|
|
});
|
|
|
|
it('should be updated after a join step', function() {
|
|
var toJoin = joiner.getBest(),
|
|
expected = {};
|
|
//Make sure we join the right ones:
|
|
expect(toJoin.sID).toEqual("0");
|
|
expect(toJoin.lID).toEqual("3");
|
|
|
|
joiner.joinCommunity(toJoin);
|
|
expect(joiner.getHeap()).toEqual({
|
|
"1": "2"
|
|
});
|
|
});
|
|
|
|
it('should return the largest value after a join step', function() {
|
|
var toJoin = joiner.getBest(),
|
|
expected = {};
|
|
//Make sure we join the right ones:
|
|
expect(toJoin.sID).toEqual("0");
|
|
expect(toJoin.lID).toEqual("3");
|
|
|
|
joiner.joinCommunity(toJoin);
|
|
|
|
expect(joiner.getBest()).toEqual({
|
|
sID: "1",
|
|
lID: "2",
|
|
val: 2/m - one._in * two._out - one._out * two._in
|
|
});
|
|
});
|
|
|
|
it('should return null for best if the value is 0 or worse', function() {
|
|
var toJoin = joiner.getBest();
|
|
//Make sure we join the right ones:
|
|
expect(toJoin.sID).toEqual("0");
|
|
expect(toJoin.lID).toEqual("3");
|
|
joiner.joinCommunity(toJoin);
|
|
|
|
toJoin = joiner.getBest();
|
|
//Make sure we join the right ones:
|
|
expect(toJoin.sID).toEqual("1");
|
|
expect(toJoin.lID).toEqual("2");
|
|
joiner.joinCommunity(toJoin);
|
|
expect(joiner.getBest()).toBeNull();
|
|
});
|
|
|
|
});
|
|
|
|
describe('communities', function() {
|
|
|
|
it('should be able to get the communities', function() {
|
|
// No communities yet. Should not return single nodes.
|
|
expect(joiner.getCommunities()).toEqual({});
|
|
});
|
|
|
|
it('should be able to join two communities', function() {
|
|
var toJoin = joiner.getBest(),
|
|
joinVal = toJoin.val,
|
|
lowId = toJoin.sID,
|
|
highId = toJoin.lID,
|
|
expected = {},
|
|
m = edges.length,
|
|
zero = {
|
|
_in: 1/m,
|
|
_out: 2/m
|
|
},
|
|
one = {
|
|
_in: 3/m,
|
|
_out: 1/m
|
|
},
|
|
two = {
|
|
_in: 2/m,
|
|
_out: 2/m
|
|
},
|
|
three = {
|
|
_in: 2/m,
|
|
_out: 3/m
|
|
};
|
|
expected[lowId] = {
|
|
nodes: [
|
|
lowId,
|
|
highId
|
|
],
|
|
q: joinVal
|
|
};
|
|
expect(toJoin).toEqual({
|
|
sID: "0",
|
|
lID: "3",
|
|
val: 2/m - zero._in * three._out - zero._out * three._in
|
|
});
|
|
joiner.joinCommunity(toJoin);
|
|
expect(joiner.getCommunities()).toEqual(expected);
|
|
});
|
|
|
|
});
|
|
|
|
describe('checking multiple executions', function() {
|
|
|
|
it('should be able to recompute the joining', function() {
|
|
var best = joiner.getBest(),
|
|
first,
|
|
firstStringified,
|
|
second,
|
|
secondStringified;
|
|
best = joiner.getBest();
|
|
while (best !== null) {
|
|
joiner.joinCommunity(best);
|
|
best = joiner.getBest();
|
|
}
|
|
first = joiner.getCommunities();
|
|
firstStringified = JSON.stringify(first);
|
|
joiner.setup();
|
|
best = joiner.getBest();
|
|
while (best !== null) {
|
|
joiner.joinCommunity(best);
|
|
best = joiner.getBest();
|
|
}
|
|
second = joiner.getCommunities();
|
|
secondStringified = JSON.stringify(second);
|
|
expect(JSON.stringify(first)).toEqual(firstStringified);
|
|
expect(secondStringified).toEqual(firstStringified);
|
|
});
|
|
|
|
});
|
|
|
|
describe('checking massively insertion/deletion of edges', function() {
|
|
|
|
it('should be possible to keep a consistent adj. matrix', function() {
|
|
|
|
joiner.deleteEdge("0", "1");
|
|
joiner.deleteEdge("0", "3");
|
|
joiner.deleteEdge("1", "2");
|
|
joiner.deleteEdge("2", "1");
|
|
joiner.deleteEdge("2", "3");
|
|
joiner.deleteEdge("3", "0");
|
|
joiner.deleteEdge("3", "1");
|
|
joiner.deleteEdge("3", "2");
|
|
|
|
expect(joiner.getAdjacencyMatrix()).toEqual({});
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe('checking direct community identification', function() {
|
|
|
|
it('should be able to identify an obvious community', function() {
|
|
helper.insertSimpleNodes(nodes, ["0", "1", "2", "3", "4"]);
|
|
edges.push(helper.createSimpleEdge(nodes, 0, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 0, 2));
|
|
edges.push(helper.createSimpleEdge(nodes, 0, 3));
|
|
edges.push(helper.createSimpleEdge(nodes, 3, 4));
|
|
|
|
_.each(edges, function(e) {
|
|
joiner.insertEdge(e.source._id, e.target._id);
|
|
});
|
|
|
|
var com = joiner.getCommunity(3, nodes[4]._id);
|
|
expect(com).toContainNodes(["0", "1", "2"]);
|
|
});
|
|
|
|
it('should prefer cliques as a community over an equal sized other group', function() {
|
|
helper.insertSimpleNodes(nodes, ["0", "1", "2", "3", "4", "5", "6", "7", "8"]);
|
|
helper.insertClique(nodes, edges, [0, 1, 2, 3]);
|
|
edges.push(helper.createSimpleEdge(nodes, 4, 3));
|
|
edges.push(helper.createSimpleEdge(nodes, 4, 5));
|
|
edges.push(helper.createSimpleEdge(nodes, 5, 6));
|
|
edges.push(helper.createSimpleEdge(nodes, 5, 7));
|
|
edges.push(helper.createSimpleEdge(nodes, 5, 8));
|
|
|
|
_.each(edges, function(e) {
|
|
joiner.insertEdge(e.source._id, e.target._id);
|
|
});
|
|
|
|
var com = joiner.getCommunity(6, nodes[4]._id);
|
|
expect(com).toContainNodes(["0", "1", "2", "3"]);
|
|
});
|
|
|
|
it('should not return a close group if there is an alternative', function() {
|
|
helper.insertSimpleNodes(nodes, ["0", "1", "2", "3", "4", "5", "6", "7", "8"]);
|
|
helper.insertClique(nodes, edges, [0, 1, 2]);
|
|
helper.insertClique(nodes, edges, [3, 4, 5]);
|
|
helper.insertClique(nodes, edges, [6, 7, 8]);
|
|
edges.push(helper.createSimpleEdge(nodes, 3, 2));
|
|
edges.push(helper.createSimpleEdge(nodes, 5, 6));
|
|
|
|
_.each(edges, function(e) {
|
|
joiner.insertEdge(e.source._id, e.target._id);
|
|
});
|
|
var com = joiner.getCommunity(6, nodes[3]._id);
|
|
expect(com).toContainNodes(["6", "7", "8"]);
|
|
});
|
|
/*
|
|
it('should also take the best community if no focus is given', function() {
|
|
helper.insertSimpleNodes(nodes, ["0", "1", "2", "3", "4", "5", "6", "7"]);
|
|
helper.insertClique(nodes, edges, [0, 1, 2]);
|
|
edges.push(helper.createSimpleEdge(nodes, 3, 2));
|
|
edges.push(helper.createSimpleEdge(nodes, 3, 4));
|
|
edges.push(helper.createSimpleEdge(nodes, 4, 5));
|
|
edges.push(helper.createSimpleEdge(nodes, 5, 6));
|
|
edges.push(helper.createSimpleEdge(nodes, 5, 7));
|
|
|
|
_.each(edges, function(e) {
|
|
joiner.insertEdge(e.source._id, e.target._id);
|
|
});
|
|
|
|
var com = joiner.getCommunity(6);
|
|
expect(com).toContainNodes(["0", "1", "2"]);
|
|
});
|
|
*/
|
|
});
|
|
|
|
describe('checking the zachary karate club', function() {
|
|
|
|
beforeEach(function() {
|
|
// This is the Zachary Karate Club Network
|
|
helper.insertSimpleNodes(nodes, [
|
|
"0", // Just Temporary node, as the orig is counting from 1 instead of 0
|
|
"1","2","3","4","5","6","7","8","9","10",
|
|
"11","12","13","14","15","16","17","18","19","20",
|
|
"21","22","23","24","25","26","27","28","29","30",
|
|
"31","32","33","34"
|
|
]);
|
|
edges.push(helper.createSimpleEdge(nodes, 2, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 3, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 3, 2));
|
|
edges.push(helper.createSimpleEdge(nodes, 4, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 4, 2));
|
|
edges.push(helper.createSimpleEdge(nodes, 4, 3));
|
|
edges.push(helper.createSimpleEdge(nodes, 5, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 6, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 7, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 7, 5));
|
|
edges.push(helper.createSimpleEdge(nodes, 7, 6));
|
|
edges.push(helper.createSimpleEdge(nodes, 8, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 8, 2));
|
|
edges.push(helper.createSimpleEdge(nodes, 8, 3));
|
|
edges.push(helper.createSimpleEdge(nodes, 8, 4));
|
|
edges.push(helper.createSimpleEdge(nodes, 9, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 9, 3));
|
|
edges.push(helper.createSimpleEdge(nodes, 10, 3));
|
|
edges.push(helper.createSimpleEdge(nodes, 11, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 11, 5));
|
|
edges.push(helper.createSimpleEdge(nodes, 11, 6));
|
|
edges.push(helper.createSimpleEdge(nodes, 12, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 13, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 13, 4));
|
|
edges.push(helper.createSimpleEdge(nodes, 14, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 14, 2));
|
|
edges.push(helper.createSimpleEdge(nodes, 14, 3));
|
|
edges.push(helper.createSimpleEdge(nodes, 14, 4));
|
|
edges.push(helper.createSimpleEdge(nodes, 17, 6));
|
|
edges.push(helper.createSimpleEdge(nodes, 17, 7));
|
|
edges.push(helper.createSimpleEdge(nodes, 18, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 18, 2));
|
|
edges.push(helper.createSimpleEdge(nodes, 20, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 20, 2));
|
|
edges.push(helper.createSimpleEdge(nodes, 22, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 22, 2));
|
|
edges.push(helper.createSimpleEdge(nodes, 26, 24));
|
|
edges.push(helper.createSimpleEdge(nodes, 26, 25));
|
|
edges.push(helper.createSimpleEdge(nodes, 28, 3));
|
|
edges.push(helper.createSimpleEdge(nodes, 28, 24));
|
|
edges.push(helper.createSimpleEdge(nodes, 28, 25));
|
|
edges.push(helper.createSimpleEdge(nodes, 29, 3));
|
|
edges.push(helper.createSimpleEdge(nodes, 30, 24));
|
|
edges.push(helper.createSimpleEdge(nodes, 30, 27));
|
|
edges.push(helper.createSimpleEdge(nodes, 31, 2));
|
|
edges.push(helper.createSimpleEdge(nodes, 31, 9));
|
|
edges.push(helper.createSimpleEdge(nodes, 32, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 32, 25));
|
|
edges.push(helper.createSimpleEdge(nodes, 32, 26));
|
|
edges.push(helper.createSimpleEdge(nodes, 32, 29));
|
|
edges.push(helper.createSimpleEdge(nodes, 33, 3));
|
|
edges.push(helper.createSimpleEdge(nodes, 33, 9));
|
|
edges.push(helper.createSimpleEdge(nodes, 33, 15));
|
|
edges.push(helper.createSimpleEdge(nodes, 33, 16));
|
|
edges.push(helper.createSimpleEdge(nodes, 33, 19));
|
|
edges.push(helper.createSimpleEdge(nodes, 33, 21));
|
|
edges.push(helper.createSimpleEdge(nodes, 33, 23));
|
|
edges.push(helper.createSimpleEdge(nodes, 33, 24));
|
|
edges.push(helper.createSimpleEdge(nodes, 33, 30));
|
|
edges.push(helper.createSimpleEdge(nodes, 33, 31));
|
|
edges.push(helper.createSimpleEdge(nodes, 33, 32));
|
|
edges.push(helper.createSimpleEdge(nodes, 34, 9));
|
|
edges.push(helper.createSimpleEdge(nodes, 34, 10));
|
|
edges.push(helper.createSimpleEdge(nodes, 34, 14));
|
|
edges.push(helper.createSimpleEdge(nodes, 34, 15));
|
|
edges.push(helper.createSimpleEdge(nodes, 34, 16));
|
|
edges.push(helper.createSimpleEdge(nodes, 34, 19));
|
|
edges.push(helper.createSimpleEdge(nodes, 34, 20));
|
|
edges.push(helper.createSimpleEdge(nodes, 34, 21));
|
|
edges.push(helper.createSimpleEdge(nodes, 34, 23));
|
|
edges.push(helper.createSimpleEdge(nodes, 34, 24));
|
|
edges.push(helper.createSimpleEdge(nodes, 34, 27));
|
|
edges.push(helper.createSimpleEdge(nodes, 34, 28));
|
|
edges.push(helper.createSimpleEdge(nodes, 34, 29));
|
|
edges.push(helper.createSimpleEdge(nodes, 34, 30));
|
|
edges.push(helper.createSimpleEdge(nodes, 34, 31));
|
|
edges.push(helper.createSimpleEdge(nodes, 34, 32));
|
|
edges.push(helper.createSimpleEdge(nodes, 34, 33));
|
|
nodes.shift(1); //Remove the temporary node;
|
|
|
|
_.each(edges, function(e) {
|
|
joiner.insertEdge(e.source._id, e.target._id);
|
|
});
|
|
|
|
joiner.setup();
|
|
|
|
});
|
|
|
|
it('should never have duplicates in communities', function() {
|
|
this.addMatchers({
|
|
toNotContainDuplicates: function() {
|
|
var comms = this.actual,
|
|
duplicate = [],
|
|
found = {},
|
|
failed = false;
|
|
_.each(comms, function (v) {
|
|
_.each(v.nodes, function (i) {
|
|
if (found[i]) {
|
|
failed = true;
|
|
duplicate.push(i);
|
|
} else {
|
|
found[i] = true;
|
|
}
|
|
});
|
|
});
|
|
this.message = function() {
|
|
var outComms = comms;
|
|
_.each(outComms, function(o) {
|
|
o.nodes = _.filter(o.nodes, function(n) {
|
|
return _.contains(duplicate, n);
|
|
});
|
|
});
|
|
return "Found duplicate nodes [" + duplicate
|
|
+ "] in communities: " + JSON.stringify(outComms);
|
|
};
|
|
return !failed;
|
|
}
|
|
});
|
|
var best = joiner.getBest();
|
|
while (best !== null) {
|
|
joiner.joinCommunity(best);
|
|
best = joiner.getBest();
|
|
expect(joiner.getCommunities()).toNotContainDuplicates();
|
|
}
|
|
});
|
|
|
|
it('should be able to find communities', function() {
|
|
/////////////////////////////////////////////////////
|
|
/// correct acc to: NMCM09 //
|
|
/// Red: //
|
|
/// 21,23,24,19,27,16,30,33,34,29,15,9,31 //
|
|
/// White: //
|
|
/// 25, 26, 28, 32 //
|
|
/// Green: //
|
|
/// 5, 6, 7, 11, 17 //
|
|
/// Blue: //
|
|
/// 1, 2, 3, 4, 10, 14, 20, 22, 18, 13, 12 //
|
|
/////////////////////////////////////////////////////
|
|
|
|
this.addMatchers({
|
|
toContainKarateClubCommunities: function() {
|
|
var c1 = [
|
|
"10", "15", "16", "19", "21", "23",
|
|
"30", "33", "34"
|
|
].sort().join(),
|
|
c2 = ["1", "12", "13", "14", "18", "2", "20", "22", "3", "4", "8"].sort().join(),
|
|
c3 = ["11", "17", "5", "6", "7"].sort().join(),
|
|
c4 = ["24", "25", "26", "28", "29", "32"].sort().join(),
|
|
swap = ["9", "27", "31"],
|
|
comms = this.actual,
|
|
failed = false,
|
|
msg = "Found incorrect: ";
|
|
_.each(comms, function(o) {
|
|
var check = o.nodes;
|
|
_.each(swap, function (s) {
|
|
var index = _.indexOf(check, s);
|
|
if (index > -1) {
|
|
check = _.without(check, s);
|
|
swap = _.without(swap, s);
|
|
}
|
|
});
|
|
check = check.sort().join();
|
|
switch (check) {
|
|
case c1:
|
|
c1 = "";
|
|
break;
|
|
case c2:
|
|
c2 = "";
|
|
break;
|
|
case c3:
|
|
c3 = "";
|
|
break;
|
|
case c4:
|
|
c4 = "";
|
|
break;
|
|
default:
|
|
msg += "[" + check + "] ";
|
|
failed = true;
|
|
}
|
|
return;
|
|
});
|
|
this.message = function() {
|
|
var notFound = "";
|
|
if (c1 !== "") {
|
|
notFound += "[" + c1 + "] ";
|
|
}
|
|
if (c2 !== "") {
|
|
notFound += "[" + c2 + "] ";
|
|
}
|
|
if (c3 !== "") {
|
|
notFound += "[" + c3 + "] ";
|
|
}
|
|
if (c4 !== "") {
|
|
notFound += "[" + c4 + "] ";
|
|
}
|
|
if (swap.length > 0) {
|
|
notFound += "[" + swap.join() + "] ";
|
|
}
|
|
return msg + " and did not find: " + notFound;
|
|
};
|
|
return !failed;
|
|
}
|
|
});
|
|
var best = joiner.getBest();
|
|
while (best !== null) {
|
|
joiner.joinCommunity(best);
|
|
best = joiner.getBest();
|
|
}
|
|
expect(joiner.getCommunities()).toContainKarateClubCommunities();
|
|
});
|
|
|
|
});
|
|
|
|
describe('checking consistency after join', function() {
|
|
|
|
beforeEach(function() {
|
|
this.addMatchers({
|
|
toBeOrdered: function() {
|
|
var dQ = this.actual,
|
|
notFailed = true,
|
|
msg = "In dQ the pointers: ";
|
|
_.each(dQ, function(list, pointer) {
|
|
_.each(list, function(val, target) {
|
|
if (target < pointer) {
|
|
notFailed = false;
|
|
msg += pointer + " -> " + target + ", ";
|
|
}
|
|
});
|
|
});
|
|
this.message = function() {
|
|
return msg + "are not correct";
|
|
};
|
|
return notFailed;
|
|
},
|
|
|
|
toFulfillHeapConstraint: function(joined) {
|
|
var heap = this.actual.getHeap(),
|
|
high = joined.lID;
|
|
this.message = function() {
|
|
return "The heap " + _.keys(heap) + " should not contain " + high;
|
|
};
|
|
return _.isUndefined(heap[high]);
|
|
},
|
|
toFulfillDQConstraint: function(joined) {
|
|
var dQ = this.actual.getDQ(),
|
|
high = joined.lID;
|
|
this.message = function() {
|
|
return "The delta Q " + _.keys(dQ) + " should not contain " + high;
|
|
};
|
|
return _.isUndefined(dQ[high]);
|
|
},
|
|
toBeDefinedInHeapIffInDQ: function(testee) {
|
|
var id = this.actual,
|
|
dQ = testee.getDQ(),
|
|
heap = testee.getHeap();
|
|
if (_.isUndefined(dQ[id])) {
|
|
this.message = id + " is defined on heap but not on dQ";
|
|
return _.isUndefined(heap[id]);
|
|
}
|
|
this.message = id + " is defined on dQ but not on heap";
|
|
return !_.isUndefined(heap[id]);
|
|
},
|
|
toFulfillCommunityInclusionConstraint: function(joined) {
|
|
var comms = this.actual.getCommunities(),
|
|
low = joined.sID,
|
|
high = joined.lID;
|
|
if (_.isUndefined(comms[low])) {
|
|
this.message = function() {
|
|
return "The lower ID " + low + " is no pointer to a community";
|
|
};
|
|
return false;
|
|
}
|
|
this.message = function() {
|
|
return "The community " + comms[low].nodes + " should contain " + high;
|
|
};
|
|
return _.contains(comms[low].nodes, high);
|
|
},
|
|
|
|
toFulfillCommunityPointerConstraint: function() {
|
|
var comms = this.actual.getCommunities(),
|
|
notFailed = true,
|
|
msg = "In communities the pointers: ";
|
|
_.each(comms, function(list, pointer) {
|
|
var ns = list.nodes;
|
|
if (ns[0] !== pointer) {
|
|
notFailed = false;
|
|
msg += pointer + " -first-> " + ns[0] + ", ";
|
|
}
|
|
_.each(ns, function(id) {
|
|
if (id < pointer) {
|
|
notFailed = false;
|
|
msg += pointer + " -> " + id + ", ";
|
|
}
|
|
});
|
|
});
|
|
this.message = function () {
|
|
return msg + "are not correct";
|
|
};
|
|
return notFailed;
|
|
},
|
|
|
|
toNotContainAnyJoinedNode: function() {
|
|
var comms = this.actual.getCommunities(),
|
|
dQ = this.actual.getDQ(),
|
|
forbidden = [],
|
|
msg = "Nodes: ",
|
|
notFailed = true;
|
|
_.each(comms, function(list) {
|
|
var reducedList = list.nodes.slice();
|
|
reducedList.shift(1);
|
|
forbidden = forbidden.concat(reducedList);
|
|
});
|
|
_.each(forbidden, function (id) {
|
|
if (!_.isUndefined(dQ[id])) {
|
|
notFailed = false;
|
|
msg += id + ", ";
|
|
}
|
|
});
|
|
this.message = function() {
|
|
return msg + "should not be contained in dQ";
|
|
};
|
|
return notFailed;
|
|
|
|
},
|
|
|
|
toBeConsistent: function(joined) {
|
|
var testee = this.actual;
|
|
expect(testee).toFulfillDQConstraint(joined);
|
|
expect(testee).toFulfillHeapConstraint(joined);
|
|
expect(joined.sID).toBeDefinedInHeapIffInDQ(testee);
|
|
expect(testee).toFulfillCommunityInclusionConstraint(joined);
|
|
expect(testee).toNotContainAnyJoinedNode();
|
|
expect(testee).toFulfillCommunityPointerConstraint();
|
|
|
|
return true;
|
|
},
|
|
|
|
toContainALowerAndAHigherID: function() {
|
|
var toJoin = this.actual;
|
|
this.message = function() {
|
|
return toJoin.sID + " shold be lower than " + toJoin.lID;
|
|
};
|
|
return toJoin.sID < toJoin.lID;
|
|
}
|
|
|
|
});
|
|
});
|
|
|
|
it('for a larger network', function() {
|
|
var i, best,
|
|
step = 0,
|
|
nodeCount = 20;
|
|
helper.insertNSimpleNodes(nodes, nodeCount);
|
|
helper.insertClique(nodes, edges, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
for (i = 11; i < nodeCount; i++) {
|
|
edges.push(helper.createSimpleEdge(nodes, i - 1, i));
|
|
edges.push(helper.createSimpleEdge(nodes, i, i - 2));
|
|
}
|
|
joiner.setup();
|
|
best = joiner.getBest();
|
|
while (best !== null) {
|
|
expect(best).toContainALowerAndAHigherID();
|
|
joiner.joinCommunity(best);
|
|
expect(joiner).toBeConsistent(best, step);
|
|
best = joiner.getBest();
|
|
step++;
|
|
}
|
|
});
|
|
|
|
});
|
|
/*
|
|
describe('checking large networks', function() {
|
|
|
|
it('should be able to handle 1000 nodes', function() {
|
|
var start = (new Date()).getTime(),
|
|
i,
|
|
best,
|
|
nodeCount = 1000,
|
|
diff;
|
|
helper.insertNSimpleNodes(nodes, nodeCount);
|
|
helper.insertClique(nodes, edges, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
for (i = 11; i < nodeCount; i++) {
|
|
edges.push(helper.createSimpleEdge(nodes, i - 1, i));
|
|
edges.push(helper.createSimpleEdge(nodes, i, i - 2));
|
|
}
|
|
_.each(edges, function(e) {
|
|
joiner.insertEdge(e.source._id, e.target._id);
|
|
});
|
|
diff = (new Date()).getTime() - start;
|
|
console.log("Runtime Fill:", diff, "ms");
|
|
start = (new Date()).getTime();
|
|
joiner.setup();
|
|
diff = (new Date()).getTime() - start;
|
|
console.log("Runtime Setup:", diff, "ms");
|
|
start = (new Date()).getTime();
|
|
best = joiner.getBest();
|
|
while (best !== null) {
|
|
joiner.joinCommunity(best);
|
|
best = joiner.getBest();
|
|
}
|
|
diff = (new Date()).getTime() - start;
|
|
console.log("Runtime Compute:", diff, "ms");
|
|
});
|
|
|
|
// This is the max. number of nodes for the admin UI
|
|
// However the format is realy unlikely in the adminUI
|
|
|
|
it('should be able to handle 3000 nodes', function() {
|
|
var start = (new Date()).getTime(),
|
|
i, best, nodeCount = 3000, diff;
|
|
helper.insertNSimpleNodes(nodes, nodeCount);
|
|
helper.insertClique(nodes, edges, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
for (i = 11; i < nodeCount; i++) {
|
|
edges.push(helper.createSimpleEdge(nodes, i - 1, i));
|
|
edges.push(helper.createSimpleEdge(nodes, i, i - 2));
|
|
}
|
|
_.each(edges, function(e) {
|
|
joiner.insertEdge(e.source._id, e.target._id);
|
|
});
|
|
diff = (new Date()).getTime() - start;
|
|
console.log("Runtime Fill:", diff, "ms");
|
|
start = (new Date()).getTime();
|
|
joiner.setup();
|
|
diff = (new Date()).getTime() - start;
|
|
console.log("Runtime Setup:", diff, "ms");
|
|
start = (new Date()).getTime();
|
|
best = joiner.getBest();
|
|
while (best !== null) {
|
|
joiner.joinCommunity(best);
|
|
best = joiner.getBest();
|
|
}
|
|
diff = (new Date()).getTime() - start;
|
|
|
|
console.log("Runtime Compute:", diff, "ms");
|
|
});
|
|
|
|
// This is what we expect in the Admin UI
|
|
it('should be able to handle few large satelites', function() {
|
|
var start = (new Date()).getTime(),
|
|
i,
|
|
best,
|
|
diff,
|
|
s0 = helper.insertSatelite(nodes, edges, 0, 500),
|
|
s1 = helper.insertSatelite(nodes, edges, 1, 300),
|
|
s2 = helper.insertSatelite(nodes, edges, 2, 313),
|
|
s3 = helper.insertSatelite(nodes, edges, 3, 461),
|
|
s4 = helper.insertSatelite(nodes, edges, 4, 251),
|
|
s5 = helper.insertSatelite(nodes, edges, 5, 576),
|
|
s6 = helper.insertSatelite(nodes, edges, 6, 126),
|
|
s7 = helper.insertSatelite(nodes, edges, 7, 231),
|
|
s8 = helper.insertSatelite(nodes, edges, 8, 50),
|
|
s9 = helper.insertSatelite(nodes, edges, 9, 70),
|
|
s10 = helper.insertSatelite(nodes, edges, 10, 111);
|
|
edges.push(helper.createSimpleEdge(nodes, s0, s1));
|
|
edges.push(helper.createSimpleEdge(nodes, s0, s2));
|
|
edges.push(helper.createSimpleEdge(nodes, s0, s3));
|
|
edges.push(helper.createSimpleEdge(nodes, s0, s4));
|
|
edges.push(helper.createSimpleEdge(nodes, s1, s0));
|
|
edges.push(helper.createSimpleEdge(nodes, s1, s5));
|
|
edges.push(helper.createSimpleEdge(nodes, s1, s6));
|
|
edges.push(helper.createSimpleEdge(nodes, s2, s1));
|
|
edges.push(helper.createSimpleEdge(nodes, s3, s7));
|
|
edges.push(helper.createSimpleEdge(nodes, s3, s8));
|
|
edges.push(helper.createSimpleEdge(nodes, s4, s0));
|
|
edges.push(helper.createSimpleEdge(nodes, s4, s8));
|
|
edges.push(helper.createSimpleEdge(nodes, s4, s9));
|
|
edges.push(helper.createSimpleEdge(nodes, s5, s2));
|
|
edges.push(helper.createSimpleEdge(nodes, s5, s6));
|
|
edges.push(helper.createSimpleEdge(nodes, s5, s10));
|
|
edges.push(helper.createSimpleEdge(nodes, s6, s5));
|
|
edges.push(helper.createSimpleEdge(nodes, s7, s5));
|
|
edges.push(helper.createSimpleEdge(nodes, s7, s6));
|
|
edges.push(helper.createSimpleEdge(nodes, s8, s0));
|
|
edges.push(helper.createSimpleEdge(nodes, s8, s2));
|
|
edges.push(helper.createSimpleEdge(nodes, s8, s4));
|
|
edges.push(helper.createSimpleEdge(nodes, s8, s6));
|
|
edges.push(helper.createSimpleEdge(nodes, s9, s8));
|
|
edges.push(helper.createSimpleEdge(nodes, s9, s10));
|
|
edges.push(helper.createSimpleEdge(nodes, s10, s1));
|
|
edges.push(helper.createSimpleEdge(nodes, s10, s9));
|
|
_.each(edges, function(e) {
|
|
joiner.insertEdge(e.source._id, e.target._id);
|
|
});
|
|
|
|
diff = (new Date()).getTime() - start;
|
|
console.log("Runtime Fill:", diff, "ms");
|
|
start = (new Date()).getTime();
|
|
joiner.setup();
|
|
diff = (new Date()).getTime() - start;
|
|
console.log("Runtime Setup:", diff, "ms");
|
|
start = (new Date()).getTime();
|
|
best = joiner.getBest();
|
|
while (best !== null) {
|
|
joiner.joinCommunity(best);
|
|
best = joiner.getBest();
|
|
}
|
|
diff = (new Date()).getTime() - start;
|
|
|
|
console.log("Runtime Compute:", diff, "ms");
|
|
});
|
|
|
|
it('should be able to handle many small satelites', function() {
|
|
var start = (new Date()).getTime(),
|
|
i,
|
|
best,
|
|
diff,
|
|
// This test network has been randomly generated.
|
|
// Each Satelite center has 20-100 children
|
|
// And has an edge to 3 - 13 centers
|
|
|
|
s0 = helper.insertSatelite(nodes, edges, 0, 22),
|
|
s1 = helper.insertSatelite(nodes, edges, 1, 72),
|
|
s2 = helper.insertSatelite(nodes, edges, 2, 76),
|
|
s3 = helper.insertSatelite(nodes, edges, 3, 68),
|
|
s4 = helper.insertSatelite(nodes, edges, 4, 64),
|
|
s5 = helper.insertSatelite(nodes, edges, 5, 46),
|
|
s6 = helper.insertSatelite(nodes, edges, 6, 24),
|
|
s7 = helper.insertSatelite(nodes, edges, 7, 98),
|
|
s8 = helper.insertSatelite(nodes, edges, 8, 84),
|
|
s9 = helper.insertSatelite(nodes, edges, 9, 93),
|
|
s10 = helper.insertSatelite(nodes, edges, 10, 79),
|
|
s11 = helper.insertSatelite(nodes, edges, 11, 58),
|
|
s12 = helper.insertSatelite(nodes, edges, 12, 98),
|
|
s13 = helper.insertSatelite(nodes, edges, 13, 64),
|
|
s14 = helper.insertSatelite(nodes, edges, 14, 62),
|
|
s15 = helper.insertSatelite(nodes, edges, 15, 56),
|
|
s16 = helper.insertSatelite(nodes, edges, 16, 63),
|
|
s17 = helper.insertSatelite(nodes, edges, 17, 83),
|
|
s18 = helper.insertSatelite(nodes, edges, 18, 98),
|
|
s19 = helper.insertSatelite(nodes, edges, 19, 29),
|
|
s20 = helper.insertSatelite(nodes, edges, 20, 50),
|
|
s21 = helper.insertSatelite(nodes, edges, 21, 62),
|
|
s22 = helper.insertSatelite(nodes, edges, 22, 20),
|
|
s23 = helper.insertSatelite(nodes, edges, 23, 30),
|
|
s24 = helper.insertSatelite(nodes, edges, 24, 50),
|
|
s25 = helper.insertSatelite(nodes, edges, 25, 55),
|
|
s26 = helper.insertSatelite(nodes, edges, 26, 41),
|
|
s27 = helper.insertSatelite(nodes, edges, 27, 60),
|
|
s28 = helper.insertSatelite(nodes, edges, 28, 62),
|
|
s29 = helper.insertSatelite(nodes, edges, 29, 91),
|
|
s30 = helper.insertSatelite(nodes, edges, 30, 59),
|
|
s31 = helper.insertSatelite(nodes, edges, 31, 48),
|
|
s32 = helper.insertSatelite(nodes, edges, 32, 76),
|
|
s33 = helper.insertSatelite(nodes, edges, 33, 88),
|
|
s34 = helper.insertSatelite(nodes, edges, 34, 92),
|
|
s35 = helper.insertSatelite(nodes, edges, 35, 87),
|
|
s36 = helper.insertSatelite(nodes, edges, 36, 65),
|
|
s37 = helper.insertSatelite(nodes, edges, 37, 80),
|
|
s38 = helper.insertSatelite(nodes, edges, 38, 28),
|
|
s39 = helper.insertSatelite(nodes, edges, 39, 33),
|
|
s40 = helper.insertSatelite(nodes, edges, 40, 86),
|
|
s41 = helper.insertSatelite(nodes, edges, 41, 81),
|
|
s42 = helper.insertSatelite(nodes, edges, 42, 26),
|
|
s43 = helper.insertSatelite(nodes, edges, 43, 57),
|
|
s44 = helper.insertSatelite(nodes, edges, 44, 61),
|
|
s45 = helper.insertSatelite(nodes, edges, 45, 47),
|
|
s46 = helper.insertSatelite(nodes, edges, 46, 47),
|
|
s47 = helper.insertSatelite(nodes, edges, 47, 33);
|
|
edges.push(helper.createSimpleEdge(nodes, s0, s44));
|
|
edges.push(helper.createSimpleEdge(nodes, s0, s47));
|
|
edges.push(helper.createSimpleEdge(nodes, s0, s3));
|
|
edges.push(helper.createSimpleEdge(nodes, s0, s39));
|
|
edges.push(helper.createSimpleEdge(nodes, s0, s8));
|
|
edges.push(helper.createSimpleEdge(nodes, s0, s21));
|
|
edges.push(helper.createSimpleEdge(nodes, s1, s36));
|
|
edges.push(helper.createSimpleEdge(nodes, s1, s43));
|
|
edges.push(helper.createSimpleEdge(nodes, s1, s43));
|
|
edges.push(helper.createSimpleEdge(nodes, s1, s40));
|
|
edges.push(helper.createSimpleEdge(nodes, s1, s39));
|
|
edges.push(helper.createSimpleEdge(nodes, s1, s44));
|
|
edges.push(helper.createSimpleEdge(nodes, s2, s32));
|
|
edges.push(helper.createSimpleEdge(nodes, s2, s10));
|
|
edges.push(helper.createSimpleEdge(nodes, s2, s26));
|
|
edges.push(helper.createSimpleEdge(nodes, s2, s39));
|
|
edges.push(helper.createSimpleEdge(nodes, s2, s43));
|
|
edges.push(helper.createSimpleEdge(nodes, s2, s42));
|
|
edges.push(helper.createSimpleEdge(nodes, s2, s16));
|
|
edges.push(helper.createSimpleEdge(nodes, s2, s7));
|
|
edges.push(helper.createSimpleEdge(nodes, s2, s3));
|
|
edges.push(helper.createSimpleEdge(nodes, s3, s8));
|
|
edges.push(helper.createSimpleEdge(nodes, s3, s33));
|
|
edges.push(helper.createSimpleEdge(nodes, s3, s9));
|
|
edges.push(helper.createSimpleEdge(nodes, s3, s18));
|
|
edges.push(helper.createSimpleEdge(nodes, s3, s18));
|
|
edges.push(helper.createSimpleEdge(nodes, s3, s6));
|
|
edges.push(helper.createSimpleEdge(nodes, s3, s1));
|
|
edges.push(helper.createSimpleEdge(nodes, s4, s47));
|
|
edges.push(helper.createSimpleEdge(nodes, s4, s13));
|
|
edges.push(helper.createSimpleEdge(nodes, s4, s9));
|
|
edges.push(helper.createSimpleEdge(nodes, s4, s17));
|
|
edges.push(helper.createSimpleEdge(nodes, s4, s18));
|
|
edges.push(helper.createSimpleEdge(nodes, s4, s44));
|
|
edges.push(helper.createSimpleEdge(nodes, s4, s7));
|
|
edges.push(helper.createSimpleEdge(nodes, s5, s47));
|
|
edges.push(helper.createSimpleEdge(nodes, s5, s27));
|
|
edges.push(helper.createSimpleEdge(nodes, s5, s12));
|
|
edges.push(helper.createSimpleEdge(nodes, s5, s35));
|
|
edges.push(helper.createSimpleEdge(nodes, s5, s33));
|
|
edges.push(helper.createSimpleEdge(nodes, s5, s2));
|
|
edges.push(helper.createSimpleEdge(nodes, s5, s38));
|
|
edges.push(helper.createSimpleEdge(nodes, s5, s17));
|
|
edges.push(helper.createSimpleEdge(nodes, s5, s18));
|
|
edges.push(helper.createSimpleEdge(nodes, s5, s2));
|
|
edges.push(helper.createSimpleEdge(nodes, s5, s27));
|
|
edges.push(helper.createSimpleEdge(nodes, s5, s0));
|
|
edges.push(helper.createSimpleEdge(nodes, s6, s25));
|
|
edges.push(helper.createSimpleEdge(nodes, s6, s32));
|
|
edges.push(helper.createSimpleEdge(nodes, s6, s12));
|
|
edges.push(helper.createSimpleEdge(nodes, s6, s47));
|
|
edges.push(helper.createSimpleEdge(nodes, s6, s3));
|
|
edges.push(helper.createSimpleEdge(nodes, s7, s11));
|
|
edges.push(helper.createSimpleEdge(nodes, s7, s35));
|
|
edges.push(helper.createSimpleEdge(nodes, s7, s28));
|
|
edges.push(helper.createSimpleEdge(nodes, s7, s46));
|
|
edges.push(helper.createSimpleEdge(nodes, s7, s37));
|
|
edges.push(helper.createSimpleEdge(nodes, s7, s15));
|
|
edges.push(helper.createSimpleEdge(nodes, s7, s31));
|
|
edges.push(helper.createSimpleEdge(nodes, s7, s3));
|
|
edges.push(helper.createSimpleEdge(nodes, s8, s41));
|
|
edges.push(helper.createSimpleEdge(nodes, s8, s30));
|
|
edges.push(helper.createSimpleEdge(nodes, s8, s20));
|
|
edges.push(helper.createSimpleEdge(nodes, s8, s2));
|
|
edges.push(helper.createSimpleEdge(nodes, s8, s40));
|
|
edges.push(helper.createSimpleEdge(nodes, s9, s21));
|
|
edges.push(helper.createSimpleEdge(nodes, s9, s40));
|
|
edges.push(helper.createSimpleEdge(nodes, s9, s42));
|
|
edges.push(helper.createSimpleEdge(nodes, s9, s46));
|
|
edges.push(helper.createSimpleEdge(nodes, s9, s23));
|
|
edges.push(helper.createSimpleEdge(nodes, s9, s8));
|
|
edges.push(helper.createSimpleEdge(nodes, s9, s17));
|
|
edges.push(helper.createSimpleEdge(nodes, s10, s43));
|
|
edges.push(helper.createSimpleEdge(nodes, s10, s18));
|
|
edges.push(helper.createSimpleEdge(nodes, s10, s6));
|
|
edges.push(helper.createSimpleEdge(nodes, s11, s18));
|
|
edges.push(helper.createSimpleEdge(nodes, s11, s31));
|
|
edges.push(helper.createSimpleEdge(nodes, s11, s43));
|
|
edges.push(helper.createSimpleEdge(nodes, s11, s28));
|
|
edges.push(helper.createSimpleEdge(nodes, s11, s5));
|
|
edges.push(helper.createSimpleEdge(nodes, s11, s37));
|
|
edges.push(helper.createSimpleEdge(nodes, s12, s14));
|
|
edges.push(helper.createSimpleEdge(nodes, s12, s6));
|
|
edges.push(helper.createSimpleEdge(nodes, s12, s35));
|
|
edges.push(helper.createSimpleEdge(nodes, s12, s6));
|
|
edges.push(helper.createSimpleEdge(nodes, s12, s8));
|
|
edges.push(helper.createSimpleEdge(nodes, s12, s36));
|
|
edges.push(helper.createSimpleEdge(nodes, s13, s28));
|
|
edges.push(helper.createSimpleEdge(nodes, s13, s38));
|
|
edges.push(helper.createSimpleEdge(nodes, s13, s41));
|
|
edges.push(helper.createSimpleEdge(nodes, s14, s32));
|
|
edges.push(helper.createSimpleEdge(nodes, s14, s19));
|
|
edges.push(helper.createSimpleEdge(nodes, s14, s29));
|
|
edges.push(helper.createSimpleEdge(nodes, s14, s21));
|
|
edges.push(helper.createSimpleEdge(nodes, s14, s17));
|
|
edges.push(helper.createSimpleEdge(nodes, s14, s31));
|
|
edges.push(helper.createSimpleEdge(nodes, s15, s0));
|
|
edges.push(helper.createSimpleEdge(nodes, s15, s28));
|
|
edges.push(helper.createSimpleEdge(nodes, s15, s22));
|
|
edges.push(helper.createSimpleEdge(nodes, s15, s25));
|
|
edges.push(helper.createSimpleEdge(nodes, s15, s11));
|
|
edges.push(helper.createSimpleEdge(nodes, s15, s39));
|
|
edges.push(helper.createSimpleEdge(nodes, s16, s37));
|
|
edges.push(helper.createSimpleEdge(nodes, s16, s41));
|
|
edges.push(helper.createSimpleEdge(nodes, s16, s37));
|
|
edges.push(helper.createSimpleEdge(nodes, s16, s22));
|
|
edges.push(helper.createSimpleEdge(nodes, s16, s11));
|
|
edges.push(helper.createSimpleEdge(nodes, s16, s45));
|
|
edges.push(helper.createSimpleEdge(nodes, s16, s38));
|
|
edges.push(helper.createSimpleEdge(nodes, s17, s28));
|
|
edges.push(helper.createSimpleEdge(nodes, s17, s11));
|
|
edges.push(helper.createSimpleEdge(nodes, s17, s10));
|
|
edges.push(helper.createSimpleEdge(nodes, s17, s13));
|
|
edges.push(helper.createSimpleEdge(nodes, s17, s0));
|
|
edges.push(helper.createSimpleEdge(nodes, s17, s11));
|
|
edges.push(helper.createSimpleEdge(nodes, s17, s1));
|
|
edges.push(helper.createSimpleEdge(nodes, s17, s25));
|
|
edges.push(helper.createSimpleEdge(nodes, s18, s39));
|
|
edges.push(helper.createSimpleEdge(nodes, s18, s24));
|
|
edges.push(helper.createSimpleEdge(nodes, s18, s41));
|
|
edges.push(helper.createSimpleEdge(nodes, s18, s14));
|
|
edges.push(helper.createSimpleEdge(nodes, s18, s31));
|
|
edges.push(helper.createSimpleEdge(nodes, s19, s43));
|
|
edges.push(helper.createSimpleEdge(nodes, s19, s44));
|
|
edges.push(helper.createSimpleEdge(nodes, s19, s23));
|
|
edges.push(helper.createSimpleEdge(nodes, s19, s40));
|
|
edges.push(helper.createSimpleEdge(nodes, s19, s0));
|
|
edges.push(helper.createSimpleEdge(nodes, s19, s5));
|
|
edges.push(helper.createSimpleEdge(nodes, s20, s13));
|
|
edges.push(helper.createSimpleEdge(nodes, s20, s34));
|
|
edges.push(helper.createSimpleEdge(nodes, s20, s46));
|
|
edges.push(helper.createSimpleEdge(nodes, s20, s39));
|
|
edges.push(helper.createSimpleEdge(nodes, s20, s14));
|
|
edges.push(helper.createSimpleEdge(nodes, s20, s12));
|
|
edges.push(helper.createSimpleEdge(nodes, s20, s34));
|
|
edges.push(helper.createSimpleEdge(nodes, s20, s37));
|
|
edges.push(helper.createSimpleEdge(nodes, s20, s39));
|
|
edges.push(helper.createSimpleEdge(nodes, s21, s2));
|
|
edges.push(helper.createSimpleEdge(nodes, s21, s10));
|
|
edges.push(helper.createSimpleEdge(nodes, s21, s28));
|
|
edges.push(helper.createSimpleEdge(nodes, s21, s7));
|
|
edges.push(helper.createSimpleEdge(nodes, s21, s44));
|
|
edges.push(helper.createSimpleEdge(nodes, s21, s13));
|
|
edges.push(helper.createSimpleEdge(nodes, s21, s37));
|
|
edges.push(helper.createSimpleEdge(nodes, s22, s12));
|
|
edges.push(helper.createSimpleEdge(nodes, s22, s12));
|
|
edges.push(helper.createSimpleEdge(nodes, s22, s5));
|
|
edges.push(helper.createSimpleEdge(nodes, s22, s8));
|
|
edges.push(helper.createSimpleEdge(nodes, s22, s42));
|
|
edges.push(helper.createSimpleEdge(nodes, s22, s26));
|
|
edges.push(helper.createSimpleEdge(nodes, s22, s29));
|
|
edges.push(helper.createSimpleEdge(nodes, s22, s1));
|
|
edges.push(helper.createSimpleEdge(nodes, s22, s0));
|
|
edges.push(helper.createSimpleEdge(nodes, s22, s19));
|
|
edges.push(helper.createSimpleEdge(nodes, s23, s47));
|
|
edges.push(helper.createSimpleEdge(nodes, s23, s20));
|
|
edges.push(helper.createSimpleEdge(nodes, s23, s13));
|
|
edges.push(helper.createSimpleEdge(nodes, s23, s36));
|
|
edges.push(helper.createSimpleEdge(nodes, s24, s19));
|
|
edges.push(helper.createSimpleEdge(nodes, s24, s10));
|
|
edges.push(helper.createSimpleEdge(nodes, s24, s32));
|
|
edges.push(helper.createSimpleEdge(nodes, s24, s42));
|
|
edges.push(helper.createSimpleEdge(nodes, s24, s11));
|
|
edges.push(helper.createSimpleEdge(nodes, s24, s32));
|
|
edges.push(helper.createSimpleEdge(nodes, s24, s1));
|
|
edges.push(helper.createSimpleEdge(nodes, s24, s29));
|
|
edges.push(helper.createSimpleEdge(nodes, s24, s34));
|
|
edges.push(helper.createSimpleEdge(nodes, s25, s45));
|
|
edges.push(helper.createSimpleEdge(nodes, s25, s34));
|
|
edges.push(helper.createSimpleEdge(nodes, s25, s9));
|
|
edges.push(helper.createSimpleEdge(nodes, s25, s41));
|
|
edges.push(helper.createSimpleEdge(nodes, s26, s37));
|
|
edges.push(helper.createSimpleEdge(nodes, s26, s28));
|
|
edges.push(helper.createSimpleEdge(nodes, s26, s34));
|
|
edges.push(helper.createSimpleEdge(nodes, s26, s43));
|
|
edges.push(helper.createSimpleEdge(nodes, s26, s13));
|
|
edges.push(helper.createSimpleEdge(nodes, s26, s6));
|
|
edges.push(helper.createSimpleEdge(nodes, s27, s47));
|
|
edges.push(helper.createSimpleEdge(nodes, s27, s29));
|
|
edges.push(helper.createSimpleEdge(nodes, s27, s36));
|
|
edges.push(helper.createSimpleEdge(nodes, s27, s36));
|
|
edges.push(helper.createSimpleEdge(nodes, s27, s45));
|
|
edges.push(helper.createSimpleEdge(nodes, s27, s15));
|
|
edges.push(helper.createSimpleEdge(nodes, s28, s30));
|
|
edges.push(helper.createSimpleEdge(nodes, s28, s5));
|
|
edges.push(helper.createSimpleEdge(nodes, s28, s27));
|
|
edges.push(helper.createSimpleEdge(nodes, s28, s33));
|
|
edges.push(helper.createSimpleEdge(nodes, s28, s4));
|
|
edges.push(helper.createSimpleEdge(nodes, s28, s44));
|
|
edges.push(helper.createSimpleEdge(nodes, s28, s24));
|
|
edges.push(helper.createSimpleEdge(nodes, s28, s25));
|
|
edges.push(helper.createSimpleEdge(nodes, s29, s18));
|
|
edges.push(helper.createSimpleEdge(nodes, s29, s3));
|
|
edges.push(helper.createSimpleEdge(nodes, s29, s10));
|
|
edges.push(helper.createSimpleEdge(nodes, s29, s38));
|
|
edges.push(helper.createSimpleEdge(nodes, s29, s5));
|
|
edges.push(helper.createSimpleEdge(nodes, s29, s0));
|
|
edges.push(helper.createSimpleEdge(nodes, s29, s25));
|
|
edges.push(helper.createSimpleEdge(nodes, s29, s46));
|
|
edges.push(helper.createSimpleEdge(nodes, s30, s46));
|
|
edges.push(helper.createSimpleEdge(nodes, s30, s7));
|
|
edges.push(helper.createSimpleEdge(nodes, s30, s2));
|
|
edges.push(helper.createSimpleEdge(nodes, s30, s22));
|
|
edges.push(helper.createSimpleEdge(nodes, s30, s27));
|
|
edges.push(helper.createSimpleEdge(nodes, s30, s34));
|
|
edges.push(helper.createSimpleEdge(nodes, s30, s39));
|
|
edges.push(helper.createSimpleEdge(nodes, s30, s45));
|
|
edges.push(helper.createSimpleEdge(nodes, s31, s33));
|
|
edges.push(helper.createSimpleEdge(nodes, s31, s46));
|
|
edges.push(helper.createSimpleEdge(nodes, s31, s30));
|
|
edges.push(helper.createSimpleEdge(nodes, s31, s5));
|
|
edges.push(helper.createSimpleEdge(nodes, s31, s2));
|
|
edges.push(helper.createSimpleEdge(nodes, s31, s25));
|
|
edges.push(helper.createSimpleEdge(nodes, s31, s18));
|
|
edges.push(helper.createSimpleEdge(nodes, s31, s27));
|
|
edges.push(helper.createSimpleEdge(nodes, s31, s25));
|
|
edges.push(helper.createSimpleEdge(nodes, s32, s30));
|
|
edges.push(helper.createSimpleEdge(nodes, s32, s26));
|
|
edges.push(helper.createSimpleEdge(nodes, s32, s1));
|
|
edges.push(helper.createSimpleEdge(nodes, s32, s21));
|
|
edges.push(helper.createSimpleEdge(nodes, s32, s38));
|
|
edges.push(helper.createSimpleEdge(nodes, s32, s38));
|
|
edges.push(helper.createSimpleEdge(nodes, s32, s23));
|
|
edges.push(helper.createSimpleEdge(nodes, s33, s36));
|
|
edges.push(helper.createSimpleEdge(nodes, s33, s40));
|
|
edges.push(helper.createSimpleEdge(nodes, s33, s6));
|
|
edges.push(helper.createSimpleEdge(nodes, s34, s19));
|
|
edges.push(helper.createSimpleEdge(nodes, s34, s29));
|
|
edges.push(helper.createSimpleEdge(nodes, s34, s2));
|
|
edges.push(helper.createSimpleEdge(nodes, s34, s0));
|
|
edges.push(helper.createSimpleEdge(nodes, s34, s14));
|
|
edges.push(helper.createSimpleEdge(nodes, s34, s0));
|
|
edges.push(helper.createSimpleEdge(nodes, s34, s1));
|
|
edges.push(helper.createSimpleEdge(nodes, s34, s19));
|
|
edges.push(helper.createSimpleEdge(nodes, s34, s42));
|
|
edges.push(helper.createSimpleEdge(nodes, s34, s39));
|
|
edges.push(helper.createSimpleEdge(nodes, s34, s15));
|
|
edges.push(helper.createSimpleEdge(nodes, s34, s17));
|
|
edges.push(helper.createSimpleEdge(nodes, s35, s13));
|
|
edges.push(helper.createSimpleEdge(nodes, s35, s31));
|
|
edges.push(helper.createSimpleEdge(nodes, s35, s30));
|
|
edges.push(helper.createSimpleEdge(nodes, s35, s22));
|
|
edges.push(helper.createSimpleEdge(nodes, s35, s47));
|
|
edges.push(helper.createSimpleEdge(nodes, s35, s25));
|
|
edges.push(helper.createSimpleEdge(nodes, s36, s44));
|
|
edges.push(helper.createSimpleEdge(nodes, s36, s25));
|
|
edges.push(helper.createSimpleEdge(nodes, s36, s19));
|
|
edges.push(helper.createSimpleEdge(nodes, s36, s9));
|
|
edges.push(helper.createSimpleEdge(nodes, s36, s11));
|
|
edges.push(helper.createSimpleEdge(nodes, s36, s11));
|
|
edges.push(helper.createSimpleEdge(nodes, s36, s6));
|
|
edges.push(helper.createSimpleEdge(nodes, s36, s14));
|
|
edges.push(helper.createSimpleEdge(nodes, s36, s28));
|
|
edges.push(helper.createSimpleEdge(nodes, s36, s31));
|
|
edges.push(helper.createSimpleEdge(nodes, s37, s40));
|
|
edges.push(helper.createSimpleEdge(nodes, s37, s4));
|
|
edges.push(helper.createSimpleEdge(nodes, s37, s45));
|
|
edges.push(helper.createSimpleEdge(nodes, s37, s11));
|
|
edges.push(helper.createSimpleEdge(nodes, s37, s39));
|
|
edges.push(helper.createSimpleEdge(nodes, s37, s30));
|
|
edges.push(helper.createSimpleEdge(nodes, s37, s31));
|
|
edges.push(helper.createSimpleEdge(nodes, s37, s9));
|
|
edges.push(helper.createSimpleEdge(nodes, s37, s35));
|
|
edges.push(helper.createSimpleEdge(nodes, s37, s45));
|
|
edges.push(helper.createSimpleEdge(nodes, s37, s7));
|
|
edges.push(helper.createSimpleEdge(nodes, s37, s32));
|
|
edges.push(helper.createSimpleEdge(nodes, s38, s36));
|
|
edges.push(helper.createSimpleEdge(nodes, s38, s45));
|
|
edges.push(helper.createSimpleEdge(nodes, s38, s5));
|
|
edges.push(helper.createSimpleEdge(nodes, s38, s1));
|
|
edges.push(helper.createSimpleEdge(nodes, s39, s37));
|
|
edges.push(helper.createSimpleEdge(nodes, s39, s32));
|
|
edges.push(helper.createSimpleEdge(nodes, s39, s31));
|
|
edges.push(helper.createSimpleEdge(nodes, s39, s13));
|
|
edges.push(helper.createSimpleEdge(nodes, s39, s20));
|
|
edges.push(helper.createSimpleEdge(nodes, s39, s25));
|
|
edges.push(helper.createSimpleEdge(nodes, s39, s7));
|
|
edges.push(helper.createSimpleEdge(nodes, s39, s20));
|
|
edges.push(helper.createSimpleEdge(nodes, s39, s27));
|
|
edges.push(helper.createSimpleEdge(nodes, s39, s5));
|
|
edges.push(helper.createSimpleEdge(nodes, s39, s17));
|
|
edges.push(helper.createSimpleEdge(nodes, s39, s8));
|
|
edges.push(helper.createSimpleEdge(nodes, s40, s8));
|
|
edges.push(helper.createSimpleEdge(nodes, s40, s12));
|
|
edges.push(helper.createSimpleEdge(nodes, s40, s31));
|
|
edges.push(helper.createSimpleEdge(nodes, s40, s39));
|
|
edges.push(helper.createSimpleEdge(nodes, s40, s31));
|
|
edges.push(helper.createSimpleEdge(nodes, s40, s9));
|
|
edges.push(helper.createSimpleEdge(nodes, s41, s45));
|
|
edges.push(helper.createSimpleEdge(nodes, s41, s6));
|
|
edges.push(helper.createSimpleEdge(nodes, s41, s36));
|
|
edges.push(helper.createSimpleEdge(nodes, s41, s12));
|
|
edges.push(helper.createSimpleEdge(nodes, s41, s26));
|
|
edges.push(helper.createSimpleEdge(nodes, s41, s6));
|
|
edges.push(helper.createSimpleEdge(nodes, s41, s21));
|
|
edges.push(helper.createSimpleEdge(nodes, s41, s33));
|
|
edges.push(helper.createSimpleEdge(nodes, s42, s25));
|
|
edges.push(helper.createSimpleEdge(nodes, s42, s28));
|
|
edges.push(helper.createSimpleEdge(nodes, s42, s46));
|
|
edges.push(helper.createSimpleEdge(nodes, s42, s34));
|
|
edges.push(helper.createSimpleEdge(nodes, s42, s41));
|
|
edges.push(helper.createSimpleEdge(nodes, s42, s32));
|
|
edges.push(helper.createSimpleEdge(nodes, s42, s9));
|
|
edges.push(helper.createSimpleEdge(nodes, s43, s12));
|
|
edges.push(helper.createSimpleEdge(nodes, s43, s29));
|
|
edges.push(helper.createSimpleEdge(nodes, s43, s2));
|
|
edges.push(helper.createSimpleEdge(nodes, s43, s14));
|
|
edges.push(helper.createSimpleEdge(nodes, s43, s1));
|
|
edges.push(helper.createSimpleEdge(nodes, s43, s13));
|
|
edges.push(helper.createSimpleEdge(nodes, s43, s28));
|
|
edges.push(helper.createSimpleEdge(nodes, s43, s47));
|
|
edges.push(helper.createSimpleEdge(nodes, s43, s22));
|
|
edges.push(helper.createSimpleEdge(nodes, s43, s2));
|
|
edges.push(helper.createSimpleEdge(nodes, s43, s5));
|
|
edges.push(helper.createSimpleEdge(nodes, s44, s3));
|
|
edges.push(helper.createSimpleEdge(nodes, s44, s1));
|
|
edges.push(helper.createSimpleEdge(nodes, s44, s18));
|
|
edges.push(helper.createSimpleEdge(nodes, s44, s37));
|
|
edges.push(helper.createSimpleEdge(nodes, s44, s0));
|
|
edges.push(helper.createSimpleEdge(nodes, s44, s4));
|
|
edges.push(helper.createSimpleEdge(nodes, s44, s18));
|
|
edges.push(helper.createSimpleEdge(nodes, s44, s7));
|
|
edges.push(helper.createSimpleEdge(nodes, s44, s9));
|
|
edges.push(helper.createSimpleEdge(nodes, s44, s38));
|
|
edges.push(helper.createSimpleEdge(nodes, s44, s15));
|
|
edges.push(helper.createSimpleEdge(nodes, s45, s35));
|
|
edges.push(helper.createSimpleEdge(nodes, s45, s34));
|
|
edges.push(helper.createSimpleEdge(nodes, s45, s5));
|
|
edges.push(helper.createSimpleEdge(nodes, s46, s7));
|
|
edges.push(helper.createSimpleEdge(nodes, s46, s39));
|
|
edges.push(helper.createSimpleEdge(nodes, s46, s21));
|
|
edges.push(helper.createSimpleEdge(nodes, s46, s47));
|
|
edges.push(helper.createSimpleEdge(nodes, s46, s1));
|
|
edges.push(helper.createSimpleEdge(nodes, s46, s19));
|
|
edges.push(helper.createSimpleEdge(nodes, s46, s11));
|
|
edges.push(helper.createSimpleEdge(nodes, s47, s9));
|
|
edges.push(helper.createSimpleEdge(nodes, s47, s10));
|
|
edges.push(helper.createSimpleEdge(nodes, s47, s46));
|
|
edges.push(helper.createSimpleEdge(nodes, s47, s13));
|
|
edges.push(helper.createSimpleEdge(nodes, s47, s21));
|
|
edges.push(helper.createSimpleEdge(nodes, s47, s19));
|
|
edges.push(helper.createSimpleEdge(nodes, s47, s8));
|
|
edges.push(helper.createSimpleEdge(nodes, s47, s39));
|
|
edges.push(helper.createSimpleEdge(nodes, s47, s15));
|
|
edges.push(helper.createSimpleEdge(nodes, s47, s34));
|
|
edges.push(helper.createSimpleEdge(nodes, s47, s30));
|
|
edges.push(helper.createSimpleEdge(nodes, s47, s45));
|
|
|
|
_.each(edges, function(e) {
|
|
joiner.insertEdge(e.source._id, e.target._id);
|
|
});
|
|
|
|
diff = (new Date()).getTime() - start;
|
|
console.log("Runtime Fill:", diff, "ms");
|
|
start = (new Date()).getTime();
|
|
joiner.setup();
|
|
diff = (new Date()).getTime() - start;
|
|
console.log("Runtime Setup:", diff, "ms");
|
|
start = (new Date()).getTime();
|
|
best = joiner.getBest();
|
|
while (best !== null) {
|
|
joiner.joinCommunity(best);
|
|
best = joiner.getBest();
|
|
}
|
|
diff = (new Date()).getTime() - start;
|
|
|
|
console.log("Runtime Compute:", diff, "ms");
|
|
|
|
});
|
|
|
|
});
|
|
*/
|
|
|
|
/*
|
|
it('should be able to handle 10000 nodes', function() {
|
|
var start = (new Date()).getTime();
|
|
var i, best, nodeCount = 10000;
|
|
helper.insertNSimpleNodes(nodes, nodeCount);
|
|
helper.insertClique(nodes, edges, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
for (i = 11; i < nodeCount; i++) {
|
|
edges.push(helper.createSimpleEdge(nodes, i - 1, i));
|
|
edges.push(helper.createSimpleEdge(nodes, i, i - 2));
|
|
}
|
|
var diff = (new Date()).getTime() - start;
|
|
console.log("Runtime Fill:", diff, "ms");
|
|
start = (new Date()).getTime();
|
|
joiner.setup();
|
|
diff = (new Date()).getTime() - start;
|
|
console.log("Runtime Setup:", diff, "ms");
|
|
start = (new Date()).getTime();
|
|
best = joiner.getBest();
|
|
var step = 0;
|
|
while (best !== null) {
|
|
joiner.joinCommunity(best);
|
|
best = joiner.getBest();
|
|
step++;
|
|
}
|
|
diff = (new Date()).getTime() - start;
|
|
console.log("Runtime Compute:", diff, "ms");
|
|
});
|
|
*/
|
|
});
|
|
|
|
describe('configured as a worker', function() {
|
|
|
|
var joiner,
|
|
nodes,
|
|
edges,
|
|
testNetFour,
|
|
called,
|
|
result,
|
|
custom,
|
|
error;
|
|
|
|
beforeEach(function () {
|
|
|
|
runs(function() {
|
|
custom = function() {};
|
|
called = false;
|
|
result = "";
|
|
error = "";
|
|
nodes = [];
|
|
edges = [];
|
|
testNetFour = function() {
|
|
helper.insertSimpleNodes(nodes, ["0", "1", "2", "3"]);
|
|
edges.push(helper.createSimpleEdge(nodes, 0, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 0, 3));
|
|
edges.push(helper.createSimpleEdge(nodes, 1, 2));
|
|
edges.push(helper.createSimpleEdge(nodes, 2, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 2, 3));
|
|
edges.push(helper.createSimpleEdge(nodes, 3, 0));
|
|
edges.push(helper.createSimpleEdge(nodes, 3, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 3, 2));
|
|
_.each(edges, function(e) {
|
|
joiner.call("insertEdge", e.source._id, e.target._id);
|
|
});
|
|
};
|
|
var callback = function(d) {
|
|
custom(d);
|
|
if (d.data.cmd === "insertEdge") {
|
|
return;
|
|
}
|
|
called = true;
|
|
if (d.data.cmd !== "construct") {
|
|
result = d.data.result;
|
|
error = d.data.error;
|
|
}
|
|
};
|
|
joiner = new WebWorkerWrapper(ModularityJoiner, callback);
|
|
});
|
|
|
|
waitsFor(function() {
|
|
return called;
|
|
}, 1000);
|
|
|
|
runs(function() {
|
|
called = false;
|
|
});
|
|
});
|
|
|
|
it('should be able to identify an obvious community', function() {
|
|
|
|
runs(function() {
|
|
helper.insertSimpleNodes(nodes, ["0", "1", "2", "3", "4"]);
|
|
edges.push(helper.createSimpleEdge(nodes, 0, 1));
|
|
edges.push(helper.createSimpleEdge(nodes, 0, 2));
|
|
edges.push(helper.createSimpleEdge(nodes, 0, 3));
|
|
edges.push(helper.createSimpleEdge(nodes, 3, 4));
|
|
|
|
_.each(edges, function(e) {
|
|
joiner.call("insertEdge", e.source._id, e.target._id);
|
|
});
|
|
joiner.call("getCommunity", 3, nodes[4]._id);
|
|
|
|
});
|
|
|
|
waitsFor(function() {
|
|
return called;
|
|
});
|
|
|
|
runs(function() {
|
|
expect(result).toContainNodes(["0", "1", "2"]);
|
|
expect(error).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
it('should prefer cliques as a community over an equal sized other group', function() {
|
|
|
|
runs(function() {
|
|
helper.insertSimpleNodes(nodes, ["0", "1", "2", "3", "4", "5", "6", "7", "8"]);
|
|
helper.insertClique(nodes, edges, [0, 1, 2, 3]);
|
|
edges.push(helper.createSimpleEdge(nodes, 4, 3));
|
|
edges.push(helper.createSimpleEdge(nodes, 4, 5));
|
|
edges.push(helper.createSimpleEdge(nodes, 5, 6));
|
|
edges.push(helper.createSimpleEdge(nodes, 5, 7));
|
|
edges.push(helper.createSimpleEdge(nodes, 5, 8));
|
|
|
|
_.each(edges, function(e) {
|
|
joiner.call("insertEdge", e.source._id, e.target._id);
|
|
});
|
|
|
|
joiner.call("getCommunity", 6, nodes[4]._id);
|
|
});
|
|
|
|
waitsFor(function() {
|
|
return called;
|
|
});
|
|
|
|
runs(function() {
|
|
expect(result).toContainNodes(["0", "1", "2", "3"]);
|
|
expect(error).toBeUndefined();
|
|
});
|
|
|
|
});
|
|
|
|
it('should not return a close group if there is an alternative', function() {
|
|
|
|
runs(function() {
|
|
helper.insertSimpleNodes(nodes, ["0", "1", "2", "3", "4", "5", "6", "7", "8"]);
|
|
helper.insertClique(nodes, edges, [0, 1, 2]);
|
|
helper.insertClique(nodes, edges, [3, 4, 5]);
|
|
helper.insertClique(nodes, edges, [6, 7, 8]);
|
|
edges.push(helper.createSimpleEdge(nodes, 3, 2));
|
|
edges.push(helper.createSimpleEdge(nodes, 5, 6));
|
|
|
|
_.each(edges, function(e) {
|
|
joiner.call("insertEdge", e.source._id, e.target._id);
|
|
});
|
|
|
|
joiner.call("getCommunity", 6, nodes[3]._id);
|
|
});
|
|
|
|
waitsFor(function() {
|
|
return called;
|
|
});
|
|
|
|
runs(function() {
|
|
expect(result).toContainNodes(["6", "7", "8"]);
|
|
expect(error).toBeUndefined();
|
|
});
|
|
|
|
});
|
|
|
|
it('should also take the best community if no focus is given', function() {
|
|
runs(function() {
|
|
helper.insertSimpleNodes(nodes, ["0", "1", "2", "3", "4", "5", "6", "7"]);
|
|
helper.insertClique(nodes, edges, [0, 1, 2]);
|
|
edges.push(helper.createSimpleEdge(nodes, 3, 2));
|
|
edges.push(helper.createSimpleEdge(nodes, 3, 4));
|
|
edges.push(helper.createSimpleEdge(nodes, 4, 5));
|
|
edges.push(helper.createSimpleEdge(nodes, 5, 6));
|
|
edges.push(helper.createSimpleEdge(nodes, 5, 7));
|
|
|
|
_.each(edges, function(e) {
|
|
joiner.call("insertEdge", e.source._id, e.target._id);
|
|
});
|
|
|
|
joiner.call("getCommunity", 6);
|
|
});
|
|
|
|
waitsFor(function() {
|
|
return called;
|
|
});
|
|
|
|
runs(function() {
|
|
expect(result).toContainNodes(["0", "1", "2"]);
|
|
expect(error).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
it('should be possible to send many getCommunity requests without crashing', function() {
|
|
|
|
var customCounter, s0, s1, s2, s3, s4, ts, comResults, errors;
|
|
|
|
runs(function() {
|
|
customCounter = [];
|
|
comResults = [];
|
|
errors = [];
|
|
s0 = helper.insertSatelite(nodes, edges, 0, 500);
|
|
s1 = helper.insertSatelite(nodes, edges, 1, 300);
|
|
s2 = helper.insertSatelite(nodes, edges, 2, 313);
|
|
s3 = helper.insertSatelite(nodes, edges, 3, 461);
|
|
s4 = helper.insertSatelite(nodes, edges, 4, 251);
|
|
|
|
edges.push(helper.createSimpleEdge(nodes, s0, s1));
|
|
edges.push(helper.createSimpleEdge(nodes, s0, s2));
|
|
edges.push(helper.createSimpleEdge(nodes, s1, s3));
|
|
edges.push(helper.createSimpleEdge(nodes, s1, s4));
|
|
edges.push(helper.createSimpleEdge(nodes, s2, s1));
|
|
edges.push(helper.createSimpleEdge(nodes, s2, s4));
|
|
edges.push(helper.createSimpleEdge(nodes, s3, s0));
|
|
edges.push(helper.createSimpleEdge(nodes, s4, s1));
|
|
|
|
custom = function(d) {
|
|
var data = d.data;
|
|
customCounter.push(((new Date()).getTime() - ts) + ": " + data.cmd);
|
|
if (d.data.cmd === "getCommunity") {
|
|
comResults.push(data.result || data.error);
|
|
}
|
|
if (data.error) {
|
|
errors.push(data.cmd + ": " + data.error);
|
|
}
|
|
|
|
};
|
|
|
|
ts = (new Date()).getTime();
|
|
_.each(edges, function(e) {
|
|
joiner.call("insertEdge", e.source._id, e.target._id);
|
|
});
|
|
|
|
ts = (new Date()).getTime();
|
|
});
|
|
|
|
waitsFor(function() {
|
|
return customCounter.length === 1833;
|
|
});
|
|
|
|
runs(function() {
|
|
customCounter = [];
|
|
joiner.call("getCommunity", 800);
|
|
/*
|
|
joiner.call("deleteEdge", s0._id, s1._id);
|
|
joiner.call("deleteEdge", s2._id, s1._id);
|
|
joiner.call("deleteEdge", s3._id, s0._id);
|
|
|
|
joiner.call("insertEdge", s3._id, s0._id);
|
|
joiner.call("insertEdge", s2._id, s1._id);
|
|
joiner.call("insertEdge", s0._id, s1._id);
|
|
*/
|
|
joiner.call("getCommunity", 800);
|
|
});
|
|
|
|
waitsFor(function() {
|
|
return comResults.length === 2;
|
|
});
|
|
|
|
runs(function() {
|
|
expect(comResults[0]).toEqual(comResults[1]);
|
|
expect(errors).toEqual([]);
|
|
});
|
|
});
|
|
|
|
it('should not crash because of insertion/deletion of edges', function() {
|
|
|
|
var customCounter, s0, s1, s2, s3, s4, ts, comResults, errors, adjResults;
|
|
|
|
runs(function() {
|
|
customCounter = [];
|
|
comResults = [];
|
|
errors = [];
|
|
adjResults = [];
|
|
s0 = helper.insertSatelite(nodes, edges, 0, 500);
|
|
s1 = helper.insertSatelite(nodes, edges, 1, 300);
|
|
s2 = helper.insertSatelite(nodes, edges, 2, 313);
|
|
s3 = helper.insertSatelite(nodes, edges, 3, 461);
|
|
s4 = helper.insertSatelite(nodes, edges, 4, 251);
|
|
|
|
edges.push(helper.createSimpleEdge(nodes, s0, s1));
|
|
edges.push(helper.createSimpleEdge(nodes, s0, s2));
|
|
edges.push(helper.createSimpleEdge(nodes, s1, s3));
|
|
edges.push(helper.createSimpleEdge(nodes, s1, s4));
|
|
edges.push(helper.createSimpleEdge(nodes, s2, s1));
|
|
edges.push(helper.createSimpleEdge(nodes, s2, s4));
|
|
edges.push(helper.createSimpleEdge(nodes, s3, s0));
|
|
edges.push(helper.createSimpleEdge(nodes, s4, s1));
|
|
|
|
custom = function(d) {
|
|
var data = d.data;
|
|
customCounter.push(((new Date()).getTime() - ts) + ": " + data.cmd);
|
|
if (data.cmd === "getCommunity") {
|
|
comResults.push(data.result || data.error);
|
|
}
|
|
if (data.error) {
|
|
errors.push(data.cmd + ": " + data.error);
|
|
}
|
|
|
|
};
|
|
|
|
ts = (new Date()).getTime();
|
|
_.each(edges, function(e) {
|
|
joiner.call("insertEdge", e.source._id, e.target._id);
|
|
});
|
|
|
|
ts = (new Date()).getTime();
|
|
});
|
|
|
|
waitsFor(function() {
|
|
return customCounter.length === 1833;
|
|
});
|
|
|
|
runs(function() {
|
|
customCounter = [];
|
|
joiner.call("getCommunity", 800);
|
|
|
|
joiner.call("deleteEdge", "0", "1");
|
|
joiner.call("deleteEdge", "2", "1");
|
|
joiner.call("deleteEdge", "3", "0");
|
|
|
|
joiner.call("insertEdge", "3", "0");
|
|
joiner.call("insertEdge", "2", "1");
|
|
joiner.call("insertEdge", "0", "1");
|
|
|
|
joiner.call("getCommunity", 800);
|
|
});
|
|
|
|
waitsFor(function() {
|
|
return comResults.length === 2;
|
|
});
|
|
|
|
runs(function() {
|
|
expect(adjResults[0]).toEqual(adjResults[1]);
|
|
expect(comResults[0]).toEqual(comResults[1]);
|
|
expect(errors).toEqual([]);
|
|
});
|
|
});
|
|
|
|
});
|
|
});
|
|
}());
|