Skip to content

Commit

Permalink
tests pass
Browse files Browse the repository at this point in the history
  • Loading branch information
jdfekete committed Apr 18, 2015
1 parent 9d92de5 commit 50340d9
Show file tree
Hide file tree
Showing 11 changed files with 138 additions and 35 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
NODE_PATH = ./node_modules
JS_COMPILER = $(NODE_PATH)/uglify-js/bin/uglifyjs
#JS_TESTER = $(NODE_PATH)/vows/bin/vows --nocolor -v

all: \
reorder.v1.js \
Expand Down
11 changes: 9 additions & 2 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,12 @@ Reordering:
Correspondence analysis
Chun-Hou Chen methods: http://gap.stat.sinica.edu.tw/Papers/GAP_2002.pdf
Elliptical
Barycenter method: http://www.informatica.si/PDF/29-3/13_Makinen-The%20Barycenter%20Heuristic....pdf


Reordering done:
Barycenter method:
http://www.informatica.si/PDF/29-3/13_Makinen-The%20Barycenter%20Heuristic....pdf
Optimal Leaf Ordering
Ziv Bar-Joseph, Erik D. Demaine, David K. Gifford, Angèle M. Hamel, Tommy S. Jaakkola and Nathan Srebro
K-ary Clustering with Optimal Leaf Ordering for Gene Expression Data.
Bioinformatics, 19(9), pp 1070-8, 2003
http://www.cs.cmu.edu/~zivbj/compBio/k-aryBio.pdf
40 changes: 31 additions & 9 deletions reorder.v1.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
(function(exports){
reorder = {version: "0.0.2"}; // semver
reorder = {version: "0.0.3"}; // semver

reorder.dot = science.lin.dot;
reorder.length = science.lin.length;
Expand Down Expand Up @@ -644,6 +644,16 @@ function count_crossings(graph, north, south) {
firstIndex, treeSize, tree, index, weightSum,
invert = false, crosscount;

if (north==undefined) {
var comp = reorder.permutation(graph.nodes().length);
north = comp.filter(function(n) {
return graph.outEdges(n).length!=0;
}),
south = comp.filter(function(n) {
return graph.inEdges(n).length!=0;
});
}

// Choose the smaller axis
if (north.length < south.length) {
var tmp = north;
Expand Down Expand Up @@ -693,14 +703,18 @@ function count_crossings(graph, north, south) {
}
reorder.count_crossings = count_crossings;
reorder.barycenter = function(graph, iter, comps) {
var perm = [];
var perms = [[], [], 0];
// Compute the barycenter heuristic on each connected component
if (! comps) {
comps = graph.components();
}
for (var i = 0; i < comps.length; i++)
perm = perm.concat(reorder.barycenter1(graph, comps[i], iter));
return perm;
for (var i = 0; i < comps.length; i++) {
var p = reorder.barycenter1(graph, comps[i], iter);
perms = [ perms[0].concat(p[0]),
perms[1].concat(p[1]),
perms[2]+p[2] ];
}
return perms;
};

// Take the list of neighbor indexes and return the median according to
Expand Down Expand Up @@ -733,8 +747,16 @@ reorder.barycenter1 = function(graph, comp, max_iter) {
layer,
i, v, neighbors;

if (comp.length < 3)
return comp;
layer1 = comp.filter(function(n) {
return graph.outEdges(n).length!=0;
});
layer2 = comp.filter(function(n) {
return graph.inEdges(n).length!=0;
});
if (comp.length < 3) {
return [layer1, layer2,
count_crossings(graph, layer1, layer2)];
}

if (! max_iter)
max_iter = 24;
Expand Down Expand Up @@ -786,7 +808,7 @@ reorder.barycenter1 = function(graph, comp, max_iter) {
else if (d > 0) return 1;
return 0;
});
for (i = 0; i < layer2.length; i++)
for (i = 0; i < layer.length; i++)
nodes[layer[i]].pos = i;
crossings = count_crossings(graph, layer1, layer2);
if (crossings < best_crossings) {
Expand All @@ -796,7 +818,7 @@ reorder.barycenter1 = function(graph, comp, max_iter) {
best_iter = iter;
}
}
console.log('Best iter: '+best_iter);
//console.log('Best iter: '+best_iter);
return [best_layer1, best_layer2, best_crossings];
};
reorder.dijkstra = function(graph) {
Expand Down
2 changes: 1 addition & 1 deletion reorder.v1.min.js

Large diffs are not rendered by default.

28 changes: 20 additions & 8 deletions src/barycenter.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
reorder.barycenter = function(graph, iter, comps) {
var perm = [];
var perms = [[], [], 0];
// Compute the barycenter heuristic on each connected component
if (! comps) {
comps = graph.components();
}
for (var i = 0; i < comps.length; i++)
perm = perm.concat(reorder.barycenter1(graph, comps[i], iter));
return perm;
for (var i = 0; i < comps.length; i++) {
var p = reorder.barycenter1(graph, comps[i], iter);
perms = [ perms[0].concat(p[0]),
perms[1].concat(p[1]),
perms[2]+p[2] ];
}
return perms;
};

// Take the list of neighbor indexes and return the median according to
Expand Down Expand Up @@ -39,8 +43,16 @@ reorder.barycenter1 = function(graph, comp, max_iter) {
layer,
i, v, neighbors;

if (comp.length < 3)
return comp;
layer1 = comp.filter(function(n) {
return graph.outEdges(n).length!=0;
});
layer2 = comp.filter(function(n) {
return graph.inEdges(n).length!=0;
});
if (comp.length < 3) {
return [layer1, layer2,
count_crossings(graph, layer1, layer2)];
}

if (! max_iter)
max_iter = 24;
Expand Down Expand Up @@ -92,7 +104,7 @@ reorder.barycenter1 = function(graph, comp, max_iter) {
else if (d > 0) return 1;
return 0;
});
for (i = 0; i < layer2.length; i++)
for (i = 0; i < layer.length; i++)
nodes[layer[i]].pos = i;
crossings = count_crossings(graph, layer1, layer2);
if (crossings < best_crossings) {
Expand All @@ -102,6 +114,6 @@ reorder.barycenter1 = function(graph, comp, max_iter) {
best_iter = iter;
}
}
console.log('Best iter: '+best_iter);
//console.log('Best iter: '+best_iter);
return [best_layer1, best_layer2, best_crossings];
};
2 changes: 1 addition & 1 deletion src/core.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
reorder = {version: "0.0.2"}; // semver
reorder = {version: "0.0.3"}; // semver

10 changes: 10 additions & 0 deletions src/count_crossings.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ function count_crossings(graph, north, south) {
firstIndex, treeSize, tree, index, weightSum,
invert = false, crosscount;

if (north==undefined) {
var comp = reorder.permutation(graph.nodes().length);
north = comp.filter(function(n) {
return graph.outEdges(n).length!=0;
}),
south = comp.filter(function(n) {
return graph.inEdges(n).length!=0;
});
}

// Choose the smaller axis
if (north.length < south.length) {
var tmp = north;
Expand Down
30 changes: 21 additions & 9 deletions test/barycenter-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,34 @@ var vows = require("vows"),

var suite = vows.describe("reorder.barycenter");

function dotest(mat) {
var graph = reorder.mat2graph(mat, true);
//reorder.printmat(mat);
var initial_crossings = reorder.count_crossings(graph);
var perms = reorder.barycenter(graph);
//console.log('VOrder: %j, HOrder: %j, Crossings: %d',
//perms[1], perms[0], perms[2]);
//reorder.printmat(mat, perms[1], perms[0]);
assert.isTrue(initial_crossings > perms[2]);
}

suite.addBatch({
"barycenter": {
"simple": function() {
var mat = [
[0, 1, 0, 1, 0],
[1, 0, 1, 0, 1],
[0, 1, 0, 1, 1],
[1, 1, 1, 0, 0]],
graph = reorder.mat2graph(mat, true),
expect = [0, 1, 3, 2, 4];
reorder.printmat(mat);
perm = reorder.barycenter(graph);
console.log('VOrder: %j, HOrder: %j, Crossings: %d',
perm[1], perm[0], perm[2]);
reorder.printmat(mat, perm[1], perm[0]);
//assert.deepEqual(perm, expect);
[1, 1, 1, 0, 0]];
dotest(mat);
},
"hard": function() {
for (var i = 10; i < 100; i += 20) {
for (var j = 10; j < 100; j += 20) {
var mat = reorder.randomMatrix(0.2, i, j, false);
dotest(mat);
}
}
}
}
});
Expand Down
18 changes: 17 additions & 1 deletion test/ca-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ Math.seedrandom('reorder');

var suite = vows.describe("reorder.ca");

function inDeltaArray(actual, expected, delta) {
var n = expected.length, i = -1;
if (actual.length !== n) return false;
while (++i < n) if (!inDeltaNumber(actual[i], expected[i], delta)) return false;
return true;
}

function inDeltaNumber(actual, expected, delta) {
var d = Math.abs(actual-expected);
//console.log("d="+d+": "+((d < delta) ? "pass" : "fail"));
return d < delta;
}

suite.addBatch({
"ca": {
"simple": function() {
Expand All @@ -20,7 +33,10 @@ suite.addBatch({
res = reorder.ca(mat, 0.0001);

//assert.isTrue(true);
assert.inDeltaArray(res, [-0.5354605, -0.2626774, 0.8026722], 0.001);
if (!inDeltaArray(res, [-0.5354605, -0.2626774, 0.8026722], 0.001)
&& !inDeltaArray(res, [0.5354605, 0.2626774, -0.8026722], 0.001)) {
assert.fail(actual, expected, message || "expected {actual} to be in within *" + delta + "* of {expected}", null, assert.inDelta);
}
}
}
});
Expand Down
6 changes: 3 additions & 3 deletions test/count_crossings-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function naive_count_crossings(graph, north, south) {
return count;
}

function dohard(mat) {
function dotest(mat) {
var graph = reorder.mat2graph(mat, true),
comps = graph.components(),
comp = comps.reduce(function(a, b) {
Expand Down Expand Up @@ -95,7 +95,7 @@ suite.addBatch({
12);
},
"bug": function() {
dohard([
dotest([
[0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
Expand Down Expand Up @@ -132,7 +132,7 @@ suite.addBatch({
for (var i = 10; i < 100; i += 20) {
for (var j = 10; j < 100; j += 20) {
var mat = reorder.randomMatrix(0.2, i, j, false);
dohard(mat);
dotest(mat);
}
}
}
Expand Down
25 changes: 24 additions & 1 deletion test/graph2mat-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,29 @@ Math.seedrandom('reorder');

var suite = vows.describe("reorder.graph2mat");

function remove_zeroes(mat) {
var i, j;
for (i = mat.length-1; i >= 0; i--) {
var row = mat[i];
if (row.some(function(a) { return a > 0; })) {
//console.log('remove row %d', i);
break;
}
mat.pop();
}
for (j = mat[0].length-1; j >= 0; j--) {
if (mat.some(function(row) {
return row[j] != 0;
})) {
//console.log('remove column %d', j);
break;
}
for (i = 0; i < mat.length; i++)
mat[i].pop();
}

return mat;
}

suite.addBatch({
"graph2mat": {
Expand All @@ -33,7 +56,7 @@ suite.addBatch({
"hard": function() {
for (var i = 10; i < 100; i += 20) {
for (var j = 10; j < 100; j += 20) {
var mat = reorder.randomMatrix(0.2, i, j, false),
var mat = remove_zeroes(reorder.randomMatrix(0.2, i, j, false)),
graph = reorder.mat2graph(mat, true),
m2 = reorder.graph2mat(graph);
assert.deepEqual(m2, mat);
Expand Down

0 comments on commit 50340d9

Please sign in to comment.