#! /usr/bin/gawk -f # Last edited on 1999-07-22 15:16:59 by stolfi # Brute-force traveling salesman problem # # Reads a weight matrix M[a,b] indexed by a list of letters, and a # list of permutations on those letters. Outputs every letter # permutation "p[1..n]" that minimizes the sum "M[p[i-1],p[i]]" over # "i=2..n". BEGIN { abort = -1; if (matrixFile == "") { error("must define \"matrixFile\""); } read_matrix(matrixFile); printf "num elements = %d\n\n", nf; printf "natural score = %.6f\n", compute_score(pz); printf "natural perm = %s\n\n", pz; 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("perm too long"); } # Convert score to integer to avoid fuzzy comparison of # fractional values. s = int(compute_score(ps)*1000000 + 0.5); if (s <= sbest) { if (s < sbest) { nb = 0; sbest = s; } pbest[nb] = ps; nb++; } } END { if (abort >= 0) { exit abort; } printf "best score = %.6f\n", sbest/1000000; printf "best perms =\n"; for (k=0; k "/dev/stderr"; } # printf "\n" > "/dev/stderr"; } function compute_score(ps, i,sum,fa,fb,n) { # The score of permutation "ps" is the sum "M[p[i-1],p[i]]" over # "i=2..n". n = length(ps); if (n == 0) { return 0; } sum = 0; fa = substr(ps,1,1); for(i=2; i<=n; i++) { fb = substr(ps,i,1); if(! ((fa,fb) in M)) { error("bad code in perm"); } sum += M[fa,fb]; fa = fb; } return(sum); } function error(msg) { printf "line %d: %s\n", NR, msg > "/dev/stderr"; abort = 1; exit 1; }