diff --git a/reorder.v1.js b/reorder.v1.js index 5ddf05a..9a3e608 100644 --- a/reorder.v1.js +++ b/reorder.v1.js @@ -2746,6 +2746,331 @@ reorder.ca_no_svd = ca_no_svd; reorder.ca = ca_no_svd; +// Implementation of the decorana fortran code + +function decorana(dat) { + var ZEROEIG = 1e-7, // consider as zero eigenvalue + x, y, aidot, adotj, mi, n, s1, + nr = dat.length, + nc = dat[0].length; + + adotj = sumcols(dat); + aidot = sumrows(dat); + //console.log('adotj='); reorder.printvec(adotj); + //console.log('aidot='); reorder.printvec(aidot); + + s1 = eigy(reorder.array1d(nr, 1.0), + reorder.array1d(nc, 1.0), + nr, nc, dat, aidot, adotj); + if (s1.eig < ZEROEIG) { + s1.rows = s1.cols = []; + s1.eig = 0; + } + else { + x = s1.rows; + y = s1.cols; + yxmult(y, x, nr, nc, dat); + for (var i = 0; i < nr; i++) + x[i] /= aidot[i]; + } + return s1; +} + +reorder.ca_decorana = decorana; + +function trans(y, yy, x, aidot, mi, n, dat,prt) { + var i, j, a1; + if (prt) console.log('TRANS '+prt); + yxmult(y,x,mi,n,dat,prt); + for (i = 0; i < mi; i++) { + x[i] = x[i]/aidot[i]; // 10 + } + // 100 + // a1 = 0.0; + // for (i = 0; i < mi; i++) + // a1 += aidot[i]*x[i]; // 110 + // for (i = 0; i < mi; i++) + // x[i] -= a1; // 120 + // 200 + xymult(x,yy,mi,n, dat,prt); +} + +function printvec(y) { + console.log(''); + for (var i = 0; i < y.length; i++) { + console.log('i:'+(i+1)+' v: '+y[i].toFixed(5)); + } +} + +function xymult(x, y, mi, n, dat, prt) { + var i, j, ax, row; + + if (prt) { + console.log('xymult'); + printvec(y,5, null, 'y='); + } + for (j = 0; j < n; j++) + y[j] = 0.0; // 10 + for (i = 0; i < mi; i++) { + ax = x[i]; + row = dat[i]; + for (j = 0; j < n; j++) + y[j] += ax*row[j]; // 20 + } + if (prt) { + //console.log('xymult[1]='); + printvec(y,5, null, 'y='); + } +} + +function yxmult(y,x,mi,n,dat,prt) { + var i, j, ax, row; + if (prt) { + console.log('yxmult'); + printvec(x,5, null, 'x='); + } + for (i = 0; i < mi; i++) { + ax = 0.0; + row = dat[i]; + for (j = 0; j < n; j++) { + ax += y[j]*row[j]; // 10 + } + x[i] = ax; // 20 + } + if (prt) { + //console.log('yxmult[1]='); + printvec(x,5, null, 'x='); + } +} + +function eigy(x, y, mi, n, dat, aidot, adotj) { + var i, j, tot, icount, a, ay, ex, + a11, a12, a22, a23, a33, a34, a44, + res, ax1, ax2, ax3, ax4, + b13, b14, b24, row, + y2 = reorder.zeroes(n), + y3 = reorder.zeroes(n), + y4 = reorder.zeroes(n), + y5 = reorder.zeroes(n), + tol; + + tot = 0.0; + for (j = 0; j < n; j++) { + tot += adotj[j]; + y[j] = j+1.0; // 10 + } + y[0] = 1.1; + tol=0.000005; + trans(y,y,x,aidot,mi,n,dat);//,1); + icount = 0; + while(true) { + // 20 + a = 0.0; + for (j = 0; j < n; j++) + a += y[j]*adotj[j]; // 30 + a /= tot; + ex = 0.0; + for (j = 0; j < n; j++) { + ay = y[j]-a; + ex += ay*ay*adotj[j]; + y[j] = ay; // 40 + } + ex = Math.sqrt(ex); + for (j = 0; j < n; j++) + y[j] /= ex; // 50 + trans(y,y2,x,aidot,mi,n,dat);//,2); + a=0.0; + a11=0.0; + a12=0.0; + a22=0.0; + a23=0.0; + a33=0.0; + a34=0.0; + a44=0.0; + for (j = 0; j < n; j++) { + ay = y2[j]; + y2[j] = ay/adotj[j]; + a += ay; + a11 += ay*y[j]; // 60 + } + a /= tot; + for (j = 0; j < n; j++) { + ay = y2[j]-(a+a11*y[j]); + a12 += ay*ay*adotj[j]; + y2[j] = ay; // 70 + } + a12 = Math.sqrt(a12); + for (j = 0; j < n; j++) + y2[j] /= a12; // 80 + if (a12 < tol || icount > 999) + break; + icount++; + trans(y2,y3,x,aidot,mi,n,dat);//,3); + a = 0.0; + b13 = 0.0; + for (j = 0; j < n; j++) { + ay = y3[j]; + y3[j] = ay/adotj[j]; + a += ay; + a22 +=ay*y2[j]; + b13 += ay*y[j]; // 90 + } + a /= tot; + for (j = 0; j < n; j++) { + ay = y3[j]-(a+a22*y2[j]+b13*y[j]); + a23 += ay*ay*adotj[j]; + y3[j]=ay; // 100 + } + a23=Math.sqrt(a23); + if (a23 > tol) { + // 105 + for (j = 0; j < n; j++) { + y3[j] /= a23; // 110 + } + trans(y3,y4,x,aidot,mi,n,dat);//,4); + a = 0.0; + b14 = 0.0, + b24 = 0.0; + for (j = 0; j < n; j++) { + ay = y4[j]; + y4[j] /= adotj[j]; + a += ay; + a33 += ay*y3[j]; + b14 += ay*y[j]; + b24 += ay*y2[j]; // 120 + } + a /= tot; + for (j = 0; j < n; j++) { + ay = y4[j]-(a+a33*y3[j]+b14*y[j]+b24*y2[j]); + a34 += ay*ay*adotj[j]; + y4[j] = ay; // 130 + } + a34=Math.sqrt(a34); + if(a34 > tol) { + // 135 + for (j = 0; j < n; j++) + y4[j] /= a34; // 140 + trans(y4,y5,x,aidot,mi,n,dat);//,5); + for (j = 0; j < n; j++) + a44 += y4[j]*y5[j]; // 150 + } + else { + a34=0.0; + } + } + else { + a23 = 0.0; + } + // 160 + res = solve_tridiag(tol, a11, a12, a22, a23, a33, a34, a44); + ax1 = res[0]; ax2 = res[1]; ax3 = res[2]; ax4 =res[3]; + // console.log('i '+icount+ + // ' ax1 '+ax1.toFixed(6)+ + // ' ax2 '+ax2.toFixed(6)+ + // ' ax3 '+ax3.toFixed(6)+ + // ' ax4 '+ax4.toFixed(6)); + + // 180 + if(a12 < tol) break; + for (j = 0; j < n; j++) + y[j]= ax1*y[j]+ax2*y2[j]+ax3*y3[j]+ax4*y4[j]; // 190 + // goto 20 + } + // 200 + //console.log('eigenvalue',a11.toFixed(6)); + if (a12 > tol && reorder.debug > 0) { + console.log("residual bigger than tolerance on axis 1"); + } + var aymax = y[0], + aymin = y[0], + sign = 1; + for (j = 1; j < n; j++) { + a = y[j]; + if (a < aymin) + aymin = a; + else if (a > aymax) + aymax = a; + } + if (-aymin > aymax) { + for (j = 0; j < n; j++) // 210 + y[j] = -y[j]; + } + yxmult(y,x,mi,n,dat);//,true); + for (i = 0; i < mi; i++) + x[i] /= aidot[i]; // 220 + // 225 + var axlong = 0.0; + for (i = 0; i < mi; i++) + axlong += aidot[i]*sqr(x[i]); // 230 + axlong = Math.sqrt(axlong); + for (i = 0; i < mi; i++) + x[i] /= axlong; // 240 + for (j = 0; j < n; j++) + y[j] /= axlong; // 250 + var sumsq=0.0, + ax; + for (i = 0; i < mi; i++) { + ax = x[i]; + row = dat[i]; + for (j = 0; j < n; j++) { + sumsq += row[j]*sqr(ax-y[j]); // 255 + } + // 260 + } + var sd = Math.sqrt(sumsq/tot); + if (a11 >= 0.999) { + sd = aymax/axlong; + var sd1 = -aymin/axlong; + if (sd1 > sd) + sd = sd1; + } + // 265 + for (j = 0; j < n; j++) + y[j] /= sd; // 270 + + //printvec(x); + //printvec(y); + return {rows: x, cols: y, eig: a11}; +} + +function sqr(x) { return x*x; } + +function solve_tridiag(tol, a11, a12, a22, a23, a33, a34, a44) { + var ax1=1.0, // 160 + ax2=0.1, + ax3=0.01, + ax4=0.001, + itimes, + axx1, axx2, axx3, axx4, ex, exx, resi; + //console.log('a11:'+a11+' a12:'+a12+' a22:'+a22); + //console.log('a23:'+a23+' a33:'+a33+' a34:'+a34+' a44:'+a44); + for (itimes = 0; itimes < 100; itimes++) { + axx1=a11*ax1+a12*ax2; + axx2=a12*ax1+a22*ax2+a23*ax3; + axx3=a23*ax2+a33*ax3+a34*ax4; + axx4=a34*ax3+a44*ax4; + ax1=a11*axx1+a12*axx2; + ax2=a12*axx1+a22*axx2+a23*axx3; + ax3=a23*axx2+a33*axx3+a34*axx4; + ax4=a34*axx3+a44*axx4; + ex=Math.sqrt(sqr(ax1)+sqr(ax2)+sqr(ax3)+sqr(ax4)); + ax1=ax1/ex; + ax2=ax2/ex; + ax3=ax3/ex; + ax4=ax4/ex; + if((itimes+1)%5 == 0) { + exx=Math.sqrt(ex); + resi=Math.sqrt(sqr(ax1-axx1/exx)+sqr(ax2-axx2/exx)+ + sqr(ax3-axx3/exx)+sqr(ax4-axx4/exx)); + } + if (resi < tol*0.05) + break; + // 170 + } + // 180 + return [ax1, ax2, ax3, ax4]; +} + /*jshint loopfunc:true */ reorder.cuthill_mckee = function(graph, comp) { diff --git a/reorder.v1.min.js b/reorder.v1.min.js index 1c83400..7fb28ed 100644 --- a/reorder.v1.min.js +++ b/reorder.v1.min.js @@ -1,2 +1,2 @@ (function(exports){reorder={version:"0.1.0"};reorder.debug=false;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(++i0)if(!isNaN(v[i]))s+=v[i];return s}reorder.sum=sum;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&&v!=c)order.push(v)})}return order};reorder.mat2graph=function(mat,directed){var n=mat.length,nodes=[],links=[],max_value=Number.NEGATIVE_INFINITY,i,j,v,m;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;function count_in_crossings(graph,v,w,inv){var v_edges=graph.inEdges(v),w_edges=graph.inEdges(w),iv,iw,p0,cross=0;for(iw=0;iwp0)cross++}}return cross}function count_out_crossings(graph,v,w,inv){var v_edges=graph.outEdges(v),w_edges=graph.outEdges(w),iv,iw,p0,cross=0;for(iw=0;iwp0)cross++}}return cross}function adjacent_exchange(graph,layer1,layer2){layer1=layer1.slice();layer2=layer2.slice();var i,v,w,c0,c1,inv_layer1=inverse_permutation(layer1),inv_layer2=inverse_permutation(layer2),swapped=true,improved=0;while(swapped){swapped=false;for(i=0;ic1){layer1[i]=w;layer1[i+1]=v;inv_layer1[w]=i;inv_layer1[v]=i+1;swapped=true;improved+=c0-c1}}for(i=0;ic1){layer2[i]=w;layer2[i+1]=v;inv_layer2[w]=i;inv_layer2[v]=i+1;swapped=true;improved+=c0-c1}}}return[layer1,layer2,improved]}reorder.adjacent_exchange=adjacent_exchange;reorder.barycenter_order=function(graph,comps,max_iter){var orders=[[],[],0];if(!comps){comps=graph.components()}for(var i=0;i0)return 1;return 0};for(layer=layer1,iter=0;iterdist[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_distance_floyd_warshall=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(),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;function floyd_warshall_path(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.floyd_warshall_path=floyd_warshall_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_array=function(n,min,max){var ret=Array(n);if(arguments.length==1){while(n)ret[--n]=Math.random()}else if(arguments.length==2){while(n)ret[--n]=Math.random()*min}else{while(n)ret[--n]=min+Math.random()*(max-min)}return ret};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};reorder.sort_order=function(v){return reorder.permutation(0,v.length).sort(function(a,b){return v[a]-v[b]})};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(reorder.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(reorder.debug>1)reorder.printmat(distanceMatrix);if(reorder.debug>2)reorder.printmat(vector);var perm=ordering().linkage(linkage).distanceMatrix(distanceMatrix)(vector);if(reorder.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=reorder.dot;reorder.covariancetranspose=function(v,a,b){var n=v.length,cov=0,i;for(i=0;i0)v[i]/=norm;return norm}reorder.poweriteration=function(v,eps,init){if(!eps)eps=1e-9;var n=v.length,b,i,j,tmp=Array(n),norm,s=100,e;reorder.assert(n==v[0].length,"poweriteration needs a square matrix");if(!init){b=reorder.random_array(n)}else b=init.slice();normalize(b);while(s-->0){for(i=0;i1-eps)break;var t=tmp;tmp=b;b=t}return tmp};reorder.poweriteration_n=function(v,p,init,eps,start){if(!eps)eps=1e-9;var n=v.length,b=Array(p),i,j,k,l,bk,dot,row,tmp=Array(n),s=100,eigenvalue=Array(p);reorder.assert(n==v[0].length,"poweriteration needs a square matrix");if(!init){for(i=0;i0){for(l=0;l1-eps)break;bk=tmp;tmp=b[k];b[k]=bk}if(reorder.debug)console.log("eig[%d]=%j",k,bk)}return[b,eigenvalue]};function gershgorin_bound(B){var i,j,max=0,n=B.length,t,row;for(i=0;imax)max=t}if(reorder.debug){console.log("gershgorin_bound=%d",max)}return max}function fiedler_vector(B,eps){var g=gershgorin_bound(B),n=B.length,Bhat=B.map(function(row){return row.slice()}),i,j,row;for(i=0;i1){v=vec[i];if(vmax)max=v}scale=(vmax-vmin)/(max-min);for(i=0;i=b){min=max=row[j];break}}for(;jmax)max=v}s=max!=min?1/(max-min):0;for(j=1;j=v)row[j]=row[j]*s-min;else v=NaN}}return ret};function array_to_dicts(data,axes){if(arguments.length<2)axes=reorder.range(data[0].length);var ret=[],row,dict,i,j;for(i=0;iperm.length-negs?-1:1;if(sign==-1){for(i=0;i=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=reorder.dot;reorder.covariancetranspose=function(v,a,b){var n=v.length,cov=0,i;for(i=0;i0)v[i]/=norm;return norm}reorder.poweriteration=function(v,eps,init){if(!eps)eps=1e-9;var n=v.length,b,i,j,tmp=Array(n),norm,s=100,e;reorder.assert(n==v[0].length,"poweriteration needs a square matrix");if(!init){b=reorder.random_array(n)}else b=init.slice();normalize(b);while(s-->0){for(i=0;i1-eps)break;var t=tmp;tmp=b;b=t}return tmp};reorder.poweriteration_n=function(v,p,init,eps,start){if(!eps)eps=1e-9;var n=v.length,b=Array(p),i,j,k,l,bk,dot,row,tmp=Array(n),s=100,eigenvalue=Array(p);reorder.assert(n==v[0].length,"poweriteration needs a square matrix");if(!init){for(i=0;i0){for(l=0;l1-eps)break;bk=tmp;tmp=b[k];b[k]=bk}if(reorder.debug)console.log("eig[%d]=%j",k,bk)}return[b,eigenvalue]};function gershgorin_bound(B){var i,j,max=0,n=B.length,t,row;for(i=0;imax)max=t}if(reorder.debug){console.log("gershgorin_bound=%d",max)}return max}function fiedler_vector(B,eps){var g=gershgorin_bound(B),n=B.length,Bhat=B.map(function(row){return row.slice()}),i,j,row;for(i=0;i1){v=vec[i];if(vmax)max=v}scale=(vmax-vmin)/(max-min);for(i=0;iaymax)aymax=a}if(-aymin>aymax){for(j=0;j=.999){sd=aymax/axlong;var sd1=-aymin/axlong;if(sd1>sd)sd=sd1}for(j=0;j=b){min=max=row[j];break}}for(;jmax)max=v}s=max!=min?1/(max-min):0;for(j=1;j=v)row[j]=row[j]*s-min;else v=NaN}}return ret};function array_to_dicts(data,axes){if(arguments.length<2)axes=reorder.range(data[0].length);var ret=[],row,dict,i,j;for(i=0;iperm.length-negs?-1:1;if(sign==-1){for(i=0;i tol && reorder.debug > 0) { + console.log("residual bigger than tolerance on axis 1"); + } + var aymax = y[0], + aymin = y[0], + sign = 1; + for (j = 1; j < n; j++) { + a = y[j]; + if (a < aymin) + aymin = a; + else if (a > aymax) + aymax = a; + } + if (-aymin > aymax) { + for (j = 0; j < n; j++) // 210 + y[j] = -y[j]; + } + yxmult(y,x,mi,n,dat);//,true); + for (i = 0; i < mi; i++) + x[i] /= aidot[i]; // 220 + // 225 + var axlong = 0.0; + for (i = 0; i < mi; i++) + axlong += aidot[i]*sqr(x[i]); // 230 + axlong = Math.sqrt(axlong); + for (i = 0; i < mi; i++) + x[i] /= axlong; // 240 + for (j = 0; j < n; j++) + y[j] /= axlong; // 250 + var sumsq=0.0, + ax; + for (i = 0; i < mi; i++) { + ax = x[i]; + row = dat[i]; + for (j = 0; j < n; j++) { + sumsq += row[j]*sqr(ax-y[j]); // 255 + } + // 260 + } + var sd = Math.sqrt(sumsq/tot); + if (a11 >= 0.999) { + sd = aymax/axlong; + var sd1 = -aymin/axlong; + if (sd1 > sd) + sd = sd1; + } + // 265 + for (j = 0; j < n; j++) + y[j] /= sd; // 270 + + //printvec(x); + //printvec(y); + return {rows: x, cols: y, eig: a11}; +} + +function sqr(x) { return x*x; } + +function solve_tridiag(tol, a11, a12, a22, a23, a33, a34, a44) { + var ax1=1.0, // 160 + ax2=0.1, + ax3=0.01, + ax4=0.001, + itimes, + axx1, axx2, axx3, axx4, ex, exx, resi; + //console.log('a11:'+a11+' a12:'+a12+' a22:'+a22); + //console.log('a23:'+a23+' a33:'+a33+' a34:'+a34+' a44:'+a44); + for (itimes = 0; itimes < 100; itimes++) { + axx1=a11*ax1+a12*ax2; + axx2=a12*ax1+a22*ax2+a23*ax3; + axx3=a23*ax2+a33*ax3+a34*ax4; + axx4=a34*ax3+a44*ax4; + ax1=a11*axx1+a12*axx2; + ax2=a12*axx1+a22*axx2+a23*axx3; + ax3=a23*axx2+a33*axx3+a34*axx4; + ax4=a34*axx3+a44*axx4; + ex=Math.sqrt(sqr(ax1)+sqr(ax2)+sqr(ax3)+sqr(ax4)); + ax1=ax1/ex; + ax2=ax2/ex; + ax3=ax3/ex; + ax4=ax4/ex; + if((itimes+1)%5 == 0) { + exx=Math.sqrt(ex); + resi=Math.sqrt(sqr(ax1-axx1/exx)+sqr(ax2-axx2/exx)+ + sqr(ax3-axx3/exx)+sqr(ax4-axx4/exx)); + } + if (resi < tol*0.05) + break; + // 170 + } + // 180 + return [ax1, ax2, ax3, ax4]; +} + diff --git a/test/ca-test.js b/test/ca-test.js index 1b7633f..14cf290 100644 --- a/test/ca-test.js +++ b/test/ca-test.js @@ -26,30 +26,24 @@ function compare_order(row_order1, row_order2, msg) { suite.addBatch({ "ca": { "simple": function() { - var mat = reorder.transpose([ + var mat = [ [1, 0, 0, 1, 1, 0, 0, 1], [0, 1, 1, 0, 0, 1, 0, 1], [1, 1, 0, 0, 0, 1, 1, 0], [1, 1, 1, 1, 1, 0, 0, 1], [1, 1, 0, 1, 0, 0, 0, 1], [1, 0, 0, 0, 1, 0, 0, 0] - ]), - res1 = reorder.ca_reciprocal_averaging(mat, null, [100, 0, 100, 0, 100, 0]), - row_order1 = res1[0], - col_order1 = res1[1], - res2 = reorder.ca_no_svd(mat), - row_order2 = res2[0], - col_order2 = res2[1], - ecol = [-1.044914, 0.970130, 1.675125, -0.439146, -0.321923, -1.239397], - erow = [-0.396887, 0.682180, 0.384491, -0.871822, -1.314724, 1.915459, 2.425954, -0.302626], + ], + res2 = reorder.ca_decorana(mat), + row_order2 = res2.rows, + col_order2 = res2.cols, + erow = [-1.044914, 0.970130, 1.675125, -0.439146, -0.321923, -1.239397], + ecol = [-0.396887, 0.682180, 0.384491, -0.871822, -1.314724, 1.915459, 2.425954, -0.302626], i, tmp; - compare_order(row_order1, row_order2, 'ratio between rows RA and no_svd:'); - compare_order(col_order1, col_order2, 'ratio between cols RA and no_svd:'); - compare_order(row_order1, erow, 'ratio between rows RA and svd:'); - compare_order(col_order1, ecol, 'ratio between rows RA and svd:'); - compare_order(row_order2, erow, 'ratio between rows no_svd and svd:'); - compare_order(col_order2, ecol, 'ratio between rows no_svd and svd:'); + reorder.printvec(row_order2, 6); + reorder.printvec(col_order2, 6); + /* assert.inDeltaArray(row_order, [24, 52, 42, 11, 0, 84, 100, 25],