X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=energy.c;h=4f66e6c0aa6b3a253d7e0eda715d6a510126d494;hb=f5c44e57feae26a81c416d9d7cc69f0accbac8b6;hp=db13fbffcf866a23b87d308914bcc8362b9e6728;hpb=23c346bb18366c8e9509743aacc5d777bd7f85cb;p=moebius2.git diff --git a/energy.c b/energy.c index db13fbf..4f66e6c 100644 --- a/energy.c +++ b/energy.c @@ -13,15 +13,14 @@ static double best_energy= DBL_MAX; static void addcost(double *energy, double tweight, double tcost, int pr); #define COST(weight, compute) addcost(&energy, (weight), (compute), printing) -double density; - void energy_init(void) { - density= sqrt(N); } /*---------- main energy computation and subroutines ----------*/ double compute_energy(const struct Vertices *vs) { + static int bests_unprinted; + double energy; int printing; @@ -31,13 +30,19 @@ double compute_energy(const struct Vertices *vs) { printing= printing_check(pr_cost,0); - if (printing) printf("cost > energy |"); + if (printing) printf("%15lld c>e |", evaluations); - COST(2.25e3, line_bending_adjcost(vs->a)); - COST(1e3, edge_length_variation_cost(vs->a)); - COST(0.2e3, rim_proximity_cost(vs->a)); -// COST(1e2, graph_layout_cost(vs->a)); - COST(1e8, noncircular_rim_cost(vs->a)); +#if YBITS==3 + COST( 3e2, line_bending_cost(vs->a)); + COST( 1e3, edge_length_variation_cost(vs->a)); + COST( 0.2e3, rim_proximity_cost(vs->a)); + COST( 1e8, noncircular_rim_cost(vs->a)); +#else + COST( 3e3, line_bending_cost(vs->a)); + COST( 1e4, edge_length_variation_cost(vs->a)); + COST( 0.2e3, rim_proximity_cost(vs->a)); + COST( 1e8, noncircular_rim_cost(vs->a)); +#endif if (printing) printf("| total %# e |", energy); @@ -45,12 +50,18 @@ double compute_energy(const struct Vertices *vs) { FILE *best_f; int r; - if (printing) printf(" BEST"); + if (printing) { + printf(" BEST"); + if (bests_unprinted) printf(" [%4d]",bests_unprinted); + bests_unprinted= 0; + } else { + bests_unprinted++; + } - best_f= fopen(output_file_tmp,"wb"); if (!best_f) diee("fopen new out"); + best_f= fopen(best_file_tmp,"wb"); if (!best_f) diee("fopen new out"); r= fwrite(vs->a,sizeof(vs->a),1,best_f); if (r!=1) diee("fwrite"); if (fclose(best_f)) diee("fclose new best"); - if (rename(output_file_tmp,output_file)) diee("rename install new best"); + if (rename(best_file_tmp,best_file)) diee("rename install new best"); best_energy= energy; } @@ -59,12 +70,13 @@ double compute_energy(const struct Vertices *vs) { flushoutput(); } + evaluations++; return energy; } static void addcost(double *energy, double tweight, double tcost, int pr) { double tenergy= tweight * tcost; - if (pr) printf(" %# e x %# e > %# e* |", tcost, tweight, tenergy); + if (pr) printf(" %# e x %g > %# e* |", tcost, tweight, tenergy); *energy += tenergy; } @@ -138,26 +150,12 @@ void compute_vertex_areas(const Vertices vertices) { * is nonnegative. We add epsilon to |AxB| to avoid division * by zero. * - * Normalisation: - * - * We want the answer to remain unchanged when the vertices lie - * on circles. Interposing M and N so that we have P-M-Q-N-R - * generates half as much delta for each vertex. So - * - * , -1 - * cost = D . cost - * Q,e Q,e - * - * where D is the linear density. - * - * , -1 - * Sigma cost = N . D . Sigma cost - * Q,e Q,e Q,e Q,e - * - * + * r + * cost = delta + * Q,e */ -double line_bending_adjcost(const Vertices vertices) { +double line_bending_cost(const Vertices vertices) { static const double axb_epsilon= 1e-6; static const double exponent_r= 3; @@ -176,24 +174,33 @@ double line_bending_adjcost(const Vertices vertices) { double delta= atan2(magnD(axb) + axb_epsilon, dotprod(a,b)); double cost= pow(delta,exponent_r); - if (!e && !(qi & YMASK)) + if (!e && !(qi & ~XMASK)) cost *= 10; total_cost += cost; } - return total_cost / (N / density); + return total_cost; } /*---------- edge length variation ----------*/ + /* + * Definition: + * + * See the diagram above. + * r + * cost = ( |PQ| - |QR| ) + * Q,e + */ + double edge_length_variation_cost(const Vertices vertices) { - double diff, cost= 0; - int v0, efwd,vfwd, eback; + double diff, cost= 0, exponent_r= 2; + int q, e,r, eback; - FOR_EDGE(v0,efwd,vfwd) { - eback= edge_reverse(v0,efwd); - diff= edge_lengths[v0][efwd] - edge_lengths[v0][eback]; - cost += diff*diff; + FOR_EDGE(q,e,r) { + eback= edge_reverse(q,e); + diff= edge_lengths[q][e] - edge_lengths[q][eback]; + cost += pow(diff,exponent_r); } return cost; }