From bd3bcf082ad1b465ecfc40ef8b6f050f049682c1 Mon Sep 17 00:00:00 2001 From: Jean-Daniel Fekete Date: Thu, 23 Apr 2015 10:09:43 -0400 Subject: [PATCH] works --- examples/matrix.js | 166 +++++++++++++++++++-------------- examples/miserables/index.html | 8 +- examples/saclay/index.html | 1 + reorder.v1.js | 123 +++++++++++------------- reorder.v1.min.js | 5 +- src/all_pairs_distance.js | 12 ++- src/graph.js | 10 +- src/mat2graph.js | 12 ++- src/permute.js | 6 +- test/graph2mat-test.js | 2 +- 10 files changed, 181 insertions(+), 164 deletions(-) diff --git a/examples/matrix.js b/examples/matrix.js index 6de41e3..65c6c07 100644 --- a/examples/matrix.js +++ b/examples/matrix.js @@ -45,6 +45,51 @@ function matrix(json) { var dist_adjacency; + var leafOrder = reorder.leafOrder() + .distance(science.stats.distance.manhattan); + + function computeLeaforder() { + var order = leafOrder(adjacency); + + order.forEach(function(lo, i) { + nodes[i].leafOrder = lo; + }); + return nodes.map(function(n) { return n.leafOrder; }); + } + + function computeLeaforderDist() { + if (! dist_adjacency) + dist_adjacency = reorder.graph2valuemats(graph); + + var order = reorder.valuemats_reorder(dist_adjacency, + leafOrder); + + order.forEach(function(lo, i) { + nodes[i].leafOrderDist = lo; + }); + return nodes.map(function(n) { return n.leafOrderDist; }); + + } + + function computeBarycenter() { + var barycenter = reorder.barycenter(graph); + + barycenter[0].forEach(function(lo, i) { + nodes[i].barycenter = lo; + }); + + return nodes.map(function(n) { return n.barycenter; }); + } + + function computeRCM() { + var rcm = reorder.reverse_cuthill_mckee(graph); + rcm.forEach(function(lo, i) { + nodes[i].rcm = lo; + }); + + return nodes.map(function(n) { return n.rcm; }); + } + // Precompute the orders. var orders = { name: d3.range(n).sort(function(a, b) { return d3.ascending(nodes[a].name, nodes[b].name); }), @@ -53,45 +98,10 @@ function matrix(json) { var x = nodes[b].group - nodes[a].group; return (x != 0) ? x : d3.ascending(nodes[a].name, nodes[b].name); }), - leafOrder: function() { - var leafOrder = reorder.leafOrder() - .distance(science.stats.distance.manhattan)(adjacency); - - leafOrder.forEach(function(lo, i) { - nodes[i].leafOrder = lo; - }); - return nodes.map(function(n) { return n.leafOrder; }); - }, - leafOrderDist: function() { - if (! dist_adjacency) - dist_adjacency = reorder.graph2distmat(graph); - - var leafOrder = reorder.leafOrder() - .distance(science.stats.distance.manhattan)(dist_adjacency); - - leafOrder.forEach(function(lo, i) { - nodes[i].leafOrderDist = lo; - }); - return nodes.map(function(n) { return n.leafOrderDist; }); - - }, - barycenter: function() { - var barycenter = reorder.barycenter(graph); - - barycenter[0].forEach(function(lo, i) { - nodes[i].barycenter = lo; - }); - - return nodes.map(function(n) { return n.barycenter; }); - }, - rcm: function() { - var rcm = reorder.reverse_cuthill_mckee(graph); - rcm.forEach(function(lo, i) { - nodes[i].rcm = lo; - }); - - return nodes.map(function(n) { return n.rcm; }); - } + leafOrder: computeLeaforder, + leafOrderDist: computeLeaforderDist, + barycenter: computeBarycenter, + rcm: computeRCM }; // The default sort order. @@ -174,38 +184,50 @@ function matrix(json) { d3.selectAll(".highlight").remove(); } - function order(value) { - var o = orders[value]; - - if (typeof o === "function") { - orders[value] = o.call(); - } - x.domain(orders[value]); + var currentOrder = 'name'; - var t = svg.transition().duration(1500); + function order(value) { + var o = orders[value]; + currentOrder = value; + + if (typeof o === "function") { + orders[value] = o.call(); + } + x.domain(orders[value]); - t.selectAll(".row") - .delay(function(d, i) { return x(i) * 4; }) - .attr("transform", function(d, i) { return "translate(0," + x(i) + ")"; }) - .selectAll(".cell") - .delay(function(d) { return x(d.x) * 4; }) - .attr("x", function(d) { return x(d.x); }); + var t = svg.transition().duration(1500); - t.selectAll(".column") - .delay(function(d, i) { return x(i) * 4; }) - .attr("transform", function(d, i) { return "translate(" + x(i) + ")rotate(-90)"; }); - } + t.selectAll(".row") + .delay(function(d, i) { return x(i) * 4; }) + .attr("transform", function(d, i) { return "translate(0," + x(i) + ")"; }) + .selectAll(".cell") + .delay(function(d) { return x(d.x) * 4; }) + .attr("x", function(d) { return x(d.x); }); + + t.selectAll(".column") + .delay(function(d, i) { return x(i) * 4; }) + .attr("transform", function(d, i) { return "translate(" + x(i) + ")rotate(-90)"; }); + } - function distance(value) { - var leafOrder = reorder.leafOrder().distance(science.stats.distance[value])(adjacency); + function distance(value) { + leafOrder.distance(science.stats.distance[value]); - leafOrder.forEach(function(lo, i) { - nodes[lo].leafOrder = i; - }); - orders.leafOrder = d3.range(n).sort(function(a, b) { - return nodes[b].leafOrder - nodes[a].leafOrder; }); - order("leafOrder"); - d3.select("#order").property("selectedIndex", 3); + if (currentOrder == 'leafOrder') { + orders.leafOrder = computeLeaforder(); + order("leafOrder"); + d3.select("#order").property("selectedIndex", 3); + } + else if (currentOrder == 'leafOrderDist') { + orders.leafOrderDist = computeLeaforderDist(); + order("leafOrderDist"); + d3.select("#order").property("selectedIndex", 3); + } + + // leafOrder.forEach(function(lo, i) { + // nodes[lo].leafOrder = i; + // }); + // orders.leafOrder = d3.range(n).sort(function(a, b) { + // return nodes[b].leafOrder - nodes[a].leafOrder; }); } matrix.order = order; @@ -220,18 +242,18 @@ function matrix(json) { function loadJson(json) { var mat = matrix(json); - mat.timeout = setTimeout(function() { - mat.order("group"); - d3.select("#order").property("selectedIndex", 2).node().focus(); - }, 5000); +// mat.timeout = setTimeout(function() { +// mat.order("group"); +// d3.select("#order").property("selectedIndex", 2).node().focus(); +// }, 5000); d3.select("#order").on("change", function() { - clearTimeout(mat.timeout); +// clearTimeout(mat.timeout); mat.order(this.value); }); d3.select("#distance").on("change", function() { - clearTimeout(mat.timeout); +// clearTimeout(mat.timeout); mat.distance(this.value); }); } diff --git a/examples/miserables/index.html b/examples/miserables/index.html index 9be24f9..7d6bdfb 100644 --- a/examples/miserables/index.html +++ b/examples/miserables/index.html @@ -86,10 +86,10 @@

Les Misérables Co-occurrence

d3.json("miserables.json", function(json) { var mat = matrix(json); - mat.timeout = setTimeout(function() { - mat.order("group"); - d3.select("#order").property("selectedIndex", 2).node().focus(); - }, 5000); + // mat.timeout = setTimeout(function() { + // mat.order("group"); + // d3.select("#order").property("selectedIndex", 2).node().focus(); + // }, 5000); d3.select("#order").on("change", function() { clearTimeout(mat.timeout); diff --git a/examples/saclay/index.html b/examples/saclay/index.html index a3ecfcc..9fd14ed 100644 --- a/examples/saclay/index.html +++ b/examples/saclay/index.html @@ -55,6 +55,7 @@

INRIA Saclay Researchers Co-Authorship Network

+ diff --git a/reorder.v1.js b/reorder.v1.js index 2c983e4..79457d7 100644 --- a/reorder.v1.js +++ b/reorder.v1.js @@ -333,7 +333,6 @@ reorder.graph = function(nodes, links, directed) { linkDistance = 1, edges, inEdges, outEdges, - distances, components; graph.nodes = function(x) { @@ -384,17 +383,17 @@ reorder.graph = function(nodes, links, directed) { (o = links[i]).index = i; if (typeof o.source == "number") o.source = nodes[o.source]; if (typeof o.target == "number") o.target = nodes[o.target]; + if (! ('value' in o)) o.value = 1; ++o.source.weight; ++o.target.weight; } - distances = []; if (typeof linkDistance === "function") for (i = 0; i < m; ++i) - distances[i] = +linkDistance.call(this, links[i], i); + links[i].distance = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) - distances[i] = linkDistance; + links[i].distance = linkDistance; edges = Array(nodes.length); for (i = 0; i < nodes.length; ++i) { @@ -494,7 +493,7 @@ reorder.graph = function(nodes, links, directed) { }; function distance(i) { - return distances[i]; + return links[i].distance; } graph.distance = distance; @@ -559,6 +558,7 @@ reorder.graph = function(nodes, links, directed) { comps.push(ccomp); } } + comps.sort(function(a,b) { return b.length - a.length; }); return comps; } @@ -719,6 +719,7 @@ reorder.mat2graph = function(mat, directed) { var n = mat.length, nodes = [], links = [], + max_value = Number.NEGATIVE_INFINITY, i, j, v, m; for (i = 0; i < n; i++) @@ -726,17 +727,22 @@ reorder.mat2graph = function(mat, directed) { for (i = 0; i < n; i++) { v = mat[i]; - m = directed ? v.length : i+1; - m = Math.min(m, v.length); - for (j = 0; j < m; j++) { + m = (directed) ? 0 : i; + + for (j = m; j < v.length; j++) { if (j == nodes.length) nodes.push({id: j}); if (v[j] != 0) { + if (v[j] > max_value) + max_value = v[j]; links.push({source: i, target: j, value: v[j]}); } } } return reorder.graph(nodes, links, directed) + .linkDistance(function(l, i) { + return 1 + max_value - l.value; + }) .init(); }; reorder.graph2mat = function(graph, directed) { @@ -979,7 +985,7 @@ reorder.all_pairs_distance = function(graph, comps) { function all_pairs_distance_floyd_warshall(graph, comp) { var dist = reorder.infinities(comp.length, comp.length), - a0, edges, + edges, i, j, k, inv; // Floyd Warshall, // see http://ai-depot.com/BotNavigation/Path-AllPairs.html @@ -994,10 +1000,12 @@ function all_pairs_distance_floyd_warshall(graph, comp) { edges = {}; graph.edges(comp[i]).forEach(function(e) { if (e.source == e.target) return; + if (! (e.source.index in inv) + || ! (e.target.index in inv)) + return; // ignore edges outside of comp var u = inv[e.source.index], v = inv[e.target.index]; - dist[u][v] = e.value ? e.value : 1; - dist[v][u] = e.value ? e.value : 1; + dist[v][u] = dist[u][v] = graph.distance(e.index); }); } @@ -1043,10 +1051,10 @@ function floyd_warshall_with_path(graph, comp) { if (e.source == e.target) return; var u = inv[e.source.index], v = inv[e.target.index]; - dist[u][v] = e.value ? e.value : 1; + dist[u][v] = graph.distance(e); next[u][v] = v; if (! directed) { - dist[v][u] = e.value ? e.value : 1; + dist[v][u] = graph.distance(e); next[v][u] = u; } }); @@ -1083,60 +1091,39 @@ reorder.floyd_warshall_path = function(next, u, v) { // Converts a graph with weighted edges (weight in l.value) // into a distance matrix suitable for reordering with e.g. // Optimal Leaf Ordering. -reorder.graph2distmat = function(graph, directed) { - // Transforms the weights into a distance so take the max - var max_link = graph.links() - .reduce(function(a, b) { - if (b.value > a.value) - return b; - return a; - }), - // we don't want a distance of 0 so we add a relative margin - max_value = max_link.value*1.05, - // Transform link values into a normalized distance - links = graph.links() - .map(function(l) { - return { - value: (max_value - l.value)/max_value, - source: l.source.index, - target: l.target.index - }; - }), - // use the origin node as id - nodes = graph.nodes() - .map(function(n) { return {id: n}; }), - // Create the graph structure - graph2 = reorder.graph() - .nodes(nodes) - .links(links) - .init(), - // compute the all_pairs distances for all the - // components - dists = reorder.all_pairs_distance(graph2), - // Compute the graph diameter as max distance - max_dist = dists.reduce(function(a, b) { - return Matm.max(a, reorder.distmax(b)); - }), - // Infinity will be set to 2*the max distance - inf = 2*max_dist, - n = graph.nodes().length, - dist = Array(n), - i, j, k, d, start = 0; - - dist[0] = reorder.array1d(n, inf); - for (i = 1; i < n; i++) - dist[i] = dist[0].slice(); - for (k = 0; k < dists.length; k++) { - d = dists[k]; - for (i = 0; i < d.length; i++) { - for (j = 0; j < dist.length; j++) { - dist[start+i][start+j] = d[i][j]; - dist[start+j][start+i] = d[j][i]; - } + +function distmat2valuemat(distmat) { + var n = distmat.length, + valuemat = reorder.zeroes(n, n), + max_dist = reorder.distmax(distmat), + i, j; + + for (i = 0; i < n; i++) { + for (j = i; j < n; j++) { + valuemat[j][i] = valuemat[i][j] = 1+max_dist - distmat[i][j]; } - start += d.length; } - return dist; + return valuemat; +} +reorder.distmat2valuemat = distmat2valuemat; + +reorder.graph2valuemats = function(graph, comps) { + if (! comps) + comps = graph.components(); + + var dists = reorder.all_pairs_distance(graph, comps); + return dists.map(distmat2valuemat); +}; + +reorder.valuemats_reorder = function(valuemats, leaforder, comps) { + var orders = valuemats.map(leaforder); + + if (comps) { + orders = orders.map(function(d, i) { + return reorder.permute(comps[i], d); + }); + } + return orders.reduce(reorder.flatten); }; reorder.distmax = function (distMatrix) { var max = 0, @@ -1274,11 +1261,11 @@ reorder.random_matrix = function(p, n, m, sym) { return mat; }; -reorder.permute = function(list, indexes) { - var m = indexes.length; +reorder.permute = function(list, perm) { + var m = perm.length; var copy = list.slice(0); while (m--) - copy[m] = list[indexes[m]]; + copy[m] = list[perm[m]]; return copy; }; diff --git a/reorder.v1.min.js b/reorder.v1.min.js index 2156b6a..4275297 100644 --- a/reorder.v1.min.js +++ b/reorder.v1.min.js @@ -1,3 +1,2 @@ -(function(exports){reorder={version:"0.0.4"};reorder.cmp_number_asc=function(a,b){return a-b};reorder.cmp_number=reorder.cmp_number_asc;reorder.cmp_number_desc=function(a,b){return b-a};reorder.flatten=function(a,b){return a.concat(b)};reorder.infinities=function(n){var i=-1,a=[];if(arguments.length===1)while(++i1)s+=v[i];return s};function isNum(a,b){return!(isNaN(a)||isNaN(b)||a==Infinity||b==Infinity)}reorder.distance={euclidean:function(a,b){var i=a.length,s=0,x;while(i-->0){if(isNum(a[i],b[i])){x=a[i]-b[i];s+=x*x}}return Math.sqrt(s)},manhattan:function(a,b){var i=a.length,s=0;while(i-->0){if(isNum(a[i],b[i])){s+=Math.abs(a[i]-b[i])}}return s},minkowski:function(p){return function(a,b){var i=a.length,s=0;while(i-->0){if(isNum(a[i],b[i])){s+=Math.pow(Math.abs(a[i]-b[i]),p)}}return Math.pow(s,1/p)}},chebyshev:function(a,b){var i=a.length,max=0,x;while(i-->0){if(isNum(a[i],b[i])){x=Math.abs(a[i]-b[i]);if(x>max)max=x}}return max},hamming:function(a,b){var i=a.length,d=0;while(i-->0){if(isNum(a[i],b[i])){if(a[i]!==b[i])d++}}return d},jaccard:function(a,b){var n=0,i=a.length,s=0;while(i-->0){if(isNum(a[i],b[i])){if(a[i]===b[i])s++;n++}}if(n==0)return 0;return s/n},braycurtis:function(a,b){var i=a.length,s0=0,s1=0,ai,bi;while(i-->0){ai=a[i];bi=b[i];if(isNum(ai,bi)){s0+=Math.abs(ai-bi);s1+=Math.abs(ai+bi)}}if(s1==0)return 0;return s0/s1}};reorder.range=function(start,stop,step){if(arguments.length<3){step=1;if(arguments.length<2){stop=start;start=0}}var range=[],i=start;if(step<0)for(;i>stop;i+=step)range.push(i);else for(;i=1)return reorder.graph_complete(n,directed);var nodes=graph_empty_nodes(n),links=[],v,w,i,lr,lp;w=-1;lp=Math.log(1-p);if(directed){for(v=0;v=n&&v=v&&v=0&&v!=c)dist[c]=dist[v]+1});return dist};reorder.all_pairs_distance_bfs=function(graph,comps){if(!comps)comps=[graph.nodes_indices()];var nodes=comps.reduce(reorder.flatten).sort(reorder.cmp_number),mat=Array(nodes.length),i,j,dist;for(i=0;i=0;i--){if(graph.inEdges(i).length!=0)break;else rows--}for(i=n-1;i>=0;i--){if(graph.outEdges(i).length!=0)break;else cols--}mat=reorder.zeroes(rows,cols);for(i=0;i0){if(index%2)crosscount+=tree[index+1];index=index-1>>1;tree[index]++}}return crosscount}reorder.count_crossings=count_crossings;reorder.barycenter=function(graph,iter,comps){var perms=[[],[],0];if(!comps){comps=graph.components()}for(var i=0;i0)return 1;return 0});for(i=0;idist[i][k]+dist[k][j]){dist[i][j]=dist[i][k]+dist[k][j];dist[j][i]=dist[i][j]}}}return dist}reorder.all_pairs_distance1=all_pairs_distance_floyd_warshall;function floyd_warshall_with_path(graph,comp){if(!comp)comp=graph.components()[0];var dist=reorder.infinities(comp.length,comp.length),next=Array(comp.length),directed=graph.directed(),edges,i,j,k,inv;inv=inverse_permutation(comp);for(i=0;idist[i][k]+dist[k][j]){dist[i][j]=dist[i][k]+dist[k][j];next[i][j]=next[i][k];if(!directed){dist[j][i]=dist[i][j];next[j][i]=next[k][j]}}}}}return[dist,next]}reorder.floyd_warshall_with_path=floyd_warshall_with_path;reorder.floyd_warshall_path=function(next,u,v){if(next[u][v]==undefined)return[];var path=[u];while(u!=v){u=next[u][v];path.push(u)}return path};reorder.graph2distmat=function(graph,directed){var max_link=graph.links().reduce(function(a,b){if(b.value>a.value)return b;return a}),max_value=max_link.value*1.05,links=graph.links().map(function(l){return{value:(max_value-l.value)/max_value,source:l.source.index,target:l.target.index}}),nodes=graph.nodes().map(function(n){return{id:n}}),graph2=reorder.graph().nodes(nodes).links(links).init(),dists=reorder.all_pairs_distance(graph2),max_dist=dists.reduce(function(a,b){return Matm.max(a,reorder.distmax(b))}),inf=2*max_dist,n=graph.nodes().length,dist=Array(n),i,j,k,d,start=0;dist[0]=reorder.array1d(n,inf);for(i=1;imax)max=row[j]}return max};reorder.distmin=function(distMatrix){var min=Infinity,n=distMatrix.length,i,j,row;for(i=0;i0;)dist[i].splice(n,m-n);return dist};reorder.randomPermute=function(array,i,j){if(arguments.length<3){j=array.length;if(arguments.length<2){i=0}}var m=j-i,t,k;while(m>0){k=i+Math.floor(Math.random()*m--);t=array[i+m];array[i+m]=array[k];array[k]=t}return array};reorder.randomPermutation=function(n){return reorder.randomPermute(reorder.permutation(n))};reorder.random_matrix=function(p,n,m,sym){if(!m)m=n;if(n!=m)sym=false;else if(!sym)sym=true;var mat=reorder.zeroes(n,m),i,j,cnt;if(sym){for(i=0;i0)array[m]=reorder.permute(array[m],indexes);return array};reorder.stablepermute=function(list,indexes){var p=reorder.permute(list,indexes);if(p[0]>p[p.length-1])p.reverse();return p};if(typeof science=="undefined"){science={version:"1.9.1"};science.stats={}}science.stats.hcluster=function(){var distance=reorder.distance.euclidean,linkage="single",distMatrix=null;function hcluster(vectors){var n=vectors.length,dMin=[],cSize=[],clusters=[],c1,c2,c1Cluster,c2Cluster,p,root,i,j,id=0;if(distMatrix==null){distMatrix=[];i=-1;while(++idistMatrix[i][j])dMin[i]=j}}}else{if(distMatrix.lengthdistMatrix[i][j])dMin[i]=j}}}i=-1;while(++idistMatrix[c2][j])distMatrix[j][c1]=distMatrix[c1][j]=distMatrix[c2][j];break;case"complete":if(distMatrix[c1][j]0?i-1:0,j0=j0;k-=2){low=except[k-1];high=except[k];if(high>=j0){if(j0>j){j0=Math.min(j0,low+1);except.splice(k-1,2)}else{high=j0}}else if(low<=i0){if(i0j){if(perm[perm.length-1]!=perm.length-1)perm=perm.reverse();reorder.assert(perm[perm.length-1]==perm.length-1,"Invalid constrained permutation end")}if(i0!=0){perm=reorder.permutation(i0).concat(perm.map(function(v){return v+i0}))}if(orig.length>j0){perm=perm.concat(reorder.range(j0,orig.length))}return perm}function _order_except(){var perm,k,l,low,high,pos;if(except.length==0)return _order_equiv();_compute_dist();for(k=except.length-1;k>0;k-=2){low=except[k-1];high=except[k];distanceMatrix=reorder.dist_remove(distanceMatrix,low+1,high-1);vector.splice(low+1,high-low-2);if(debug)console.log("Except["+low+", "+high+"]");if(distanceMatrix[low][low+1]!=0){distanceMatrix[low][low+1]=distanceMatrix[low+1][low]=-1}}perm=_order_equiv();for(k=0;klow)perm[l]+=high-low-2;else if(perm[l]==low)pos=l}if(pos>0&&perm[pos-1]==high-1){Array.prototype.splice.apply(perm,[pos,0].concat(reorder.range(high-2,low,-1)))}else if(perm[pos+1]==high-1){Array.prototype.splice.apply(perm,[pos+1,0].concat(reorder.range(low+1,high-1)))}else{throw"Range not respected"}}return perm}function _order_equiv(){var perm,row,e,j,k,l,m,n,has_1=false,equiv=[],fix_except={};_compute_dist();for(k=0;kk;){if(row[l]==0){j=distanceMatrix[l].indexOf(-1);if(j!=-1){fix_except[k]=[l,j];distanceMatrix[j][k]=row[j]=-1;has_1=true}e.unshift(l);distanceMatrix=reorder.dist_remove(distanceMatrix,l);vector.splice(l,1)}else if(row[l]<0)has_1=true}if(e.length!=0){e.unshift(k);equiv.push(e)}}if(has_1){for(k=0;k0;){e=equiv[k];l=perm.indexOf(e[0]);m=fix_except[e[0]];if(m&&m[0]==e[0]){l=_fix_exception(perm,l,m[0],m[1],0);m=undefined}for(n=1;n0&&perm[l-1]==next){_swap(perm,l,perm.indexOf(m));return l+1}else if(perm[l+len+1]==next){_swap(perm,l+len,perm.indexOf(m));return l}else throw"Index not found"}function _swap(perm,a,b){if(a==b)return;var c=perm[a];perm[a]=perm[b];perm[b]=c}function _order(){if(debug>1)reorder.printmat(distanceMatrix);if(debug>2)reorder.printmat(vector);var perm=ordering().debug(debug).linkage(linkage).distanceMatrix(distanceMatrix)(vector);if(debug)console.log("Permutation: "+perm);return perm}function _perm_insert(perm,i,nv){perm=perm.map(function(v){return v=b)throw"Invalid list, indices not sorted";return a-b});return order};function _orderExcept(vector,i,j){var distanceMatrix=reorder.dist().distance(distance)(vector);var row,k,l,rev=false,args,pos=-1;distanceMatrix[i][i+1]=0;distanceMatrix[i+1][i]=0;var perm=ordering().distanceMatrix(distanceMatrix)(vector);pos=perm.indexOf(i);for(k=0;ki)perm[k]+=j-i-2}if(pos!=0&&perm[pos-1]==j-1)rev=true;if(rev){perm.reverse();pos=perm.length-pos-1}args=[pos+1,0].concat(reorder.range(i+1,j-1));Array.prototype.splice.apply(perm,args);return perm}order.orderrowsexcept=order.orderexcept;return order};reorder.covariance=science.lin.dot;reorder.covariancetranspose=function(v,a,b){var n=v.length,cov=0,i;for(i=0;i0)v[i]/=norm;return v}reorder.poweriteration=function(v,eps){if(arguments.length<2)eps=1e-4;var n=v.length,b=Array(n),i,j,tmp=Array(n),norm,s=10;reorder.assert(n==v[0].length,"poweriteration needs a square matrix");for(i=0;i0){for(i=0;i1)s+=v[i];return s};function isNum(a,b){return!(isNaN(a)||isNaN(b)||a==Infinity||b==Infinity)}reorder.distance={euclidean:function(a,b){var i=a.length,s=0,x;while(i-->0){if(isNum(a[i],b[i])){x=a[i]-b[i];s+=x*x}}return Math.sqrt(s)},manhattan:function(a,b){var i=a.length,s=0;while(i-->0){if(isNum(a[i],b[i])){s+=Math.abs(a[i]-b[i])}}return s},minkowski:function(p){return function(a,b){var i=a.length,s=0;while(i-->0){if(isNum(a[i],b[i])){s+=Math.pow(Math.abs(a[i]-b[i]),p)}}return Math.pow(s,1/p)}},chebyshev:function(a,b){var i=a.length,max=0,x;while(i-->0){if(isNum(a[i],b[i])){x=Math.abs(a[i]-b[i]);if(x>max)max=x}}return max},hamming:function(a,b){var i=a.length,d=0;while(i-->0){if(isNum(a[i],b[i])){if(a[i]!==b[i])d++}}return d},jaccard:function(a,b){var n=0,i=a.length,s=0;while(i-->0){if(isNum(a[i],b[i])){if(a[i]===b[i])s++;n++}}if(n==0)return 0;return s/n},braycurtis:function(a,b){var i=a.length,s0=0,s1=0,ai,bi;while(i-->0){ai=a[i];bi=b[i];if(isNum(ai,bi)){s0+=Math.abs(ai-bi);s1+=Math.abs(ai+bi)}}if(s1==0)return 0;return s0/s1}};reorder.range=function(start,stop,step){if(arguments.length<3){step=1;if(arguments.length<2){stop=start;start=0}}var range=[],i=start;if(step<0)for(;i>stop;i+=step)range.push(i);else for(;i=1)return reorder.graph_complete(n,directed);var nodes=graph_empty_nodes(n),links=[],v,w,i,lr,lp;w=-1;lp=Math.log(1-p);if(directed){for(v=0;v=n&&v=v&&v=0&&v!=c)dist[c]=dist[v]+1});return dist};reorder.all_pairs_distance_bfs=function(graph,comps){if(!comps)comps=[graph.nodes_indices()];var nodes=comps.reduce(reorder.flatten).sort(reorder.cmp_number),mat=Array(nodes.length),i,j,dist;for(i=0;imax_value)max_value=v[j];links.push({source:i,target:j,value:v[j]})}}}return reorder.graph(nodes,links,directed).linkDistance(function(l,i){return 1+max_value-l.value}).init()};reorder.graph2mat=function(graph,directed){var nodes=graph.nodes(),links=graph.links(),n=nodes.length,i,l,mat;if(!directed)directed=graph.directed();if(directed){var rows=n,cols=n;for(i=n-1;i>=0;i--){if(graph.inEdges(i).length!=0)break;else rows--}for(i=n-1;i>=0;i--){if(graph.outEdges(i).length!=0)break;else cols--}mat=reorder.zeroes(rows,cols);for(i=0;i0){if(index%2)crosscount+=tree[index+1];index=index-1>>1;tree[index]++}}return crosscount}reorder.count_crossings=count_crossings;reorder.barycenter=function(graph,iter,comps){var perms=[[],[],0];if(!comps){comps=graph.components()}for(var i=0;i0)return 1;return 0});for(i=0;idist[i][k]+dist[k][j]){dist[i][j]=dist[i][k]+dist[k][j];dist[j][i]=dist[i][j]}}}return dist}reorder.all_pairs_distance1=all_pairs_distance_floyd_warshall;function floyd_warshall_with_path(graph,comp){if(!comp)comp=graph.components()[0];var dist=reorder.infinities(comp.length,comp.length),next=Array(comp.length),directed=graph.directed(),edges,i,j,k,inv;inv=inverse_permutation(comp);for(i=0;idist[i][k]+dist[k][j]){dist[i][j]=dist[i][k]+dist[k][j];next[i][j]=next[i][k];if(!directed){dist[j][i]=dist[i][j];next[j][i]=next[k][j]}}}}}return[dist,next]}reorder.floyd_warshall_with_path=floyd_warshall_with_path;reorder.floyd_warshall_path=function(next,u,v){if(next[u][v]==undefined)return[];var path=[u];while(u!=v){u=next[u][v];path.push(u)}return path};function distmat2valuemat(distmat){var n=distmat.length,valuemat=reorder.zeroes(n,n),max_dist=reorder.distmax(distmat),i,j;for(i=0;imax)max=row[j]}return max};reorder.distmin=function(distMatrix){var min=Infinity,n=distMatrix.length,i,j,row;for(i=0;i0;)dist[i].splice(n,m-n);return dist};reorder.randomPermute=function(array,i,j){if(arguments.length<3){j=array.length;if(arguments.length<2){i=0}}var m=j-i,t,k;while(m>0){k=i+Math.floor(Math.random()*m--);t=array[i+m];array[i+m]=array[k];array[k]=t}return array};reorder.randomPermutation=function(n){return reorder.randomPermute(reorder.permutation(n))};reorder.random_matrix=function(p,n,m,sym){if(!m)m=n;if(n!=m)sym=false;else if(!sym)sym=true;var mat=reorder.zeroes(n,m),i,j,cnt;if(sym){for(i=0;i0)array[m]=reorder.permute(array[m],indexes);return array};reorder.stablepermute=function(list,indexes){var p=reorder.permute(list,indexes);if(p[0]>p[p.length-1])p.reverse();return p};if(typeof science=="undefined"){science={version:"1.9.1"};science.stats={}}science.stats.hcluster=function(){var distance=reorder.distance.euclidean,linkage="single",distMatrix=null;function hcluster(vectors){var n=vectors.length,dMin=[],cSize=[],clusters=[],c1,c2,c1Cluster,c2Cluster,p,root,i,j,id=0;if(distMatrix==null){distMatrix=[];i=-1;while(++idistMatrix[i][j])dMin[i]=j}}}else{if(distMatrix.lengthdistMatrix[i][j])dMin[i]=j}}}i=-1;while(++idistMatrix[c2][j])distMatrix[j][c1]=distMatrix[c1][j]=distMatrix[c2][j];break;case"complete":if(distMatrix[c1][j]0?i-1:0,j0=j0;k-=2){low=except[k-1];high=except[k];if(high>=j0){if(j0>j){j0=Math.min(j0,low+1);except.splice(k-1,2)}else{high=j0}}else if(low<=i0){if(i0j){if(perm[perm.length-1]!=perm.length-1)perm=perm.reverse();reorder.assert(perm[perm.length-1]==perm.length-1,"Invalid constrained permutation end")}if(i0!=0){perm=reorder.permutation(i0).concat(perm.map(function(v){return v+i0}))}if(orig.length>j0){perm=perm.concat(reorder.range(j0,orig.length))}return perm}function _order_except(){var perm,k,l,low,high,pos;if(except.length==0)return _order_equiv();_compute_dist();for(k=except.length-1;k>0;k-=2){low=except[k-1];high=except[k];distanceMatrix=reorder.dist_remove(distanceMatrix,low+1,high-1);vector.splice(low+1,high-low-2);if(debug)console.log("Except["+low+", "+high+"]");if(distanceMatrix[low][low+1]!=0){distanceMatrix[low][low+1]=distanceMatrix[low+1][low]=-1}}perm=_order_equiv();for(k=0;klow)perm[l]+=high-low-2;else if(perm[l]==low)pos=l}if(pos>0&&perm[pos-1]==high-1){Array.prototype.splice.apply(perm,[pos,0].concat(reorder.range(high-2,low,-1)))}else if(perm[pos+1]==high-1){Array.prototype.splice.apply(perm,[pos+1,0].concat(reorder.range(low+1,high-1)))}else{throw"Range not respected"}}return perm}function _order_equiv(){var perm,row,e,j,k,l,m,n,has_1=false,equiv=[],fix_except={};_compute_dist();for(k=0;kk;){if(row[l]==0){j=distanceMatrix[l].indexOf(-1);if(j!=-1){fix_except[k]=[l,j];distanceMatrix[j][k]=row[j]=-1;has_1=true}e.unshift(l);distanceMatrix=reorder.dist_remove(distanceMatrix,l);vector.splice(l,1)}else if(row[l]<0)has_1=true}if(e.length!=0){e.unshift(k);equiv.push(e)}}if(has_1){for(k=0;k0;){e=equiv[k];l=perm.indexOf(e[0]);m=fix_except[e[0]];if(m&&m[0]==e[0]){l=_fix_exception(perm,l,m[0],m[1],0);m=undefined}for(n=1;n0&&perm[l-1]==next){_swap(perm,l,perm.indexOf(m));return l+1}else if(perm[l+len+1]==next){_swap(perm,l+len,perm.indexOf(m));return l}else throw"Index not found"}function _swap(perm,a,b){if(a==b)return;var c=perm[a];perm[a]=perm[b];perm[b]=c}function _order(){if(debug>1)reorder.printmat(distanceMatrix);if(debug>2)reorder.printmat(vector);var perm=ordering().debug(debug).linkage(linkage).distanceMatrix(distanceMatrix)(vector);if(debug)console.log("Permutation: "+perm);return perm}function _perm_insert(perm,i,nv){perm=perm.map(function(v){return v=b)throw"Invalid list, indices not sorted";return a-b});return order};function _orderExcept(vector,i,j){var distanceMatrix=reorder.dist().distance(distance)(vector);var row,k,l,rev=false,args,pos=-1;distanceMatrix[i][i+1]=0;distanceMatrix[i+1][i]=0;var perm=ordering().distanceMatrix(distanceMatrix)(vector);pos=perm.indexOf(i);for(k=0;ki)perm[k]+=j-i-2}if(pos!=0&&perm[pos-1]==j-1)rev=true;if(rev){perm.reverse();pos=perm.length-pos-1}args=[pos+1,0].concat(reorder.range(i+1,j-1));Array.prototype.splice.apply(perm,args);return perm}order.orderrowsexcept=order.orderexcept;return order};reorder.covariance=science.lin.dot;reorder.covariancetranspose=function(v,a,b){var n=v.length,cov=0,i;for(i=0;i0)v[i]/=norm;return v}reorder.poweriteration=function(v,eps){if(arguments.length<2)eps=1e-4;var n=v.length,b=Array(n),i,j,tmp=Array(n),norm,s=10;reorder.assert(n==v[0].length,"poweriteration needs a square matrix");for(i=0;i0){for(i=0;i max_value) + max_value = v[j]; links.push({source: i, target: j, value: v[j]}); } } } return reorder.graph(nodes, links, directed) + .linkDistance(function(l, i) { + return 1 + max_value - l.value; + }) .init(); }; diff --git a/src/permute.js b/src/permute.js index 95b9475..f61c3df 100644 --- a/src/permute.js +++ b/src/permute.js @@ -1,8 +1,8 @@ -reorder.permute = function(list, indexes) { - var m = indexes.length; +reorder.permute = function(list, perm) { + var m = perm.length; var copy = list.slice(0); while (m--) - copy[m] = list[indexes[m]]; + copy[m] = list[perm[m]]; return copy; }; diff --git a/test/graph2mat-test.js b/test/graph2mat-test.js index 913ff64..2254824 100644 --- a/test/graph2mat-test.js +++ b/test/graph2mat-test.js @@ -1,4 +1,4 @@ -require("science") +require("science"); require("../reorder.v1"); require("../reorder.v1");