00001 #include <gtk/gtk.h>
00002 #include <stdio.h>
00003 #include <stdlib.h>
00004 #include <string.h>
00005 #include <ctype.h>
00006 #include <list>
00007 #include "callbacks.h"
00008 #include "interface.h"
00009 #include "../../svm.h"
00010 using namespace std;
00011
00012 #define DEFAULT_PARAM "-t 2 -c 100"
00013 #define XLEN 500
00014 #define YLEN 500
00015
00016 GdkColor colors[] =
00017 {
00018 {0,0,0,0},
00019 {0,0,120<<8,120<<8},
00020 {0,120<<8,120<<8,0},
00021 {0,120<<8,0,120<<8},
00022 {0,0,200<<8,200<<8},
00023 {0,200<<8,200<<8,0},
00024 {0,200<<8,0,200<<8},
00025 };
00026
00027 GdkGC *gc;
00028 GdkPixmap *pixmap;
00029 extern "C" GtkWidget *draw_main;
00030 GtkWidget *draw_main;
00031 extern "C" GtkWidget *entry_option;
00032 GtkWidget *entry_option;
00033
00034 typedef struct {
00035 double x, y;
00036 signed char value;
00037 } point;
00038
00039 list<point> point_list;
00040 int current_value = 1;
00041
00042 extern "C" void svm_toy_initialize()
00043 {
00044 gboolean success[7];
00045
00046 gdk_colormap_alloc_colors(
00047 gdk_colormap_get_system(),
00048 colors,
00049 7,
00050 FALSE,
00051 TRUE,
00052 success);
00053
00054 gc = gdk_gc_new(draw_main->window);
00055 pixmap = gdk_pixmap_new(draw_main->window,XLEN,YLEN,-1);
00056 gdk_gc_set_foreground(gc,&colors[0]);
00057 gdk_draw_rectangle(pixmap,gc,TRUE,0,0,XLEN,YLEN);
00058 gtk_entry_set_text(GTK_ENTRY(entry_option),DEFAULT_PARAM);
00059 }
00060
00061 void redraw_area(GtkWidget* widget, int x, int y, int w, int h)
00062 {
00063 gdk_draw_pixmap(widget->window,
00064 gc,
00065 pixmap,
00066 x,y,x,y,w,h);
00067 }
00068
00069 void draw_point(const point& p)
00070 {
00071 gdk_gc_set_foreground(gc,&colors[p.value+3]);
00072 gdk_draw_rectangle(pixmap, gc, TRUE,int(p.x*XLEN),int(p.y*YLEN),4,4);
00073 gdk_draw_rectangle(draw_main->window, gc, TRUE,int(p.x*XLEN),int(p.y*YLEN),4,4);
00074 }
00075
00076 void draw_all_points()
00077 {
00078 for(list<point>::iterator p = point_list.begin(); p != point_list.end();p++)
00079 draw_point(*p);
00080 }
00081
00082 void clear_all()
00083 {
00084 point_list.clear();
00085 gdk_gc_set_foreground(gc,&colors[0]);
00086 gdk_draw_rectangle(pixmap,gc,TRUE,0,0,XLEN,YLEN);
00087 redraw_area(draw_main,0,0,XLEN,YLEN);
00088 }
00089
00090 void
00091 on_button_change_clicked (GtkButton *button,
00092 gpointer user_data)
00093 {
00094 ++current_value;
00095 if(current_value > 3) current_value = 1;
00096 }
00097
00098 void
00099 on_button_run_clicked (GtkButton *button,
00100 gpointer user_data)
00101 {
00102
00103 if(point_list.empty()) return;
00104
00105 svm_parameter param;
00106 int i,j;
00107
00108
00109 param.svm_type = C_SVC;
00110 param.kernel_type = RBF;
00111 param.degree = 3;
00112 param.gamma = 0;
00113 param.coef0 = 0;
00114 param.nu = 0.5;
00115 param.cache_size = 100;
00116 param.C = 1;
00117 param.eps = 1e-3;
00118 param.p = 0.1;
00119 param.shrinking = 1;
00120 param.probability = 0;
00121 param.nr_weight = 0;
00122 param.weight_label = NULL;
00123 param.weight = NULL;
00124
00125
00126 const char *p = gtk_entry_get_text(GTK_ENTRY(entry_option));
00127
00128 while (1) {
00129 while (*p && *p != '-')
00130 p++;
00131
00132 if (*p == '\0')
00133 break;
00134
00135 p++;
00136 switch (*p++) {
00137 case 's':
00138 param.svm_type = atoi(p);
00139 break;
00140 case 't':
00141 param.kernel_type = atoi(p);
00142 break;
00143 case 'd':
00144 param.degree = atoi(p);
00145 break;
00146 case 'g':
00147 param.gamma = atof(p);
00148 break;
00149 case 'r':
00150 param.coef0 = atof(p);
00151 break;
00152 case 'n':
00153 param.nu = atof(p);
00154 break;
00155 case 'm':
00156 param.cache_size = atof(p);
00157 break;
00158 case 'c':
00159 param.C = atof(p);
00160 break;
00161 case 'e':
00162 param.eps = atof(p);
00163 break;
00164 case 'p':
00165 param.p = atof(p);
00166 break;
00167 case 'h':
00168 param.shrinking = atoi(p);
00169 break;
00170 case 'b':
00171 param.probability = atoi(p);
00172 break;
00173 case 'w':
00174 ++param.nr_weight;
00175 param.weight_label = (int *)realloc(param.weight_label,sizeof(int)*param.nr_weight);
00176 param.weight = (double *)realloc(param.weight,sizeof(double)*param.nr_weight);
00177 param.weight_label[param.nr_weight-1] = atoi(p);
00178 while(*p && !isspace(*p)) ++p;
00179 param.weight[param.nr_weight-1] = atof(p);
00180 break;
00181 }
00182 }
00183
00184
00185 svm_problem prob;
00186
00187 prob.l = point_list.size();
00188 prob.y = new double[prob.l];
00189
00190 if(param.kernel_type == PRECOMPUTED)
00191 {
00192 }
00193 else if(param.svm_type == EPSILON_SVR ||
00194 param.svm_type == NU_SVR)
00195 {
00196 if(param.gamma == 0) param.gamma = 1;
00197 svm_node *x_space = new svm_node[2 * prob.l];
00198 prob.x = new svm_node *[prob.l];
00199
00200 i = 0;
00201 for (list <point>::iterator q = point_list.begin(); q != point_list.end(); q++, i++)
00202 {
00203 x_space[2 * i].index = 1;
00204 x_space[2 * i].value = q->x;
00205 x_space[2 * i + 1].index = -1;
00206 prob.x[i] = &x_space[2 * i];
00207 prob.y[i] = q->y;
00208 }
00209
00210
00211 svm_model *model = svm_train(&prob, ¶m);
00212 svm_node x[2];
00213 x[0].index = 1;
00214 x[1].index = -1;
00215 int *j = new int[XLEN];
00216
00217 for (i = 0; i < XLEN; i++)
00218 {
00219 x[0].value = (double) i / XLEN;
00220 j[i] = (int)(YLEN*svm_predict(model, x));
00221 }
00222
00223 gdk_gc_set_foreground(gc,&colors[0]);
00224 gdk_draw_line(pixmap,gc,0,0,0,YLEN-1);
00225 gdk_draw_line(draw_main->window,gc,0,0,0,YLEN-1);
00226
00227 int p = (int)(param.p * YLEN);
00228 for(i = 1; i < XLEN; i++)
00229 {
00230 gdk_gc_set_foreground(gc,&colors[0]);
00231 gdk_draw_line(pixmap,gc,i,0,i,YLEN-1);
00232 gdk_draw_line(draw_main->window,gc,i,0,i,YLEN-1);
00233
00234 gdk_gc_set_foreground(gc,&colors[5]);
00235 gdk_draw_line(pixmap,gc,i-1,j[i-1],i,j[i]);
00236 gdk_draw_line(draw_main->window,gc,i-1,j[i-1],i,j[i]);
00237
00238 if(param.svm_type == EPSILON_SVR)
00239 {
00240 gdk_gc_set_foreground(gc,&colors[2]);
00241 gdk_draw_line(pixmap,gc,i-1,j[i-1]+p,i,j[i]+p);
00242 gdk_draw_line(draw_main->window,gc,i-1,j[i-1]+p,i,j[i]+p);
00243
00244 gdk_gc_set_foreground(gc,&colors[2]);
00245 gdk_draw_line(pixmap,gc,i-1,j[i-1]-p,i,j[i]-p);
00246 gdk_draw_line(draw_main->window,gc,i-1,j[i-1]-p,i,j[i]-p);
00247 }
00248 }
00249
00250 svm_free_and_destroy_model(&model);
00251 delete[] j;
00252 delete[] x_space;
00253 delete[] prob.x;
00254 delete[] prob.y;
00255 }
00256 else
00257 {
00258 if(param.gamma == 0) param.gamma = 0.5;
00259 svm_node *x_space = new svm_node[3 * prob.l];
00260 prob.x = new svm_node *[prob.l];
00261
00262 i = 0;
00263 for (list <point>::iterator q = point_list.begin(); q != point_list.end(); q++, i++)
00264 {
00265 x_space[3 * i].index = 1;
00266 x_space[3 * i].value = q->x;
00267 x_space[3 * i + 1].index = 2;
00268 x_space[3 * i + 1].value = q->y;
00269 x_space[3 * i + 2].index = -1;
00270 prob.x[i] = &x_space[3 * i];
00271 prob.y[i] = q->value;
00272 }
00273
00274
00275 svm_model *model = svm_train(&prob, ¶m);
00276 svm_node x[3];
00277 x[0].index = 1;
00278 x[1].index = 2;
00279 x[2].index = -1;
00280
00281 for (i = 0; i < XLEN; i++)
00282 for (j = 0; j < YLEN; j++) {
00283 x[0].value = (double) i / XLEN;
00284 x[1].value = (double) j / YLEN;
00285 double d = svm_predict(model, x);
00286 if (param.svm_type == ONE_CLASS && d<0) d=2;
00287 gdk_gc_set_foreground(gc,&colors[(int)d]);
00288 gdk_draw_point(pixmap,gc,i,j);
00289 gdk_draw_point(draw_main->window,gc,i,j);
00290 }
00291
00292 svm_free_and_destroy_model(&model);
00293 delete[] x_space;
00294 delete[] prob.x;
00295 delete[] prob.y;
00296 }
00297 free(param.weight_label);
00298 free(param.weight);
00299 draw_all_points();
00300 }
00301
00302 void
00303 on_button_clear_clicked (GtkButton *button,
00304 gpointer user_data)
00305 {
00306 clear_all();
00307 }
00308
00309 void
00310 on_window1_destroy (GtkObject *object,
00311 gpointer user_data)
00312 {
00313 gtk_exit(0);
00314 }
00315
00316 gboolean
00317 on_draw_main_button_press_event (GtkWidget *widget,
00318 GdkEventButton *event,
00319 gpointer user_data)
00320 {
00321 point p = {(double)event->x/XLEN, (double)event->y/YLEN, current_value};
00322 point_list.push_back(p);
00323 draw_point(p);
00324 return FALSE;
00325 }
00326
00327 gboolean
00328 on_draw_main_expose_event (GtkWidget *widget,
00329 GdkEventExpose *event,
00330 gpointer user_data)
00331 {
00332 redraw_area(widget,
00333 event->area.x, event->area.y,
00334 event->area.width, event->area.height);
00335 return FALSE;
00336 }
00337
00338 GtkWidget *fileselection;
00339 static enum { SAVE, LOAD } fileselection_flag;
00340
00341 void show_fileselection()
00342 {
00343 fileselection = create_fileselection();
00344 gtk_signal_connect_object(
00345 GTK_OBJECT(GTK_FILE_SELECTION(fileselection)->ok_button),
00346 "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy),
00347 (GtkObject *) fileselection);
00348
00349 gtk_signal_connect_object (GTK_OBJECT
00350 (GTK_FILE_SELECTION(fileselection)->cancel_button),
00351 "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy),
00352 (GtkObject *) fileselection);
00353
00354 gtk_widget_show(fileselection);
00355 }
00356
00357 void
00358 on_button_save_clicked (GtkButton *button,
00359 gpointer user_data)
00360 {
00361 fileselection_flag = SAVE;
00362 show_fileselection();
00363 }
00364
00365
00366 void
00367 on_button_load_clicked (GtkButton *button,
00368 gpointer user_data)
00369 {
00370 fileselection_flag = LOAD;
00371 show_fileselection();
00372 }
00373
00374 void
00375 on_filesel_ok_clicked (GtkButton *button,
00376 gpointer user_data)
00377 {
00378 gtk_widget_hide(fileselection);
00379 const char *filename = gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
00380
00381 if(fileselection_flag == SAVE)
00382 {
00383 FILE *fp = fopen(filename,"w");
00384
00385 const char *p = gtk_entry_get_text(GTK_ENTRY(entry_option));
00386 const char* svm_type_str = strstr(p, "-s ");
00387 int svm_type = C_SVC;
00388 if(svm_type_str != NULL)
00389 sscanf(svm_type_str, "-s %d", &svm_type);
00390
00391 if(fp)
00392 {
00393 if(svm_type == EPSILON_SVR || svm_type == NU_SVR)
00394 {
00395 for(list<point>::iterator p = point_list.begin(); p != point_list.end();p++)
00396 fprintf(fp,"%f 1:%f\n", p->y, p->x);
00397 }
00398 else
00399 {
00400 for(list<point>::iterator p = point_list.begin(); p != point_list.end();p++)
00401 fprintf(fp,"%d 1:%f 2:%f\n", p->value, p->x, p->y);
00402 }
00403 fclose(fp);
00404 }
00405
00406 }
00407 else if(fileselection_flag == LOAD)
00408 {
00409 FILE *fp = fopen(filename,"r");
00410 if(fp)
00411 {
00412 clear_all();
00413 char buf[4096];
00414 while(fgets(buf,sizeof(buf),fp))
00415 {
00416 int v;
00417 double x,y;
00418 if(sscanf(buf,"%d%*d:%lf%*d:%lf",&v,&x,&y)==3)
00419 {
00420 point p = {x,y,v};
00421 point_list.push_back(p);
00422 }
00423 else if(sscanf(buf,"%lf%*d:%lf",&y,&x)==2)
00424 {
00425 point p = {x,y,current_value};
00426 point_list.push_back(p);
00427 }
00428 else
00429 break;
00430 }
00431 fclose(fp);
00432 draw_all_points();
00433 }
00434 }
00435 }
00436
00437 void
00438 on_fileselection_destroy (GtkObject *object,
00439 gpointer user_data)
00440 {
00441 }
00442
00443 void
00444 on_filesel_cancel_clicked (GtkButton *button,
00445 gpointer user_data)
00446 {
00447 }