#! /usr/bin/gawk -f # Last edited on 1999-07-21 05:20:08 by stolfi # Reads a (symmetric) weight matrix M[i,j] and a list of permutations. # Finds the permutation(s) that minimize the sum over all j>i of # "M[p[i],p[j]]*(j-i-1)^power", for a given "power" (default 0). BEGIN { abort = -1; if (matrixFile == "") { error("must define \"matrixFile\""); } if (power == "") { power = 0; } read_matrix(matrixFile); precompute_power_table(nf); split("", pbest); nb = 0; sbest = 999999999; # "pbest[0..nb-1]" are the best permutations, and "sbest" is their weight. } (abort >= 0) { exit abort; } /^ *$/ { next; } /^[#]/ { next; } /./ { if (NF != 1) { error("bad NF"); } ps = $1; if (length(ps) != nf) { error("wrong length"); } s = compute_score(ps); if (s <= sbest) { if (s < sbest) { nb = 0; sbest = s; } pbest[nb] = ps; nb++; } } END { if (abort >= 0) { exit abort; } printf "score = %d\n", sbest; for (k=0; k "/dev/stderr"; printf "f = " > "/dev/stderr"; for(j=0; j "/dev/stderr"; } printf "\n" > "/dev/stderr"; } function precompute_power_table(nf, d,p) { # Precomputes a table of "pw[d] = d^power", with "d = 0..nf", # for use by compute_score below. By convention 0^0 here is 0 not 1. split("", pw); pw[0] = 0; for (d=1; d<= nf; d++) { if (power == 0) { p = 1; } else if (power == 1) { p = d; } else if (power == 2) { p = d*d; } else { p = exp(log(d)*power); } pw[d] = p; } } function compute_score(ps, i,j,sum,fi,fj) { # The score of a permuted matrix "MP" is the sum of # "MP[i,j]*(i-j-1)^power" for all elements outside the main # diagonal. Note that elements in the two adjacent sub-diagonals # have zero weight. sum = 0; for(i=0; i0 here. if(! ((fi,fj) in M)) { error("bad code in perm"); } sum += M[fi,fj]*pw[j-i-1]; } } return(sum); } function error(msg) { printf "line %d: %s\n", NR, msg > "/dev/stderr"; abort = 1; exit 1; }