1
0
Fork 0

GraphViewer: Added a function to the node reducer to join nodes based on their similarity if too many child nodes aare added at once

This commit is contained in:
Michael Hackstein 2013-05-24 15:21:26 +02:00
parent 79efa0b2a9
commit 866b74d4b6
2 changed files with 205 additions and 2 deletions

View File

@ -265,9 +265,34 @@ function NodeReducer(nodes, edges) {
joinCommunities(l.sID, l.lID, coms, heap, l.val);
updateValues(l, dQ, a, heap);
return true;
},
addNode = function(bucket, node) {
bucket.push(node);
},
getSimilarityValue = function(bucket, node) {
if (bucket.length === 0) {
return 1;
}
var comp = bucket[0],
props = _.union(_.keys(comp), _.keys(node)),
countMatch = 0,
propCount = 0;
_.each(props, function(key) {
if (comp[key] !== undefined && node[key]!== undefined) {
countMatch++;
if (comp[key] === node[key]) {
countMatch++;
}
}
});
propCount = props.length * 2;
propCount++;
countMatch++;
return countMatch / propCount;
};
self.getCommunity = function(limit, focus) {
var dQ = {},
@ -305,4 +330,36 @@ function NodeReducer(nodes, edges) {
}
return res[0];
};
self.bucketNodes = function(toSort, numBuckets) {
var res = [],
threshold = 0.3;
if (toSort.length <= numBuckets) {
res = _.map(toSort, function(n) {
return [n];
});
return res;
}
_.each(toSort, function(n) {
var i, shortest, sLength;
shortest = 0;
sLength = Number.POSITIVE_INFINITY;
for (i = 0; i < numBuckets; i++) {
res[i] = res[i] || [];
if (getSimilarityValue(res[i], n) > threshold) {
addNode(res[i], n);
return;
}
if (sLength > res[i].length) {
shortest = i;
sLength = res[i].length;
}
}
addNode(res[shortest], n);
});
return res;
};
}

View File

@ -98,6 +98,12 @@
expect(reducer.getCommunity.length).toEqual(2);
});
it('should offer a function for bucket sort of nodes', function() {
expect(reducer.bucketNodes).toBeDefined();
expect(reducer.bucketNodes).toEqual(jasmine.any(Function));
expect(reducer.bucketNodes.length).toEqual(2);
});
});
describe('checking community identification', function() {
@ -154,6 +160,146 @@
});
describe('checking bucket sort of nodes', function() {
var allNodes, buckets;
beforeEach(function() {
allNodes = [];
this.addMatchers({
toContainAll: function(objs) {
var bucket = this.actual,
passed = true;
_.each(bucket, function(n) {
var i;
for (i = 0; i < objs.length; i++) {
if (objs[i] === n) {
return;
}
}
passed = false;
});
this.message = function() {
return JSON.stringify(bucket)
+ " should contain all of "
+ JSON.stringify(objs);
};
return passed;
}
});
});
it('should not bucket anything if #nodes <= #buckets', function() {
buckets = 5;
allNodes.push({a: 1});
allNodes.push({a: 1});
allNodes.push({a: 1});
allNodes.push({a: 1});
allNodes.push({a: 1});
var res = reducer.bucketNodes(allNodes, buckets);
expect(res.length).toEqual(5);
expect(res[0].length).toEqual(1);
expect(res[1].length).toEqual(1);
expect(res[2].length).toEqual(1);
expect(res[3].length).toEqual(1);
expect(res[4].length).toEqual(1);
});
it('should create at most the given amount of buckets', function() {
buckets = 3;
allNodes.push({a: 1});
allNodes.push({b: 2});
allNodes.push({c: 3});
allNodes.push({d: 4});
allNodes.push({e: 5});
allNodes.push({f: 6});
var res = reducer.bucketNodes(allNodes, buckets);
expect(res.length).toEqual(3);
});
it('should uniformly distribute dissimilar nodes', function() {
buckets = 3;
allNodes.push({a: 1});
allNodes.push({b: 2});
allNodes.push({c: 3});
allNodes.push({d: 4});
allNodes.push({e: 5});
allNodes.push({f: 6});
allNodes.push({g: 7});
allNodes.push({h: 8});
allNodes.push({i: 9});
var res = reducer.bucketNodes(allNodes, buckets);
expect(res[0].length).toEqual(3);
expect(res[1].length).toEqual(3);
expect(res[2].length).toEqual(3);
});
it('should bucket clearly similar nodes together', function() {
buckets = 3;
var a1, a2 ,a3,
b1, b2, b3,
c1, c2, c3,
resArray,
res1,
res2,
res3;
a1 = {a: 1};
a2 = {a: 1};
a3 = {a: 1};
b1 = {b: 2};
b2 = {b: 2};
b3 = {b: 2};
c1 = {c: 3};
c2 = {c: 3};
c3 = {c: 3};
allNodes.push(a1);
allNodes.push(a2);
allNodes.push(a3);
allNodes.push(b1);
allNodes.push(b2);
allNodes.push(b3);
allNodes.push(c1);
allNodes.push(c2);
allNodes.push(c3);
resArray = reducer.bucketNodes(allNodes, buckets);
res1 = resArray[0];
res2 = resArray[1];
res3 = resArray[2];
if (res1[0].a !== undefined) {
expect(res1).toContainAll([a1, a2, a3]);
} else if (res2[0].a !== undefined) {
expect(res2).toContainAll([a1, a2, a3]);
} else {
expect(res3).toContainAll([a1, a2, a3]);
}
if (res1[0].b !== undefined) {
expect(res1).toContainAll([b1, b2, b3]);
} else if (res2[0].b !== undefined) {
expect(res2).toContainAll([b1, b2, b3]);
} else {
expect(res3).toContainAll([b1, b2, b3]);
}
if (res1[0].c !== undefined) {
expect(res1).toContainAll([c1, c2, c3]);
} else if (res2[0].c !== undefined) {
expect(res2).toContainAll([c1, c2, c3]);
} else {
expect(res3).toContainAll([c1, c2, c3]);
}
});
});
});
});
}());