chiark / gitweb /
curveopt: try simple, but no good
[moebius3.git] / findcurve.c
1 /*
2  */
3
4 #include <math.h>
5 #include <string.h>
6 #include <assert.h>
7
8 #include <gsl/gsl_errno.h>
9 #include <gsl/gsl_sf.h>
10 #include <gsl/gsl_siman.h>
11 #include <gsl/gsl_randist.h>
12 #include <gsl/gsl_multimin.h>
13
14 #include "symbolic.c"
15
16 #define J_END_COL(i) \
17   for (j=0; j<PN; j++) gsl_matrix_set(J,i,j,J_COL[j]);
18
19 static inline _Bool IS_SMALL(double v) {
20   return v < 1E6;
21 }
22
23 static inline double sinc(double x) {
24   return gsl_sf_sinc(x / M_PI);
25 }
26
27 static int NP;
28 static double *INPUT; /* dyanmic array, on main's stack */
29 static double PREP[NPREP];
30
31 #define GET_X(xg)                                       \
32   double X[NX];                                         \
33   ({ int get_x_i;                                       \
34      for (get_x_i=0; get_x_i<NX; get_x_i++)             \
35        X[get_x_i] = gsl_vector_get(xg, get_x_i);        \
36   })
37
38 static void printcore(const double *X) {
39   int i, j;
40   DECLARE_F_G;
41   CALCULATE_F_G;
42   printf("[");
43   for (i=0; i<NP; i++)
44     for (j=0; j<3; j++)
45       printf(" %25.18g,", POINT(i)[j]);
46   printf(" ]\n");
47 }
48
49 static void prepare(double X[] /* startpoint */) {
50   /* fills in PREP and startpoint */
51   PREPARE;
52 }
53
54 //#define DEBUG
55
56 static double cb_f(const gsl_vector *xg, void *params) {
57   int P;
58
59   GET_X(xg);
60
61   DECLARE_F_G;
62   CALCULATE_F_G;
63
64 #ifdef DEBUG
65   int i,j;
66   printf(" Efunc\n");
67   for (j=0; j<3; j++) {
68     for (P=0; P<NP; P++)
69       printf(" %7.4f", POINT(P)[j]);
70     printf("\n");
71   }
72   printf("             ");
73 #endif
74
75   CALCULATE_COST;
76   return cost;
77 }
78
79 static void __attribute__((unused))  cb_step(const gsl_rng *rng, void *xp, double step_size) {
80   double *x = xp;
81   int i;
82   double step[NX];
83   gsl_ran_dir_nd(rng, NX, step);
84   for (i=0; i<NX; i++)
85     x[i] += step_size * step[i];
86   //printf("\n cb_step %p %10.7f [", xp, step_size);
87   //for (i=0; i<N; i++) printf(" %10.7f,", step[i]);
88   //printf("]\n");
89 }
90
91 static double __attribute__((unused))  cb_metric(void *xp, void *yp) {
92   const double *x=xp, *y=yp;
93   int i;
94   double s;
95   for (i=0, s=0; i<NX; i++) {
96     double d = x[i] - y[i];
97     s += d*d;
98   }
99   return sqrt(s);
100 }
101
102 static void __attribute__((unused)) cb_print(gsl_vector *xp) {
103   GET_X(xp);
104   printf("\n");
105   printcore(X);
106 }
107
108 static double scan1double(void) {
109   double v;
110   int r;
111
112   r = scanf("%lf",&v);
113   if (ferror(stdin)) { perror("stdin"); exit(-1); }
114   if (feof(stdin)) exit(0);
115   if (r!=1) { fputs("bad input\n",stderr); exit(-1); }
116   return v;
117 }
118
119 int main(int argc, const char *const *argv) {
120   double epsilon;
121   int i, r;
122
123   NP = atoi(argv[1]);
124   epsilon = atof(argv[2]);
125
126   double startpoint_X[NX];
127   double input[NINPUT]; INPUT = input;
128
129   gsl_multimin_function func = {
130     .f = cb_f,
131     .n = NX,
132     .params = 0,
133   };
134
135   gsl_vector *current_gx = gsl_vector_alloc(NX);
136   gsl_vector *step_size = gsl_vector_alloc(NX);
137   gsl_vector_set_all(step_size, 0.01);
138
139   gsl_multimin_fminimizer *minimiser =
140     gsl_multimin_fminimizer_alloc(gsl_multimin_fminimizer_nmsimplex2rand, NX);
141
142   for (;;) {
143     /* NINPUT + 1 doubles: startpoint, epsilon for residual */
144     for (i=0; i<NINPUT; i++)
145       INPUT[i] = scan1double();
146
147     prepare(startpoint_X);
148     for (i=0; i<NX; i++)
149       gsl_vector_set(current_gx, i, startpoint_X[i]);
150
151     r = gsl_multimin_fminimizer_set(minimiser, &func, current_gx, step_size);
152     assert(!r);
153
154     for (;;) {
155       r = gsl_multimin_fminimizer_iterate(minimiser);
156       assert(!r);
157
158       //cb_print(current_gx);
159
160       double size = gsl_multimin_fminimizer_size(minimiser);
161       //printf(" size=%10.7f\n", size);
162
163       if (size < epsilon) break;
164     }      
165
166     cb_print(current_gx);
167
168     printf("[]\n");
169     fflush(stdout);
170   }
171 }