5 /* We want to do multidimensional minimisation.
7 * We don't think there are any local minima. Or at least, if there
8 * are, the local minimum which will be found from the starting
9 * state is the one we want.
11 * We don't want to try to provide a derivative of the cost
12 * function. That's too tedious (and anyway the polynomial
13 * approximation to our our cost function sometimes has high degree
14 * in the inputs which means the quadratic model implied by most of
15 * the gradient descent minimisers is not ideal).
17 * This eliminates most of the algorithms. Nelder and Mead's
18 * simplex algorithm is still available and we will try that.
20 * In our application we are searching for the optimal locations of
21 * N actualvertices in D3 (3) dimensions - ie, we are searching for
22 * the optimal metapoint in an N*D3-dimensional space.
24 * So eg with X=Y=100, the simplex will contain 300 metavertices
25 * each of which is an array of 300 doubles for the actualvertex
26 * coordinates. Hopefully this won't be too slow ...
31 #include <gsl/gsl_errno.h>
32 #include <gsl/gsl_multimin.h>
40 const char *input_file, *best_file;
42 long long evaluations;
43 double stop_epsilon= 1e-20;
45 static void printing_init(void);
47 static gsl_multimin_fminimizer *minimiser;
48 static const char *final_file;
49 static char *final_file_tmp;
51 static double minfunc_f(const gsl_vector *x, void *params) {
54 assert(x->size == DIM);
55 assert(x->stride == 1);
56 map_dimensions(x->data, vs.a);
57 return compute_energy(&vs);
60 static void badusage(void) {
61 fputs("usage: minimise <input> [-i<intermediate>] -o<output\n",stderr);
65 static sig_atomic_t quit_requested;
66 sig_atomic_t quitting_reported_threads;
67 int quitting_last_iteration;
69 static void sigint_handler(int ignored) {
73 int main(int argc, const char *const *argv) {
74 gsl_multimin_function multimin_function;
76 struct Vertices initial_full;
77 double initial_half[DIM], step_size[DIM];
79 gsl_vector initial_gsl, step_size_gsl;
80 int r, i, size_check_counter= 0;
85 if (strncmp(argv[2],"-o",2)) badusage(); best_file= argv[2]+2;
89 if (strncmp(argv[2],"-i",2)) badusage(); best_file= argv[2]+2;
90 if (strncmp(argv[3],"-o",2)) badusage(); final_file= argv[3]+2;
94 if (argv[1][0]=='-') badusage();
96 if (asprintf(&best_file_tmp,"%s.new",best_file) <= 0) diee("asprintf");
98 if (asprintf(&final_file_tmp,"%s.new",final_file) <= 0) diee("asprintf");
100 memset(&sa,0,sizeof(sa));
101 sa.sa_handler= sigint_handler;
102 sa.sa_flags= SA_RESETHAND;
103 r= sigaction(SIGINT,&sa,0);
104 if (r) diee("sigaction SIGINT");
106 graph_layout_prepare();
110 printf("X=%d=0x%x Y=%d=0x%x DIM=%d\n",X,X,Y,Y,DIM);
112 minimiser= gsl_multimin_fminimizer_alloc
113 (gsl_multimin_fminimizer_nmsimplex, DIM);
114 if (!minimiser) { perror("alloc minimiser"); exit(-1); }
116 multimin_function.f= minfunc_f;
117 multimin_function.n= DIM;
118 multimin_function.params= 0;
120 initial_f= fopen(input_file,"rb"); if (!initial_f) diee("fopen initial");
121 errno= 0; r= fread(&initial_full,sizeof(initial_full),1,initial_f);
122 if (r!=1) diee("fread");
125 pmap_dimensions(&initial_full);
126 unmap_dimensions(initial_half,&initial_full);
127 for (i=0; i<DIM; i++) step_size[i]= 0.03;
129 initial_gsl.size= DIM;
130 initial_gsl.stride= 1;
131 initial_gsl.block= 0;
132 initial_gsl.owner= 0;
133 step_size_gsl= initial_gsl;
135 initial_gsl.data= initial_half;
136 step_size_gsl.data= step_size;
138 GA( gsl_multimin_fminimizer_set(minimiser, &multimin_function,
139 &initial_gsl, &step_size_gsl) );
142 if (quit_requested) {
143 fprintf(stderr,"SIGINT caught, quitting soon.\n");
144 quitting_last_iteration= 1;
147 GA( gsl_multimin_fminimizer_iterate(minimiser) );
149 if (!(size_check_counter++ % DIM)) {
150 size= gsl_multimin_fminimizer_size(minimiser);
151 r= gsl_multimin_test_size(size, stop_epsilon);
153 if (printing_check(pr_size,215))
154 printf("r=%2d, size %# e\n", r, size);
157 if (r==GSL_SUCCESS) break;
158 assert(r==GSL_CONTINUE);
161 if (quitting_reported_threads)
166 if (unlink(final_file_tmp) && errno != ENOENT) diee("unlink final .tmp");
167 if (link(best_file,final_file_tmp)) diee("link final .tmp");
168 if (rename(final_file_tmp,final_file)) diee("install final");
170 printf("FINISHED (%lld evaluations)\n",evaluations);
175 /*---------- printing rate limit ----------*/
177 static volatile unsigned print_todo;
178 static sigset_t print_alarmset;
180 int printing_check(enum printing_instance which, int indent) {
181 static int skipped[pr__max];
183 unsigned bits= 1u << which;
186 if (!(print_todo & bits)) {
191 sigprocmask(SIG_BLOCK,&print_alarmset,0);
193 sigprocmask(SIG_UNBLOCK,&print_alarmset,0);
195 printf("%*s",indent,"");
197 if (sk) printf("[%4d] ",sk);
204 static void alarmhandler(int ignored) {
208 static void printing_init(void) {
210 struct itimerval itv;
212 sigemptyset(&print_alarmset);
213 sigaddset(&print_alarmset,SIGALRM);
215 sa.sa_handler= alarmhandler;
216 sa.sa_mask= print_alarmset;
217 sa.sa_flags= SA_RESTART;
218 if (sigaction(SIGALRM,&sa,0)) diee("sigaction ALRM");
220 itv.it_interval.tv_sec= 0;
221 itv.it_interval.tv_usec= 200000;
222 itv.it_value= itv.it_interval;
224 if (setitimer(ITIMER_REAL,&itv,0)) diee("setitimer REAL");