SVM.cpp
上传用户:sanxfzhen
上传日期:2014-12-28
资源大小:2324k
文件大小:133k
源码类别:

多国语言处理

开发平台:

Visual C++

  1. // SVM.cpp: implementation of the CSVM class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "SVM.h"
  6. #include "Message.h"
  7. # include <stdio.h>
  8. # include <ctype.h>
  9. # include <math.h>
  10. # include <string.h>
  11. # include <stdlib.h>
  12. # include <time.h> 
  13. # include <float.h>
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char THIS_FILE[]=__FILE__;
  17. #define new DEBUG_NEW
  18. #endif
  19. extern CCompute_Prompt com_pro;
  20. extern CCompute_Param com_param;
  21. extern CCompute_Result com_result;
  22. # define VERSION       "V3.50"
  23. # define VERSION_DATE  "01.11.00"
  24. # define PRIMAL_OPTIMAL      1
  25. # define DUAL_OPTIMAL        2
  26. # define MAXITER_EXCEEDED    3
  27. # define NAN_SOLUTION        4
  28. # define ONLY_ONE_VARIABLE   5
  29. # define LARGEROUND          0
  30. # define SMALLROUND          1
  31. # define DEF_PRECISION          1E-5
  32. # define DEF_MAX_ITERATIONS     200
  33. # define DEF_LINDEP_SENSITIVITY 1E-8
  34. # define EPSILON_HIDEO          1E-20
  35. # define EPSILON_EQ             1E-5
  36. CSVM theSVM;
  37. //////////////////////////////////////////////////////////////////////
  38. // Construction/Destruction
  39. //////////////////////////////////////////////////////////////////////
  40. CSVM::CSVM()
  41. {
  42. precision_violations=0;
  43. opt_precision=DEF_PRECISION;
  44. maxiter=DEF_MAX_ITERATIONS;
  45. lindep_sensitivity=DEF_LINDEP_SENSITIVITY;
  46. smallroundcount=0;
  47. }
  48. CSVM::~CSVM()
  49. {
  50. }
  51. /***************************svm_learn_main****************************/
  52. void CSVM::set_learn_parameters(LEARN_PARM* learn_parm,KERNEL_PARM* kernel_parm)
  53. {
  54.   learn_parm->biased_hyperplane=com_param.biased_Hyperplane;
  55.   learn_parm->remove_inconsistent=com_param.remove_inconsitant;
  56.   learn_parm->skip_final_opt_check=com_param.final_test;
  57.   learn_parm->svm_maxqpsize=com_param.maximum_size;
  58.   learn_parm->svm_newvarsinqp=com_param.new_variable;
  59.   learn_parm->svm_iter_to_shrink=com_param.iteration_time;
  60.   learn_parm->svm_c=com_param.C;
  61.   learn_parm->transduction_posratio=com_param.fraction;
  62.   learn_parm->svm_costratio=com_param.cost_factor;
  63.   learn_parm->svm_costratio_unlab=1.0;
  64.   learn_parm->svm_unlabbound=1E-5;
  65.   learn_parm->epsilon_crit=0.001;
  66.   learn_parm->epsilon_a=1E-15;
  67.   learn_parm->compute_loo=com_param.loo;
  68.   learn_parm->rho=com_param.rho;
  69.   learn_parm->xa_depth=com_param.search_depth;
  70.   kernel_parm->kernel_type=com_param.kernel_type;
  71.   kernel_parm->poly_degree=com_param.poly_degree;
  72.   kernel_parm->rbf_gamma=com_param.rbf_gamma;
  73.   kernel_parm->coef_lin=com_param.poly_s;
  74.   kernel_parm->coef_const=com_param.poly_c;
  75.   //strcpy(kernel_parm->custom,com_param.);
  76. }
  77. int CSVM::svm_learn_main (int pos_label)
  78. {  
  79.   DOC *docs;  /* training examples */
  80.   long *label,max_docs,max_words_doc;
  81.   long totwords,totdoc,ll,i;
  82.   KERNEL_CACHE kernel_cache;
  83.   LEARN_PARM learn_parm;
  84.   KERNEL_PARM kernel_parm;
  85.   MODEL model;
  86.   char docfile[200];
  87.   char modelfile[200];
  88.   
  89.   if (com_pro.show_action)
  90.   printm("begin to compute");
  91.   if (com_pro.show_action)
  92. printm("Scanning examples...");
  93.   set_learn_parameters(&learn_parm,&kernel_parm);
  94.   strcpy(docfile,com_param.trainfile);
  95.   strcpy(modelfile,com_param.modelfile);
  96. //  kernel_cache_size=com_param.cache_size;
  97.   nol_ll(docfile,&max_docs,&max_words_doc,&ll); /* scan size of input file */
  98.   max_words_doc+=2;
  99.   ll+=2;
  100.   max_docs+=2;
  101.   docs = (DOC *)my_malloc(sizeof(DOC)*max_docs);
  102.   label = (long *)my_malloc(sizeof(long)*max_docs);
  103.   
  104.   read_documents(docfile,docs,label,max_words_doc,ll,&totwords,&totdoc,pos_label);
  105.   if(kernel_parm.kernel_type == LINEAR) /* don't need the cache */
  106.   { 
  107.     svm_learn(docs,label,totdoc,totwords,&learn_parm,&kernel_parm,NULL,&model);
  108.   }
  109.   else 
  110.   {
  111.     kernel_cache_init(&kernel_cache,totdoc,com_param.cache_size);
  112.     svm_learn(docs,label,totdoc,totwords,&learn_parm,&kernel_parm,&kernel_cache,&model);
  113.     kernel_cache_cleanup(&kernel_cache);
  114.   }
  115.   write_model(modelfile,&model);
  116.   free(model.supvec);
  117.   free(model.alpha);
  118.   free(model.index);
  119.   for(i=0;i<totdoc;i++) 
  120.     free(docs[i].words);
  121.   free(docs);
  122.   free(label);
  123.   if (com_pro.show_action)
  124. printm("Cease to compute");
  125.   return(0);
  126. }
  127. /********************************svm_learn_main****************************/
  128. /********************************svm_classify****************************/
  129. double CSVM::svm_classify(DOC &doc)
  130. {
  131. long llsv,max_sv,max_words_sv,pred_format,j;
  132. double sim=0;
  133. MODEL model; 
  134. char modelfile[MAX_PATH];
  135. strcpy(modelfile,com_param.modelfile);
  136. pred_format=0;
  137. // scan size of model file
  138. nol_ll(modelfile,&max_sv,&max_words_sv,&llsv);
  139. max_words_sv+=2;
  140. llsv+=2;
  141. model.supvec = (DOC **)my_malloc(sizeof(DOC *)*max_sv);
  142. model.alpha = (double *)my_malloc(sizeof(double)*max_sv);
  143. read_model(modelfile,&model,max_words_sv,llsv);
  144. doc.twonorm_sq=sprod_ss(doc.words,doc.words);
  145. if(model.kernel_parm.kernel_type == 0) 
  146. {   // linear kernel, compute weight vector
  147. add_weight_vector_to_linear_model(&model);
  148. for(j=0;(doc.words[j]).wnum != 0;j++) 
  149. {  
  150. // Check if feature numbers are not larger than in    
  151. // model. Remove feature if necessary.
  152. if((doc.words[j]).wnum>model.totwords) 
  153. (doc.words[j]).wnum=0;              
  154. }                                        
  155. sim=classify_example_linear(&model,&doc);
  156. }
  157. // non-linear kernel
  158. else sim=classify_example(&model,&doc);
  159. free(model.supvec);
  160. free(model.alpha);
  161. //linear kernel
  162. if(model.kernel_parm.kernel_type == 0) free(model.lin_weights);
  163. return sim;
  164. }
  165. int CSVM::svm_classify(int post_label, double* weight)
  166. {
  167. DOC doc;   /* test example */
  168. long max_docs,max_words_doc,lld,llsv;
  169. long max_sv,max_words_sv,totdoc=0,doc_label;
  170. long wnum,pred_format;
  171. long j;
  172. char *line; 
  173. FILE *docfl;
  174. MODEL model; 
  175. char docfile[MAX_PATH];
  176. char modelfile[MAX_PATH];
  177. strcpy(docfile,com_param.classifyfile);
  178. strcpy(modelfile,com_param.modelfile);
  179. pred_format=0;
  180. nol_ll(docfile,&max_docs,&max_words_doc,&lld); /* scan size of input file */
  181. max_words_doc+=2;
  182. lld+=2;
  183. nol_ll(modelfile,&max_sv,&max_words_sv,&llsv); /* scan size of model file */
  184. max_words_sv+=2;
  185. llsv+=2;
  186. model.supvec = (DOC **)my_malloc(sizeof(DOC *)*max_sv);
  187. model.alpha = (double *)my_malloc(sizeof(double)*max_sv);
  188. line = (char *)my_malloc(sizeof(char)*lld);
  189. doc.words = (SVM_WORD *)my_malloc(sizeof(SVM_WORD)*(max_words_doc+10));
  190. read_model(modelfile,&model,max_words_sv,llsv);
  191. /* linear kernel */
  192. /* compute weight vector */
  193. if(model.kernel_parm.kernel_type == 0)
  194. add_weight_vector_to_linear_model(&model);
  195. }
  196. if (com_pro.show_action)
  197. printm("Classifying test examples..");
  198. if ((docfl = fopen (docfile, "r")) == NULL)
  199. {
  200. printe(docfile);
  201. return -1;
  202. }
  203. //chen 10.9.2001
  204. while((!feof(docfl)) && fgets(line,(int)lld,docfl)) 
  205. {
  206. if(line[0] == '#') continue;  /* line contains comments */
  207. parse_document(line,&doc,&doc_label,&wnum,max_words_doc);
  208. if(model.kernel_parm.kernel_type == 0) 
  209. {   /* linear kernel */
  210. for(j=0;(doc.words[j]).wnum != 0;j++) 
  211. {  /* Check if feature numbers are not larger than in    
  212.  model. Remove feature if necessary.  */
  213. if((doc.words[j]).wnum>model.totwords) 
  214. (doc.words[j]).wnum=0;              
  215. }                                        
  216. weight[totdoc]=classify_example_linear(&model,&doc);
  217. }
  218. else /* non-linear kernel */                        
  219. weight[totdoc]=classify_example(&model,&doc);
  220. totdoc++;
  221. }  
  222. free(line);
  223. free(doc.words);
  224. free(model.supvec);
  225. free(model.alpha);
  226. if(model.kernel_parm.kernel_type == 0) 
  227. { /* linear kernel */
  228. free(model.lin_weights);
  229. }
  230. return(0);
  231. }
  232. /********************************svm_classify****************************/
  233. /********************************svm_common****************************/
  234. double CSVM::classify_example(MODEL *model,DOC *ex)
  235. {
  236. register long i;
  237. register double dist;
  238. dist=0;
  239. for(i=1;i<model->sv_num;i++) {  
  240. dist+=kernel(&model->kernel_parm,model->supvec[i],ex)*model->alpha[i];
  241. }
  242. return(dist-model->b);
  243. }
  244. /*    classifies example for linear kernel 
  245. important: the model must have the linear weight vector computed 
  246. important: the feature numbers in the example to classify must 
  247. not be larger than the weight vector!               */
  248. double CSVM::classify_example_linear(MODEL *model,DOC *ex)
  249. {
  250. return((double)(sprod_ns(model->lin_weights,ex->words)-model->b));
  251. }
  252. /* calculate the kernel function */
  253. CFLOAT CSVM::kernel(KERNEL_PARM *kernel_parm,DOC *a,DOC*b)
  254. {
  255. com_result.kernel_cache_statistic++;
  256. switch(kernel_parm->kernel_type)
  257. {
  258.     case 0: /* linear */ 
  259. return((CFLOAT)sprod_ss(a->words,b->words)); 
  260.     case 1: /* polynomial */
  261. return((CFLOAT)pow(kernel_parm->coef_lin*sprod_ss(a->words,b->words)+kernel_parm->coef_const,(double)kernel_parm->poly_degree)); 
  262.     case 2: /* radial basis function */
  263. return((CFLOAT)exp(-kernel_parm->rbf_gamma*(a->twonorm_sq-2*sprod_ss(a->words,b->words)+b->twonorm_sq)));
  264.     case 3: /* sigmoid neural net */
  265. return((CFLOAT)tanh(kernel_parm->coef_lin*sprod_ss(a->words,b->words)+kernel_parm->coef_const)); 
  266.     case 4: /* custom-kernel supplied in file kernel.h*/
  267. return((CFLOAT)custom_kernel(kernel_parm,a,b)); 
  268. //chen .test sum of 
  269. //return((CFLOAT)pow(kernel_parm->coef_lin*sprod_ss(a->words,b->words)+kernel_parm->coef_const,(double)kernel_parm->poly_degree)+exp(-kernel_parm->rbf_gamma*(a->twonorm_sq-2*sprod_ss(a->words,b->words)+b->twonorm_sq))); 
  270.     default: sprintf(temstr,"Error: Unknown kernel function");
  271. printm(temstr);
  272. return (-1);
  273. }
  274. }
  275. /* compute the inner product of two sparse vectors */
  276. double CSVM::sprod_ss(SVM_WORD *a,SVM_WORD*b)
  277. {
  278.     register FVAL sum=0;
  279.     register SVM_WORD *ai,*bj;
  280.     ai=a;
  281.     bj=b;
  282.     while (ai->wnum && bj->wnum) {
  283. if(ai->wnum > bj->wnum) {
  284. bj++;
  285. }
  286. else if (ai->wnum < bj->wnum) {
  287. ai++;
  288. }
  289. else {
  290. sum+=ai->weight * bj->weight;
  291. ai++;
  292. bj++;
  293. }
  294.     }
  295.     return((double)sum);
  296. }
  297. /* compute the inner product of two sparse vectors,b right shit 1 bit */
  298. double CSVM::sprod_ss1(SVM_WORD *a,SVM_WORD*b,int offset)
  299. {
  300.     register FVAL sum=0;
  301.     register SVM_WORD *ai,*bj;
  302.     ai=a;
  303.     bj=b;
  304.     while (ai->wnum && bj->wnum) {
  305. if(ai->wnum > bj->wnum+offset) {
  306. bj++;
  307. }
  308. else if (ai->wnum < bj->wnum+offset) {
  309. ai++;
  310. }
  311. else 
  312. {
  313. int np=(ai->wnum-1)%16+1+offset;
  314. if (np>0 && np<17) 
  315. sum+=ai->weight * bj->weight;
  316. ai++;
  317. bj++;
  318. }
  319.     }
  320.     return((double)sum);
  321. }
  322. double CSVM::sprod_ss2(SVM_WORD *a,SVM_WORD*b,int offset)
  323. {
  324.     register FVAL sum=0;
  325.     register SVM_WORD *ai,*bj;
  326.     ai=a;
  327.     bj=b;
  328.     while (ai->wnum && bj->wnum) {
  329. if(ai->wnum > bj->wnum+offset) {
  330. bj++;
  331. }
  332. else if (ai->wnum < bj->wnum+offset) {
  333. ai++;
  334. }
  335. else 
  336. {
  337. int np=ai->wnum+offset;
  338. if (np>0 && np<257) 
  339. sum+=ai->weight * bj->weight;
  340. ai++;
  341. bj++;
  342. }
  343.     }
  344.     return((double)sum);
  345. }
  346. /* compute length of weight vector */
  347. double CSVM::model_length_s(MODEL *model,KERNEL_PARM *kernel_parm)
  348. {
  349. register long i,j;
  350. register double sum=0,alphai;
  351. register DOC *supveci;
  352. for(i=1;i<model->sv_num;i++) {  
  353. alphai=model->alpha[i];
  354. supveci=model->supvec[i];
  355. for(j=1;j<model->sv_num;j++) {
  356. sum+=alphai*model->alpha[j]
  357. *kernel(kernel_parm,supveci,model->supvec[j]);
  358. }
  359. }
  360. return(sqrt(sum));
  361. }
  362. void CSVM::clear_vector_n(double *vec,long n)
  363. {
  364. register long i;
  365. for(i=0;i<=n;i++) vec[i]=0;
  366. }
  367. void CSVM::add_vector_ns(double *vec_n,SVM_WORD *vec_s,double faktor)
  368. {
  369. register SVM_WORD *ai;
  370. ai=vec_s;
  371. while (ai->wnum) {
  372. vec_n[ai->wnum]+=(faktor*ai->weight);
  373. ai++;
  374. }
  375. }
  376. double CSVM::sprod_ns(double *vec_n,SVM_WORD *vec_s)
  377. {
  378. register double sum=0;
  379. register SVM_WORD *ai;
  380. ai=vec_s;
  381. while (ai->wnum) {
  382. sum+=(vec_n[ai->wnum]*ai->weight);
  383. ai++;
  384. }
  385. return(sum);
  386. }
  387. /* compute weight vector in linear case and add to model*/
  388. void CSVM::add_weight_vector_to_linear_model(MODEL *model)
  389. {
  390. long i;
  391. model->lin_weights=(double *)my_malloc(sizeof(double)*(model->totwords+1));
  392. clear_vector_n(model->lin_weights,model->totwords);
  393. for(i=1;i<model->sv_num;i++) {
  394. add_vector_ns(model->lin_weights,(model->supvec[i])->words,
  395. model->alpha[i]);
  396. }
  397. }
  398. int CSVM::read_model(char *modelfile,MODEL *model,long max_words,long ll)
  399. {
  400. FILE *modelfl;
  401. long j,i;
  402. char *line;
  403. SVM_WORD *words;
  404. register long wpos;
  405. long wnum,pos;
  406. double weight;
  407. char version_buffer[100];
  408. if (com_pro.show_action)
  409. {
  410. sprintf(temstr,"Reading model..."); 
  411. printm(temstr); 
  412. }
  413. words = (SVM_WORD *)my_malloc(sizeof(SVM_WORD)*(max_words+10));
  414. line = (char *)my_malloc(sizeof(char)*ll);
  415. if ((modelfl = fopen (modelfile, "r")) == NULL)
  416. {
  417. printe (modelfile);  
  418. return -1;
  419. }
  420. fscanf(modelfl,"SVM-light Version %sn",version_buffer);
  421. if(strcmp(version_buffer,VERSION)) 
  422. {
  423. printe ("Version of model-file does not match version of svm_classify!"); 
  424. return -1;
  425. }
  426. fscanf(modelfl,"%ld # kernel typen",&(model->kernel_parm.kernel_type));
  427. fscanf(modelfl,"%ld # kernel parameter -d n",&(model->kernel_parm.poly_degree));
  428. fscanf(modelfl,"%lf # kernel parameter -g n",&(model->kernel_parm.rbf_gamma));
  429. fscanf(modelfl,"%lf # kernel parameter -s n",&(model->kernel_parm.coef_lin));
  430. fscanf(modelfl,"%lf # kernel parameter -r n",&(model->kernel_parm.coef_const));
  431. fscanf(modelfl,"%s # kernel parameter -u n",&(model->kernel_parm.custom));
  432. fscanf(modelfl,"%ld # highest feature index n",&(model->totwords));
  433. fscanf(modelfl,"%ld # number of training documents n",&(model->totdoc));
  434. fscanf(modelfl,"%ld # number of support vectors plus 1 n",&(model->sv_num));
  435. fscanf(modelfl,"%lf # threshold b n",&(model->b));
  436. for(i=1;i<model->sv_num;i++) 
  437. {
  438. fgets(line,(int)ll,modelfl);
  439. pos=0;
  440. wpos=0;
  441. sscanf(line,"%lf",&model->alpha[i]);
  442. while(line[++pos]>' ');
  443. while((sscanf(line+pos,"%ld:%lf",&wnum,&weight) != EOF) && (wpos<max_words)) 
  444. {
  445. while(line[++pos]>' ');
  446. words[wpos].wnum=wnum;
  447. words[wpos].weight=weight; 
  448. wpos++;
  449. model->supvec[i] = (DOC *)my_malloc(sizeof(DOC));
  450. (model->supvec[i])->words = (SVM_WORD *)my_malloc(sizeof(SVM_WORD)*(wpos+1));
  451. for(j=0;j<wpos;j++)
  452. {
  453. (model->supvec[i])->words[j]=words[j]; 
  454. }
  455. ((model->supvec[i])->words[wpos]).wnum=0;
  456. (model->supvec[i])->twonorm_sq = sprod_ss((model->supvec[i])->words,(model->supvec[i])->words);
  457. (model->supvec[i])->docnum = -1;
  458. }
  459. fclose(modelfl);
  460. free(line);
  461. free(words);
  462. if (com_pro.show_readfile)
  463. {
  464. sprintf(temstr, "OK. (%d support vectors read)",(int)(model->sv_num-1));
  465. printm(temstr);
  466. }
  467. }
  468. /*read the data from text documents*/
  469. int CSVM::read_documents(char *docfile,
  470. DOC  *docs,
  471. long *label,
  472. long max_words_doc,
  473. long ll,
  474. long *totwords,
  475. long *totdoc,
  476. int post_label)
  477. {
  478. char *line;
  479. DOC doc;
  480. long dnum=0,wpos,i,dpos=0,dneg=0,dunlab=0;
  481. long doc_label;
  482. FILE *docfl;
  483. line = (char *)my_malloc(sizeof(char)*ll);
  484. if ((docfl = fopen (docfile, "r")) == NULL)
  485. printe (docfile);  
  486. return -1;
  487. }
  488. doc.words = (SVM_WORD *)my_malloc(sizeof(SVM_WORD)*(max_words_doc+10));
  489. if (com_pro.show_readfile)
  490. {
  491. sprintf(temstr,"Reading examples into memory..."); 
  492. printm(temstr);
  493. }
  494. dnum=0;
  495. (*totwords)=0;
  496. while((!feof(docfl)) && fgets(line,(int)ll,docfl)) {
  497. if(line[0] == '#') continue;  /* line contains comments */
  498. if(!parse_document(line,&doc,&doc_label,&wpos,max_words_doc)) 
  499. {
  500. sprintf(temstr,"Parsing error in line %ld!",dnum);
  501. printm(temstr);
  502. }
  503. if(doc_label==0)
  504. {
  505. label[dnum]=0;
  506. dunlab++;
  507. }
  508. else if(doc_label==post_label)
  509. {
  510. label[dnum]=1;
  511. dpos++;
  512. }
  513. else
  514. {
  515. label[dnum]=-1;
  516. dneg++;
  517. }
  518. if((wpos>1) && ((doc.words[wpos-2]).wnum>(*totwords))) 
  519. (*totwords)=(doc.words[wpos-2]).wnum;
  520. docs[dnum].words = (SVM_WORD *)my_malloc(sizeof(SVM_WORD)*wpos);
  521. docs[dnum].docnum=dnum;
  522. for(i=0;i<wpos;i++) 
  523. docs[dnum].words[i]=doc.words[i];
  524. docs[dnum].twonorm_sq=doc.twonorm_sq;
  525. dnum++;  
  526. if((dnum % 100) == 0&&com_pro.show_readfile) 
  527. {
  528. sprintf(temstr,"read %ld..",dnum); 
  529. printm(temstr);
  530. }
  531. fclose(docfl);
  532. free(line);
  533. free(doc.words);
  534. if (com_pro.show_action)
  535. {
  536. sprintf(temstr, "OK. (%ld examples read)", dnum);
  537. printm(temstr);
  538. sprintf(temstr,"%ld positive, %ld negative, and %ld unlabeled examples.",dpos,dneg,dunlab); 
  539. printm(temstr);
  540. }
  541. (*totdoc)=dnum;
  542. }
  543. /*Parse one  line of data file */
  544. int CSVM::parse_document(char *line,DOC *doc,long *label,long*numwords,long max_words_doc)
  545. {
  546. register long wpos,pos;
  547. long wnum;
  548. double weight;
  549. pos=0;
  550. while(line[pos]) 
  551. {      /* cut off comments */
  552. if(line[pos] == '#') 
  553. {
  554. line[pos]=0;
  555. }
  556. else 
  557. {
  558. pos++;
  559. }
  560. }
  561. wpos=0;
  562. if((sscanf(line,"%ld",label)) == EOF) return(0);
  563. pos=0;
  564. while(line[pos]==' ') pos++;
  565. while(line[pos]>' ') pos++;
  566. while((sscanf(line+pos,"%ld:%lf",&wnum,&weight) != EOF) &&  (wpos<max_words_doc))
  567. {
  568. while(line[pos++]==' ');
  569. while(line[++pos]>' ');
  570. if(wnum<=0) 
  571. printe ("Feature numbers must be larger or equal to 1!!!"); 
  572. sprintf(temstr,"LINE: %s",line);
  573. printm(temstr);
  574. return (0);
  575.  
  576. }
  577. if((wpos>0) && ((doc->words[wpos-1]).wnum >= wnum))
  578. printe ("Features must be in increasing order!!!"); 
  579. sprintf(temstr,"LINE: %s",line);
  580. printm(temstr);
  581. return (0);
  582.  
  583. }
  584. (doc->words[wpos]).wnum=wnum;
  585. (doc->words[wpos]).weight=weight; 
  586. wpos++;
  587. }
  588. (doc->words[wpos]).wnum=0;
  589. (*numwords)=wpos+1;
  590. doc->docnum=-1;
  591. doc->twonorm_sq=sprod_ss(doc->words,doc->words);
  592. return(1);
  593. }
  594. /* grep through file and count number of lines, 
  595. maximum number of spaces per line, and 
  596. longest line. */
  597. int CSVM::nol_ll(char *file,long *nol,long *wol,long *ll) 
  598. {
  599. FILE *fl;
  600. int ic;
  601. char c;
  602. long current_length,current_wol;
  603. if ((fl = fopen (file, "r")) == NULL)
  604. printe (file);   
  605. return -1;
  606. }
  607. current_length=0;
  608. current_wol=0;
  609. (*ll)=0;
  610. (*nol)=1;
  611. (*wol)=0;
  612. while((ic=getc(fl)) != EOF) 
  613. {
  614. c=(char)ic;
  615. current_length++;
  616. if(c == ' ') 
  617. {
  618. current_wol++;
  619. }
  620. if(c == 'n') 
  621. {
  622. (*nol)++;
  623. if(current_length>(*ll)) 
  624. {
  625. (*ll)=current_length;
  626. }
  627. if(current_wol>(*wol)) 
  628. {
  629. (*wol)=current_wol;
  630. }
  631. current_length=0;
  632. current_wol=0;
  633. }
  634. }
  635. fclose(fl);
  636. }
  637. long CSVM::minl(long a,long b)
  638. {
  639. if(a<b)
  640. return(a);
  641. else
  642. return(b);
  643. }
  644. long CSVM::maxl(long a,long b)
  645. {
  646. if(a>b)
  647. return(a);
  648. else
  649. return(b);
  650. }
  651. long CSVM::get_runtime() 
  652. {
  653. clock_t start;
  654. start = clock();
  655. return((long)((double)start*100.0/(double)CLOCKS_PER_SEC));
  656. }
  657. int CSVM::isnan(double a)
  658. {
  659. return(_isnan(a));
  660. }
  661. void * CSVM::my_malloc(long size) 
  662. {
  663. void *ptr;
  664. ptr=(void *)malloc(size);
  665. if(!ptr)
  666. printe ("Out of memory!"); 
  667. return (NULL);
  668. }
  669. return(ptr);
  670. }
  671. //print error on screen
  672. void CSVM::printe(char* pInfo)
  673. {
  674. CMessage::PrintError(pInfo);
  675. }
  676. //print message on screen
  677. void CSVM::printm(char* pInfo)
  678. {
  679. CMessage::PrintInfo(pInfo);
  680. }
  681. //custom kernel function
  682. /////////////////////////////////////////////////////////////////
  683. //chen 2001.09.14
  684. /////////////////////////////////////////////////////////////////
  685. double CSVM::ktt(int ta,int tb,double pa[],double pb[])
  686. {
  687. int ya,yb;
  688. ya=((ta-1)%13)+1;
  689. yb=((tb-1)%13)+1;
  690. if (ya<13&&yb<13) 
  691. return pa[ta]*pa[ta+1]*pb[tb]*pb[tb+1];
  692. else return 0.0;
  693. }
  694. double CSVM::kt(int t,double ta[],double tb[])
  695. {
  696. int x,y;
  697. double sum=0.0;
  698. x=((t-1)/16)+1;
  699. y=((t-1)%16)+1;
  700. if (x>1) 
  701. sum+=ta[t]*tb[t]*ta[t-16]*tb[t-16];
  702. if (x>2) 
  703. sum+=ta[t]*tb[t]*ta[t-32]*tb[t-32];
  704. if (x>3) 
  705. sum+=ta[t]*tb[t]*ta[t-48]*tb[t-48];
  706. if (x<14) 
  707. sum+=ta[t]*tb[t]*ta[t-48]*tb[t-48];
  708. if (x<15) 
  709. sum+=ta[t]*tb[t]*ta[t-32]*tb[t-32];
  710. if (x<16)
  711. sum+=ta[t]*tb[t]*ta[t+16]*tb[t+16];
  712. if (y>3) 
  713. sum+=ta[t]*tb[t]*ta[t-3]*tb[t-3];
  714. if (y>2) 
  715. sum+=ta[t]*tb[t]*ta[t-2]*tb[t-2];
  716. if (y>1) 
  717. sum+=ta[t]*tb[t]*ta[t-1]*tb[t-1];
  718. if (y<14) 
  719. sum+=ta[t]*tb[t]*ta[t+3]*tb[t+3];
  720. if (y<15) 
  721. sum+=ta[t]*tb[t]*ta[t+2]*tb[t+2];
  722. if (y<16) 
  723. sum+=ta[t]*tb[t]*ta[t+1]*tb[t+1];
  724. return sum;
  725. }
  726. double CSVM::fi(double* tt)
  727. {
  728. int x,y;
  729. double sum=0.0;
  730. for (int t=1;t<=52;t++)
  731. {
  732. x=((t-1)/13)+1;
  733. y=((t-1)%13)+1;
  734. if (y<13)
  735. sum+=tt[t]*tt[t+1];
  736. }
  737. return sum;
  738. }
  739. double CSVM::fs(double ta[])
  740. {
  741. double sum=0.0;
  742. int x,y;
  743. for (int i=1;i<256;i++)
  744. {
  745. x=((i-1)/16)+1;
  746. y=((i-1)%16)+1;
  747. if (x<16)
  748. sum+=ta[i]*ta[i+16];
  749. if (y<16) 
  750. sum+=ta[i]*ta[i+1];
  751. }
  752. return sum;
  753. }
  754. double CSVM::sumofword(DOC* a)
  755. {
  756. double sum=0.0;
  757. SVM_WORD* pwa=a->words;
  758. while (pwa->wnum)
  759. {
  760. sum+=pwa->weight;
  761. pwa++;
  762. }
  763. return sum;
  764. }
  765. double CSVM::custom_kernel(KERNEL_PARM *kernel_parm,DOC *a,DOC*b)
  766. {
  767. double sum=0;
  768.     SVM_WORD *ai,*bj;
  769.     ai=a->words;
  770.     bj=b->words;
  771.     while (ai->wnum || bj->wnum) 
  772. {
  773. if(ai->wnum == bj->wnum) 
  774. {
  775. sum+=(fabs(ai->weight-bj->weight))*(fabs(ai->weight-bj->weight));
  776. ai++;bj++;
  777. }
  778. else if ((ai!=0) &&(ai->wnum<bj->wnum || bj->wnum==0))
  779. {
  780. sum+=fabs(ai->weight)*fabs(ai->weight);
  781. ai++;
  782. }
  783. else if ((bj!=0) &&(bj->wnum<ai->wnum|| ai->wnum==0))
  784. {
  785. sum+=fabs(bj->weight)*fabs(bj->weight);
  786. bj++;
  787. }
  788.     }
  789. //   case 1: /* polynomial *///
  790. //return((CFLOAT)pow(kernel_parm->coef_lin*sprod_ss(a->words,b->words)+kernel_parm->coef_const,(double)kernel_parm->poly_degree)); 
  791.     //case 2: /* radial basis function */
  792. // return((CFLOAT)exp(-kernel_parm->rbf_gamma*(a->twonorm_sq-2*sprod_ss(a->words,b->words)+b->twonorm_sq)));
  793.     //case 3: /* sigmoid neural net */
  794. // return((CFLOAT)tanh(kernel_parm->coef_lin*sprod_ss(a->words,b->words)+kernel_parm->coef_const)); 
  795.     //case 4: /* custom-kernel supplied in file kernel.h*/
  796. // return((CFLOAT)custom_kernel(kernel_parm,a,b)); 
  797. /*
  798.     SVM_WORD *ai,*bj;
  799.     ai=a->words;
  800.     bj=b->words;
  801. double suma=0.0,sumb=0.0;
  802.     while (ai->wnum ) 
  803. {
  804. suma+=ai->weight;
  805. ai++;
  806. }
  807.     while (bj->wnum ) 
  808. {
  809. sumb+=bj->weight;
  810. bj++;
  811. }
  812. */
  813. // double K_rbf=exp(-0.001*(a->twonorm_sq-2*sprod_ss(a->words,b->words)+b->twonorm_sq));
  814. double K_Laplace=exp(-0.0001*sum);
  815. double K_poly=pow(sprod_ss(a->words,b->words)+20,3);
  816. // double K_linear=sprod_ss(a->words,b->words);
  817. //double sum;
  818. //double sum=suma*sumb;
  819. //sum=K_rbf*K_poly;
  820. //double sum=fabs(pro*pro+pro-tan(pro));
  821. return K_Laplace*K_poly;
  822. }
  823. /********************************svm_common****************************/
  824. /********************************svm_hideo****************************/
  825. double *CSVM::optimize_qp(QP *qp,
  826. double *epsilon_crit,
  827. long nx, /* Maximum number of variables in QP */
  828. double *threshold, 
  829. LEARN_PARM *learn_parm)
  830. /* start the optimizer and return the optimal values */
  831. /* The HIDEO optimizer does not necessarily fully solve the problem. */
  832. /* Since it requires a strictly positive definite hessian, the solution */
  833. /* is restricted to a linear independent subset in case the matrix is */
  834. /* only semi-definite. */
  835. {
  836.   long i;
  837.   int result;
  838.   double eq;
  839.   if(!primal) { /* allocate memory at first call */
  840.     primal=(double *)my_malloc(sizeof(double)*nx);
  841.     dual=(double *)my_malloc(sizeof(double)*((nx+1)*2));
  842.     nonoptimal=(long *)my_malloc(sizeof(long)*(nx));
  843.     buffer=(double *)my_malloc(sizeof(double)*((nx+1)*2*(nx+1)*2+
  844.        nx*nx+2*(nx+1)*2+2*nx+1+2*nx+
  845.        nx+nx+nx*nx));
  846.     (*threshold)=0;
  847.   }
  848.     eq=qp->opt_ce0[0];
  849.     for(i=0;i<qp->opt_n;i++) {
  850.       eq+=qp->opt_xinit[i]*qp->opt_ce[i];
  851.     }
  852.     
  853.   
  854.   result=optimize_hildreth_despo(qp->opt_n,qp->opt_m,
  855.  opt_precision,(*epsilon_crit),
  856.  learn_parm->epsilon_a,maxiter,
  857.  /* (long)PRIMAL_OPTIMAL, */
  858.  (long)0, (long)0,
  859.  lindep_sensitivity,
  860.  qp->opt_g,qp->opt_g0,qp->opt_ce,qp->opt_ce0,
  861.  qp->opt_low,qp->opt_up,primal,qp->opt_xinit,
  862.  dual,nonoptimal,buffer);
  863.   if(learn_parm->totwords < learn_parm->svm_maxqpsize) { 
  864.     /* larger working sets will be linear dependent anyway */
  865.     learn_parm->svm_maxqpsize=maxl(learn_parm->totwords,(long)2);
  866.   }
  867.   if(result == NAN_SOLUTION) {
  868.     lindep_sensitivity*=2;  /* throw out linear dependent examples more */
  869.                             /* generously */
  870.     if(learn_parm->svm_maxqpsize>2) {
  871.       learn_parm->svm_maxqpsize--;  /* decrease size of qp-subproblems */
  872.     }
  873.     precision_violations++;
  874.   }
  875.   /* take one round of only two variable to get unstuck */
  876.   if(result != PRIMAL_OPTIMAL) {
  877.     smallroundcount++;
  878.     result=optimize_hildreth_despo(qp->opt_n,qp->opt_m,
  879.    opt_precision,(*epsilon_crit),
  880.    learn_parm->epsilon_a,(long)maxiter,
  881.    (long)PRIMAL_OPTIMAL,(long)SMALLROUND,
  882.    lindep_sensitivity,
  883.    qp->opt_g,qp->opt_g0,qp->opt_ce,qp->opt_ce0,
  884.    qp->opt_low,qp->opt_up,primal,qp->opt_xinit,
  885.    dual,nonoptimal,buffer);
  886.     }
  887.     if(result != PRIMAL_OPTIMAL) {
  888.       if(result != ONLY_ONE_VARIABLE) 
  889. precision_violations++;
  890.       if(result == MAXITER_EXCEEDED) 
  891. maxiter+=100;
  892.       if(result == NAN_SOLUTION) {
  893. lindep_sensitivity*=2;  /* throw out linear dependent examples more */
  894.                         /* generously */
  895. /* results not valid, so return inital values */
  896. for(i=0;i<qp->opt_n;i++) {
  897.   primal[i]=qp->opt_xinit[i];
  898. }
  899.       }
  900.     }
  901.   if(precision_violations > 50) {
  902.     precision_violations=0;
  903.     (*epsilon_crit)*=10.0; 
  904.     }
  905.   if((qp->opt_m>0) && (result != NAN_SOLUTION))
  906.     (*threshold)=dual[1]-dual[0];
  907.   else
  908.     (*threshold)=0;
  909.   return(primal);
  910. }
  911. int CSVM::optimize_hildreth_despo(
  912.      long   n,            /* number of variables */
  913.      long   m,            /* number of linear equality constraints [0,1] */
  914.      double precision,    /* solve at least to this dual precision */
  915.      double epsilon_crit, /* stop, if KT-Conditions approx fulfilled */
  916.      double epsilon_a,    /* precision of alphas at bounds */
  917.      long   maxiter,      /* stop after this many iterations */
  918.      long   goal,         /* keep going until goal fulfilled */
  919.      long   smallround,   /* use only two variables of steepest descent */
  920.      double lindep_sensitivity, /* epsilon for detecting linear dependent ex */
  921.      double *g,           /* hessian of objective */
  922.      double *g0,          /* linear part of objective */
  923.      double *ce,double *ce0,     /* linear equality constraints */
  924.      double *low,double *up,     /* box constraints */
  925.      double *primal,      /* primal variables */
  926.      double *init,        /* initial values of primal */
  927.      double *dual,        /* dual variables */
  928.      long   *lin_dependent,
  929.      double *buffer)
  930. {
  931.   long i,j,k,from,to,n_indep,changed;
  932.   double sum,bmin=0,bmax=0;
  933.   double *d,*d0,*ig,*dual_old,*temp,*start;       
  934.   double *g0_new,*g_new,*ce_new,*ce0_new,*low_new,*up_new;
  935.   double add,t;
  936.   int result;
  937.   //double obj_before,obj_after; 
  938.   long b1,b2;
  939.   g0_new=&(buffer[0]);    /* claim regions of buffer */
  940.   d=&(buffer[n]);
  941.   d0=&(buffer[n+(n+m)*2*(n+m)*2]);
  942.   ce_new=&(buffer[n+(n+m)*2*(n+m)*2+(n+m)*2]);
  943.   ce0_new=&(buffer[n+(n+m)*2*(n+m)*2+(n+m)*2+n]);
  944.   ig=&(buffer[n+(n+m)*2*(n+m)*2+(n+m)*2+n+m]);
  945.   dual_old=&(buffer[n+(n+m)*2*(n+m)*2+(n+m)*2+n+m+n*n]);
  946.   low_new=&(buffer[n+(n+m)*2*(n+m)*2+(n+m)*2+n+m+n*n+(n+m)*2]);
  947.   up_new=&(buffer[n+(n+m)*2*(n+m)*2+(n+m)*2+n+m+n*n+(n+m)*2+n]);
  948.   start=&(buffer[n+(n+m)*2*(n+m)*2+(n+m)*2+n+m+n*n+(n+m)*2+n+n]);
  949.   g_new=&(buffer[n+(n+m)*2*(n+m)*2+(n+m)*2+n+m+n*n+(n+m)*2+n+n+n]);
  950.   temp=&(buffer[n+(n+m)*2*(n+m)*2+(n+m)*2+n+m+n*n+(n+m)*2+n+n+n+n*n]);
  951.   b1=-1;
  952.   b2=-1;
  953.   for(i=0;i<n;i++) {   /* get variables with steepest feasible descent */
  954.     sum=g0[i];         
  955.     for(j=0;j<n;j++) 
  956.       sum+=init[j]*g[i*n+j];
  957.     sum=sum*ce[i];
  958.     if(((b1==-1) || (sum<bmin)) 
  959.        && (!((init[i]<=(low[i]+epsilon_a)) && (ce[i]<0.0)))
  960.        && (!((init[i]>=( up[i]-epsilon_a)) && (ce[i]>0.0)))
  961.        ) {
  962.       bmin=sum;
  963.       b1=i;
  964.     }
  965.     if(((b2==-1) || (sum>bmax)) 
  966.        && (!((init[i]<=(low[i]+epsilon_a)) && (ce[i]>0.0)))
  967.        && (!((init[i]>=( up[i]-epsilon_a)) && (ce[i]<0.0)))
  968.        ) {
  969.       bmax=sum;
  970.       b2=i;
  971.     }
  972.   }
  973.   
  974.   for(i=0;i<n;i++) {
  975.     start[i]=init[i];
  976.   }
  977.   /* in case both examples are equal */
  978.   add=0;
  979.   changed=0;
  980.   if((-g[b1*n+b2] == g[b1*n+b1]) && (-g[b1*n+b2] == g[b2*n+b2])) {
  981.     changed=1;
  982.     if(ce[b1] == ce[b2]) { /* distribute evenly */
  983.       start[b1]=(init[b1]+init[b2])/2.0;
  984.       start[b2]=(init[b1]+init[b2])/2.0;
  985.       if(start[b2] > up[b2]) {
  986. t=start[b2]-up[b2];
  987. start[b2]=up[b2];
  988. start[b1]+=t;
  989.       }
  990.       if(start[b1] > up[b1]) {
  991. t=start[b1]-up[b1];
  992. start[b1]=up[b1];
  993. start[b2]+=t;
  994.       }
  995.     }
  996.     else { /* set to upper bound */
  997.       t=up[b1]-init[b1];
  998.       if((up[b2]-init[b2]) < t) {
  999. t=up[b2]-init[b2];
  1000.       }
  1001.       start[b1]=init[b1]+t;
  1002.       start[b2]=init[b2]+t;
  1003.     }
  1004.   }
  1005.   /* if we have a biased hyperplane, then adding a constant to the */
  1006.   /* hessian does not change the solution. So that is done for examples */
  1007.   /* with zero diagonal entry, since HIDEO cannot handle them. */
  1008.   else if((fabs(g[b1*n+b1]) < lindep_sensitivity) 
  1009.   || (fabs(g[b2*n+b2]) < lindep_sensitivity)) {
  1010.     add+=0.093274;
  1011.   }    
  1012.   /* in case both examples are linear dependent */
  1013.   else if(fabs(g[b1*n+b1]/g[b1*n+b2] - g[b1*n+b2]/g[b2*n+b2])
  1014.   < lindep_sensitivity) { 
  1015.     add+=0.078274;
  1016.   }
  1017. /* sprintf(temstr,"b1=%ld,b2=%ldn",b1,b2); */
  1018.   lcopy_matrix(g,n,d);
  1019.   if((m==1) && (add>0.0)) {
  1020.     for(j=0;j<n;j++) {
  1021.       for(k=0;k<n;k++) {
  1022. d[j*n+k]+=add*ce[j]*ce[k];
  1023.       }
  1024.     }
  1025.   }
  1026.   else {
  1027.     add=0.0;
  1028.   }
  1029.   if(n>2) {                    /* switch, so that variables are better mixed */
  1030.     lswitchrk_matrix(d,n,b1,(long)0); 
  1031.     if(b2 == 0) 
  1032.       lswitchrk_matrix(d,n,b1,(long)1); 
  1033.     else
  1034.       lswitchrk_matrix(d,n,b2,(long)1); 
  1035.   }
  1036.   if(smallround == SMALLROUND) {
  1037.     for(i=2;i<n;i++) {
  1038.       lin_dependent[i]=1;
  1039.     }
  1040.     lin_dependent[0]=0;
  1041.     lin_dependent[1]=0;
  1042.   }
  1043.   else {
  1044.     for(i=0;i<n;i++) {
  1045.       lin_dependent[i]=0;
  1046.     }
  1047.   }
  1048.   linvert_matrix(d,n,ig,lindep_sensitivity,lin_dependent);
  1049.   if(n>2) {                    /* now switch back */
  1050.     if(b2 == 0) {
  1051.       lswitchrk_matrix(ig,n,b1,(long)1); 
  1052.       i=lin_dependent[1];  
  1053.       lin_dependent[1]=lin_dependent[b1];
  1054.       lin_dependent[b1]=i;
  1055.     }
  1056.     else {
  1057.       lswitchrk_matrix(ig,n,b2,(long)1); 
  1058.       i=lin_dependent[1];  
  1059.       lin_dependent[1]=lin_dependent[b2];
  1060.       lin_dependent[b2]=i;
  1061.     }
  1062.     lswitchrk_matrix(ig,n,b1,(long)0); 
  1063.     i=lin_dependent[0];  
  1064.     lin_dependent[0]=lin_dependent[b1];
  1065.     lin_dependent[b1]=i;
  1066.   }
  1067.   /* lprint_matrix(d,n); */
  1068.   /* lprint_matrix(ig,n); */
  1069.   lcopy_matrix(g,n,g_new);   /* restore g_new matrix */
  1070.   if(add>0)
  1071.     for(j=0;j<n;j++) {
  1072.       for(k=0;k<n;k++) {
  1073. g_new[j*n+k]+=add*ce[j]*ce[k];
  1074.       }
  1075.     }
  1076.   for(i=0;i<n;i++) {  /* fix linear dependent vectors */
  1077.     g0_new[i]=g0[i]+add*ce0[0]*ce[i];
  1078.   }
  1079.   if(m>0) ce0_new[0]=-ce0[0];
  1080.   for(i=0;i<n;i++) {  /* fix linear dependent vectors */
  1081.     if(lin_dependent[i]) {
  1082.       for(j=0;j<n;j++) {
  1083. if(!lin_dependent[j]) {
  1084.   g0_new[j]+=start[i]*g_new[i*n+j];
  1085. }
  1086.       }
  1087.       if(m>0) ce0_new[0]-=(start[i]*ce[i]);
  1088.     }
  1089.   }
  1090.   from=0;   /* remove linear dependent vectors */
  1091.   to=0;
  1092.   n_indep=0;
  1093.   for(i=0;i<n;i++) {
  1094.     if(!lin_dependent[i]) {
  1095.       g0_new[n_indep]=g0_new[i];
  1096.       ce_new[n_indep]=ce[i]; 
  1097.       low_new[n_indep]=low[i];
  1098.       up_new[n_indep]=up[i];
  1099.       primal[n_indep]=start[i];
  1100.       n_indep++;
  1101.     }
  1102.     for(j=0;j<n;j++) {
  1103.       if((!lin_dependent[i]) && (!lin_dependent[j])) {
  1104.         ig[to]=ig[from];
  1105.         g_new[to]=g_new[from];
  1106. to++;
  1107.       }
  1108.       from++;
  1109.     }
  1110.   }
  1111.   
  1112.   /* cannot optimize with only one variable */
  1113.   if((n_indep<=1) && (m>0) && (!changed)) { 
  1114.     for(i=n-1;i>=0;i--) {
  1115.       primal[i]=init[i];
  1116.     }
  1117.     return((int)ONLY_ONE_VARIABLE);
  1118.   }
  1119.   result=solve_dual(n_indep,m,precision,epsilon_crit,maxiter,g_new,g0_new,
  1120.     ce_new,ce0_new,low_new,up_new,primal,d,d0,ig,
  1121.     dual,dual_old,temp,goal);
  1122.   
  1123.   j=n_indep;
  1124.   for(i=n-1;i>=0;i--) {
  1125.     if(!lin_dependent[i]) {
  1126.       j--;
  1127.       primal[i]=primal[j];
  1128.     }
  1129.     else if((m==0) && (g[i*n+i]==0)) {
  1130.       /* if we use a biased hyperplane, each example with a zero diagonal */
  1131.       /* entry must have an alpha at the upper bound. Doing this */
  1132.       /* is essential for the HIDEO optimizer, since it cannot handle zero */
  1133.       /* diagonal entries in the hessian for the unbiased hyperplane case. */
  1134.       primal[i]=up[i];  
  1135.     }
  1136.     else {
  1137.       primal[i]=start[i];  /* leave as is */
  1138.     }
  1139.     temp[i]=primal[i];
  1140.   }
  1141.    
  1142.  
  1143.   return((int)result);
  1144. }
  1145. int CSVM::solve_dual(
  1146.      /* Solves the dual using the method of Hildreth and D'Espo. */
  1147.      /* Can only handle problems with zero or exactly one */
  1148.      /* equality constraints. */
  1149.      long   n,            /* number of variables */
  1150.      long   m,            /* number of linear equality constraints */
  1151.      double precision,    /* solve at least to this dual precision */
  1152.      double epsilon_crit, /* stop, if KT-Conditions approx fulfilled */
  1153.      long   maxiter,      /* stop after that many iterations */
  1154.      double *g,
  1155.      double *g0,          /* linear part of objective */
  1156.      double *ce,double *ce0,     /* linear equality constraints */
  1157.      double *low,double *up,     /* box constraints */
  1158.      double *primal,      /* variables (with initial values) */
  1159.      double *d,double *d0,double *ig,double *dual,double *dual_old,double *temp,       /* buffer  */
  1160.      long goal)
  1161. {
  1162.   long i,j,k,iter;
  1163.   double sum,w,maxviol,viol,temp1,temp2,isnantest;
  1164.   double model_b,dist;
  1165.   long retrain,maxfaktor,primal_optimal=0,at_bound,scalemaxiter;
  1166.   double epsilon_a=1E-15,epsilon_hideo;
  1167.   double eq; 
  1168.   if((m<0) || (m>1)) 
  1169.     printe("SOLVE DUAL: inappropriate number of eq-constrains!");
  1170.   for(i=0;i<2*(n+m);i++) {
  1171.     dual[i]=0;
  1172.     dual_old[i]=0;
  1173.   }
  1174.   for(i=0;i<n;i++) {   
  1175.     for(j=0;j<n;j++) {   /* dual hessian for box constraints */
  1176.       d[i*2*(n+m)+j]=ig[i*n+j];
  1177.       d[(i+n)*2*(n+m)+j]=-ig[i*n+j];
  1178.       d[i*2*(n+m)+j+n]=-ig[i*n+j];
  1179.       d[(i+n)*2*(n+m)+j+n]=ig[i*n+j];
  1180.     }
  1181.     if(m>0) {
  1182.       sum=0;              /* dual hessian for eq constraints */
  1183.       for(j=0;j<n;j++) {
  1184. sum+=(ce[j]*ig[i*n+j]);
  1185.       }
  1186.       d[i*2*(n+m)+2*n]=sum;
  1187.       d[i*2*(n+m)+2*n+1]=-sum;
  1188.       d[(n+i)*2*(n+m)+2*n]=-sum;
  1189.       d[(n+i)*2*(n+m)+2*n+1]=sum;
  1190.       d[(n+n)*2*(n+m)+i]=sum;
  1191.       d[(n+n+1)*2*(n+m)+i]=-sum;
  1192.       d[(n+n)*2*(n+m)+(n+i)]=-sum;
  1193.       d[(n+n+1)*2*(n+m)+(n+i)]=sum;
  1194.       
  1195.       sum=0;
  1196.       for(j=0;j<n;j++) {
  1197. for(k=0;k<n;k++) {
  1198.   sum+=(ce[k]*ce[j]*ig[j*n+k]);
  1199. }
  1200.       }
  1201.       d[(n+n)*2*(n+m)+2*n]=sum;
  1202.       d[(n+n)*2*(n+m)+2*n+1]=-sum;
  1203.       d[(n+n+1)*2*(n+m)+2*n]=-sum;
  1204.       d[(n+n+1)*2*(n+m)+2*n+1]=sum;
  1205.     } 
  1206.   }
  1207.   for(i=0;i<n;i++) {   /* dual linear component for the box constraints */
  1208.     w=0;
  1209.     for(j=0;j<n;j++) {
  1210.       w+=(ig[i*n+j]*g0[j]); 
  1211.     }
  1212.     d0[i]=up[i]+w;
  1213.     d0[i+n]=-low[i]-w;
  1214.   }
  1215.   if(m>0) {  
  1216.     sum=0;             /* dual linear component for eq constraints */
  1217.     for(j=0;j<n;j++) {
  1218.       for(k=0;k<n;k++) {
  1219. sum+=(ce[k]*ig[k*n+j]*g0[j]); 
  1220.       }
  1221.     }
  1222.     d0[2*n]=ce0[0]+sum;
  1223.     d0[2*n+1]=-ce0[0]-sum;
  1224.   }
  1225.   maxviol=999999;
  1226.   iter=0;
  1227.   retrain=1;
  1228.   maxfaktor=1;
  1229.   scalemaxiter=maxiter/5;
  1230.   while((retrain) && (maxviol > 0) && (iter < (scalemaxiter*maxfaktor))) {
  1231.     iter++;
  1232.     
  1233.     while((maxviol > precision) && (iter < (scalemaxiter*maxfaktor))) {
  1234.       iter++;
  1235.       maxviol=0;
  1236.       for(i=0;i<2*(n+m);i++) {
  1237. sum=d0[i];
  1238. for(j=0;j<2*(n+m);j++) {
  1239.   sum+=d[i*2*(n+m)+j]*dual_old[j];
  1240. }
  1241. sum-=d[i*2*(n+m)+i]*dual_old[i];
  1242. dual[i]=-sum/d[i*2*(n+m)+i];
  1243. if(dual[i]<0) dual[i]=0;
  1244. viol=fabs(dual[i]-dual_old[i]);
  1245. if(viol>maxviol) 
  1246.   maxviol=viol;
  1247. dual_old[i]=dual[i];
  1248.       }
  1249.       /*
  1250.       sprintf(temstr,"%d) maxviol=%20f precision=%fn",iter,maxviol,precision); 
  1251.       */
  1252.     }
  1253.   
  1254.     if(m>0) {
  1255.       for(i=0;i<n;i++) {
  1256. temp[i]=dual[i]-dual[i+n]+ce[i]*(dual[n+n]-dual[n+n+1])+g0[i];
  1257.       }
  1258.     } 
  1259.     else {
  1260.       for(i=0;i<n;i++) {
  1261. temp[i]=dual[i]-dual[i+n]+g0[i];
  1262.       }
  1263.     }
  1264.     for(i=0;i<n;i++) {
  1265.       primal[i]=0;             /* calc value of primal variables */
  1266.       for(j=0;j<n;j++) {
  1267. primal[i]+=ig[i*n+j]*temp[j];
  1268.       }
  1269.       primal[i]*=-1.0;
  1270.       if(primal[i]<=(low[i])) {  /* clip conservatively */
  1271. primal[i]=low[i];
  1272.       }
  1273.       else if(primal[i]>=(up[i])) {
  1274. primal[i]=up[i];
  1275.       }
  1276.     }
  1277.     if(m>0) 
  1278.       model_b=dual[n+n+1]-dual[n+n];
  1279.     else
  1280.       model_b=0;
  1281.     epsilon_hideo=EPSILON_HIDEO;
  1282.     for(i=0;i<n;i++) {           /* check precision of alphas */
  1283.       isnantest+=primal[j];
  1284.       dist=-model_b*ce[i]; 
  1285.       dist+=(g0[i]+1.0);
  1286.       for(j=0;j<i;j++) {
  1287. dist+=(primal[j]*g[j*n+i]);
  1288.       }
  1289.       for(j=i;j<n;j++) {
  1290. dist+=(primal[j]*g[i*n+j]);
  1291.       }
  1292.       if((primal[i]<(up[i]-epsilon_hideo)) && (dist < (1.0-epsilon_crit))) {
  1293. epsilon_hideo=(up[i]-primal[i])*2.0;
  1294.       }
  1295.       else if((primal[i]>(low[i]+epsilon_hideo)) &&(dist>(1.0+epsilon_crit))) {
  1296. epsilon_hideo=(primal[i]-low[i])*2.0;
  1297.       }
  1298.     }
  1299.      /*sprintf(temstr,"nEPSILON_HIDEO=%.30fn",epsilon_hideo); */
  1300.     for(i=0;i<n;i++) {           /* clip alphas to bounds */
  1301.       if(primal[i]<=(low[i]+epsilon_hideo)) {
  1302. primal[i]=low[i];
  1303.       }
  1304.       else if(primal[i]>=(up[i]-epsilon_hideo)) {
  1305. primal[i]=up[i];
  1306.       }
  1307.     }
  1308.     retrain=0;
  1309.     primal_optimal=1;
  1310.     at_bound=0;
  1311.     for(i=0;(i<n);i++) {  /* check primal KT-Conditions */
  1312.       dist=-model_b*ce[i]; 
  1313.       dist+=(g0[i]+1.0);
  1314.       for(j=0;j<i;j++) {
  1315. dist+=(primal[j]*g[j*n+i]);
  1316.       }
  1317.       for(j=i;j<n;j++) {
  1318. dist+=(primal[j]*g[i*n+j]);
  1319.       }
  1320.       if((primal[i]<(up[i]-epsilon_a)) && (dist < (1.0-epsilon_crit))) {
  1321. retrain=1;
  1322. primal_optimal=0;
  1323.       }
  1324.       else if((primal[i]>(low[i]+epsilon_a)) && (dist > (1.0+epsilon_crit))) {
  1325. retrain=1;
  1326. primal_optimal=0;
  1327.       }
  1328.       if((primal[i]<=(low[i]+epsilon_a)) || (primal[i]>=(up[i]-epsilon_a))) {
  1329. at_bound++;
  1330.       }
  1331.       /*    sprintf(temstr,"HIDEOtemp: a[%ld]=%.30f, dist=%.6f, b=%f, at_bound=%ldn",i,primal[i],dist,model_b,at_bound);  */
  1332.     }
  1333.     if(m>0) {
  1334.       eq=-ce0[0];               /* check precision of eq-constraint */
  1335.       for(i=0;i<n;i++) { 
  1336. eq+=(ce[i]*primal[i]);
  1337.       }
  1338.       if((EPSILON_EQ < fabs(eq)) 
  1339.  /*
  1340.  && !((goal==PRIMAL_OPTIMAL) 
  1341.        && (at_bound==n)) */
  1342.  ) {
  1343. retrain=1;
  1344. primal_optimal=0;
  1345.       }
  1346.       /* sprintf(temstr,"n eq=%.30f ce0=%f at-bound=%ldn",eq,ce0[0],at_bound);  */
  1347.     }
  1348.     if(retrain) {
  1349.       precision/=10;
  1350.       if(((goal == PRIMAL_OPTIMAL) && (maxfaktor < 50000))
  1351.  || (maxfaktor < 5)) {
  1352. maxfaktor++;
  1353.       }
  1354.     }
  1355.   }
  1356.   if(!primal_optimal) {
  1357.     for(i=0;i<n;i++) {
  1358.       primal[i]=0;             /* calc value of primal variables */
  1359.       for(j=0;j<n;j++) {
  1360. primal[i]+=ig[i*n+j]*temp[j];
  1361.       }
  1362.       primal[i]*=-1.0;
  1363.       if(primal[i]<=(low[i]+epsilon_a)) {  /* clip conservatively */
  1364. primal[i]=low[i];
  1365.       }
  1366.       else if(primal[i]>=(up[i]-epsilon_a)) {
  1367. primal[i]=up[i];
  1368.       }
  1369.     }
  1370.   }
  1371.   isnantest=0;
  1372.   for(i=0;i<n;i++) {           /* check for isnan */
  1373.     isnantest+=primal[i];
  1374.   }
  1375.   if(m>0) {
  1376.     temp1=dual[n+n+1];   /* copy the dual variables for the eq */
  1377.     temp2=dual[n+n];     /* constraints to a handier location */
  1378.     for(i=n+n+1;i>=2;i--) {
  1379.       dual[i]=dual[i-2];
  1380.     }
  1381.     dual[0]=temp2;
  1382.     dual[1]=temp1;
  1383.     isnantest+=temp1+temp2;
  1384.   }
  1385.   if(isnan(isnantest)) {
  1386.     return((int)NAN_SOLUTION);
  1387.   }
  1388.   else if(primal_optimal) {
  1389.     return((int)PRIMAL_OPTIMAL);
  1390.   }
  1391.   else if(maxviol == 0.0) {
  1392.     return((int)DUAL_OPTIMAL);
  1393.   }
  1394.   else {
  1395.     return((int)MAXITER_EXCEEDED);
  1396.   }
  1397. }
  1398. void CSVM::linvert_matrix(
  1399. double *matrix,
  1400. long depth,
  1401. double *inverse,double lindep_sensitivity,
  1402. long *lin_dependent)  /* indicates the active parts of matrix on 
  1403.  input and output*/
  1404. {
  1405.   long i,j,k;
  1406.   double factor;
  1407.   for(i=0;i<depth;i++) {
  1408.     /*    lin_dependent[i]=0; */
  1409.     for(j=0;j<depth;j++) {
  1410.       inverse[i*depth+j]=0.0;
  1411.     }
  1412.     inverse[i*depth+i]=1.0;
  1413.   }
  1414.   for(i=0;i<depth;i++) {
  1415.     if(lin_dependent[i] || (fabs(matrix[i*depth+i])<lindep_sensitivity)) {
  1416.       lin_dependent[i]=1;
  1417.     }
  1418.     else {
  1419.       for(j=i+1;j<depth;j++) {
  1420. factor=matrix[j*depth+i]/matrix[i*depth+i];
  1421. for(k=i;k<depth;k++) {
  1422.   matrix[j*depth+k]-=(factor*matrix[i*depth+k]);
  1423. }
  1424. for(k=0;k<depth;k++) {
  1425.   inverse[j*depth+k]-=(factor*inverse[i*depth+k]);
  1426. }
  1427.       }
  1428.     }
  1429.   }
  1430.   for(i=depth-1;i>=0;i--) {
  1431.     if(!lin_dependent[i]) {
  1432.       factor=1/matrix[i*depth+i];
  1433.       for(k=0;k<depth;k++) {
  1434. inverse[i*depth+k]*=factor;
  1435.       }
  1436.       matrix[i*depth+i]=1;
  1437.       for(j=i-1;j>=0;j--) {
  1438. factor=matrix[j*depth+i];
  1439. matrix[j*depth+i]=0;
  1440. for(k=0;k<depth;k++) {
  1441.   inverse[j*depth+k]-=(factor*inverse[i*depth+k]);
  1442. }
  1443.       }
  1444.     }
  1445.   }
  1446. }
  1447. void CSVM::ladd_matrix(
  1448. double *matrix,
  1449. long depth,
  1450. double scalar)
  1451. {
  1452.   long i,j;
  1453.   for(i=0;i<depth;i++) {
  1454.     for(j=0;j<depth;j++) {
  1455.       matrix[i*depth+j]+=scalar;
  1456.     }
  1457.   }
  1458. }
  1459. void CSVM::lcopy_matrix(
  1460. double *matrix,
  1461. long depth,
  1462. double *matrix2)
  1463. {
  1464.   long i;
  1465.   
  1466.   for(i=0;i<(depth)*(depth);i++) {
  1467.     matrix2[i]=matrix[i];
  1468.   }
  1469. }
  1470. void CSVM::lswitch_rows_matrix(
  1471. double *matrix,
  1472. long depth,long r1,long r2)
  1473. {
  1474.   long i;
  1475.   double temp;
  1476.   for(i=0;i<depth;i++) {
  1477.     temp=matrix[r1*depth+i];
  1478.     matrix[r1*depth+i]=matrix[r2*depth+i];
  1479.     matrix[r2*depth+i]=temp;
  1480.   }
  1481. }
  1482. void CSVM::lswitchrk_matrix(
  1483. double *matrix,
  1484. long depth,long rk1,long rk2)
  1485. {
  1486.   long i;
  1487.   double temp;
  1488.   for(i=0;i<depth;i++) {
  1489.     temp=matrix[rk1*depth+i];
  1490.     matrix[rk1*depth+i]=matrix[rk2*depth+i];
  1491.     matrix[rk2*depth+i]=temp;
  1492.   }
  1493.   for(i=0;i<depth;i++) {
  1494.     temp=matrix[i*depth+rk1];
  1495.     matrix[i*depth+rk1]=matrix[i*depth+rk2];
  1496.     matrix[i*depth+rk2]=temp;
  1497.   }
  1498. }
  1499. double CSVM::calculate_qp_objective(
  1500. long opt_n,
  1501. double *opt_g,double *opt_g0,double *alpha)
  1502. {
  1503.   double obj;
  1504.   long i,j;
  1505.   obj=0;  /* calculate objective  */
  1506.   for(i=0;i<opt_n;i++) {
  1507.     obj+=(opt_g0[i]*alpha[i]);
  1508.     obj+=(0.5*alpha[i]*alpha[i]*opt_g[i*opt_n+i]);
  1509.     for(j=0;j<i;j++) {
  1510.       obj+=(alpha[j]*alpha[i]*opt_g[j*opt_n+i]);
  1511.     }
  1512.   }
  1513.   return(obj);
  1514. }
  1515. /********************************svm_hideo****************************/
  1516. /********************************svm_learn****************************/
  1517. /* Learns an SVM model based on the training data in docs/label. The resulting
  1518. model is returned in the structure model. */
  1519. void CSVM::svm_learn(
  1520.                DOC *docs,                
  1521.                long *label,               
  1522.                long totdoc,               
  1523.                long totwords,             
  1524.                LEARN_PARM *learn_parm,    
  1525.                KERNEL_PARM *kernel_parm, 
  1526.                KERNEL_CACHE *kernel_cache,
  1527.                MODEL *model             
  1528.                )
  1529. {
  1530.     long *inconsistent,i;
  1531.     long inconsistentnum;
  1532.     long misclassified,upsupvecnum;
  1533.     double loss,model_length,example_length;
  1534.     double maxdiff,*lin,*a;
  1535.     long runtime_start,runtime_end;
  1536.     long iterations;
  1537.     long *unlabeled,transduction;
  1538.     long heldout;
  1539.     long loo_count=0,loo_count_pos=0,loo_count_neg=0,trainpos=0,trainneg=0;
  1540.     long loocomputed=0,runtime_start_loo=0,runtime_start_xa=0;
  1541.     double heldout_c=0,r_delta_sq=0,r_delta,r_delta_avg;
  1542.     
  1543.     double *xi_fullset; /* buffer for storing xi on full sample in loo */
  1544.     double *a_fullset;  /* buffer for storing alpha on full sample in loo */
  1545.     TIMING timing_profile;
  1546.     SHRINK_STATE shrink_state;
  1547.     
  1548.     runtime_start=get_runtime();
  1549.     timing_profile.time_kernel=0;
  1550.     timing_profile.time_opti=0;
  1551.     timing_profile.time_shrink=0;
  1552.     timing_profile.time_update=0;
  1553.     timing_profile.time_model=0;
  1554.     timing_profile.time_check=0;
  1555.     timing_profile.time_select=0;
  1556.     
  1557. com_result.kernel_cache_statistic=0;
  1558.     
  1559.     learn_parm->totwords=totwords;
  1560.     
  1561.     /* make sure -n value is reasonable */
  1562.     if((learn_parm->svm_newvarsinqp < 2) || (learn_parm->svm_newvarsinqp > learn_parm->svm_maxqpsize))
  1563.     {
  1564.         learn_parm->svm_newvarsinqp=learn_parm->svm_maxqpsize;
  1565.     }
  1566.     
  1567.     init_shrink_state(&shrink_state,totdoc,(long)10000);
  1568.     
  1569.     inconsistent = (long *)my_malloc(sizeof(long)*totdoc);
  1570.     unlabeled = (long *)my_malloc(sizeof(long)*totdoc);
  1571.     a = (double *)my_malloc(sizeof(double)*totdoc);
  1572.     a_fullset = (double *)my_malloc(sizeof(double)*totdoc);
  1573.     xi_fullset = (double *)my_malloc(sizeof(double)*totdoc);
  1574.     lin = (double *)my_malloc(sizeof(double)*totdoc);
  1575.     learn_parm->svm_cost = (double *)my_malloc(sizeof(double)*totdoc);
  1576.     model->supvec = (DOC **)my_malloc(sizeof(DOC *)*(totdoc+2));
  1577.     model->alpha = (double *)my_malloc(sizeof(double)*(totdoc+2));
  1578.     model->index = (long *)my_malloc(sizeof(long)*(totdoc+2));
  1579.     
  1580.     model->at_upper_bound=0;
  1581.     model->b=0;        
  1582.     model->supvec[0]=0;  /* element 0 reserved and empty for now */
  1583.     model->alpha[0]=0;
  1584.     model->lin_weights=NULL;
  1585.     model->totwords=totwords;
  1586.     model->totdoc=totdoc;
  1587.     model->kernel_parm=(*kernel_parm);
  1588.     model->sv_num=1;
  1589.     model->loo_error=-1;
  1590.     model->loo_recall=-1;
  1591.     model->loo_precision=-1;
  1592.     model->xa_error=-1;
  1593.     model->xa_recall=-1;
  1594.     model->xa_precision=-1;
  1595.     inconsistentnum=0;
  1596.     transduction=0;
  1597.     
  1598.     r_delta=estimate_r_delta(docs,totdoc,kernel_parm);
  1599.     r_delta_sq=r_delta*r_delta;
  1600.     
  1601.     r_delta_avg=estimate_r_delta_average(docs,totdoc,kernel_parm);
  1602.     if(learn_parm->svm_c == 0.0)
  1603.     {  /* default value for C */
  1604.         learn_parm->svm_c=1.0/(r_delta_avg*r_delta_avg);
  1605. if (com_pro.show_compute_1)
  1606. {
  1607.         sprintf(temstr,"Setting default regularization parameter C=%.4fn",learn_parm->svm_c);
  1608.         printm(temstr);
  1609. }
  1610.     }
  1611.     
  1612.     for(i=0;i<totdoc;i++) 
  1613.     {    /* various inits */
  1614.         inconsistent[i]=0;
  1615.         a[i]=0;
  1616.         lin[i]=0;
  1617.         unlabeled[i]=0;
  1618.         if(label[i] == 0) 
  1619.         {
  1620.             unlabeled[i]=1;
  1621.             transduction=1;
  1622.         }
  1623.         if(label[i] > 0)
  1624.         {
  1625.             learn_parm->svm_cost[i]=learn_parm->svm_c*learn_parm->svm_costratio*
  1626.                 fabs((double)label[i]);
  1627.             label[i]=1;
  1628.             trainpos++;
  1629.         }
  1630.         else if(label[i] < 0) 
  1631.         {
  1632.             learn_parm->svm_cost[i]=learn_parm->svm_c*fabs((double)label[i]);
  1633.             label[i]=-1;
  1634.             trainneg++;
  1635.         }
  1636.         else
  1637.         {
  1638.             learn_parm->svm_cost[i]=0;
  1639.         }
  1640.     }
  1641.     
  1642.     /* caching makes no sense for linear kernel */
  1643.     if(kernel_parm->kernel_type == LINEAR)
  1644.     {
  1645.         kernel_cache = NULL;   
  1646.     } 
  1647.     
  1648.     if(transduction) 
  1649.     {
  1650.         learn_parm->svm_iter_to_shrink=99999999;
  1651.         sprintf(temstr,"nDeactivating Shrinking due to an incompatibility with the transductive nlearner in the current version.nn");
  1652.         printm(temstr);
  1653.     }
  1654.     
  1655.     if(transduction && learn_parm->compute_loo) 
  1656.     {
  1657.         learn_parm->compute_loo=0;
  1658.         sprintf(temstr,"nCannot compute leave-one-out estimates for transductive learner.nn");
  1659.         printm(temstr);
  1660.     }
  1661.     
  1662.     if(learn_parm->remove_inconsistent && learn_parm->compute_loo) 
  1663.     {
  1664.         learn_parm->compute_loo=0;
  1665.         sprintf(temstr,"nCannot compute leave-one-out estimates when removing inconsistent examples.nn");
  1666.         printm(temstr);
  1667.     }    
  1668.     
  1669.     if((trainpos == 1) || (trainneg == 1)) 
  1670.     {
  1671.         learn_parm->compute_loo=0;
  1672.         sprintf(temstr,"nCannot compute leave-one-out with only one example in one class.nn");
  1673.         printm(temstr);
  1674.     }    
  1675.     
  1676.     if (com_pro.show_action)
  1677. {
  1678. sprintf(temstr,"Optimizing..."); 
  1679. printm(temstr);
  1680. }
  1681.     
  1682.     /* train the svm */
  1683.     iterations=optimize_to_convergence(docs,label,totdoc,totwords,learn_parm,
  1684.         kernel_parm,kernel_cache,&shrink_state,model,inconsistent,unlabeled,a,lin,&timing_profile,  &maxdiff,(long)-1,(long)1);
  1685.     if (com_pro.show_action)
  1686. {
  1687. sprintf(temstr,"done. (%ld iterations) ",iterations);
  1688. printm(temstr);
  1689. }
  1690.     
  1691.     misclassified=0;
  1692.     for(i=0;(i<totdoc);i++)
  1693.     { /* get final statistic */
  1694.         if((lin[i]-model->b)*(double)label[i] <= 0.0) 
  1695.             misclassified++;
  1696.     }
  1697. if (com_pro.show_action)
  1698. {
  1699. printm("optimization finished");
  1700. }
  1701. if (com_pro.show_trainresult)
  1702. {
  1703. sprintf(temstr," (%ld misclassified, maxdiff=%.5f).n", misclassified,maxdiff); 
  1704. printm(temstr);
  1705. }
  1706. com_result.train_misclassify=misclassified;
  1707. com_result.max_difference=maxdiff;
  1708.              
  1709.     runtime_end=get_runtime();
  1710.              
  1711.     if (learn_parm->remove_inconsistent)
  1712.     {     
  1713.         inconsistentnum=0;
  1714.         for(i=0;i<totdoc;i++) 
  1715.             if(inconsistent[i]) 
  1716.                inconsistentnum++;
  1717.         sprintf(temstr,"Number of SV: %ld (plus %ld inconsistent examples)n", model->sv_num-1,inconsistentnum);
  1718.         printm(temstr);
  1719.     }
  1720.     
  1721.     else
  1722.     {
  1723.      upsupvecnum=0;
  1724.      for(i=1;i<model->sv_num;i++) 
  1725.      {
  1726.          if(fabs(model->alpha[i]) >= (learn_parm->svm_cost[(model->supvec[i])->docnum]-learn_parm->epsilon_a)) 
  1727.              upsupvecnum++;
  1728.      }
  1729.  if (com_pro.show_trainresult)
  1730.  {
  1731.  sprintf(temstr,"Number of SV: %ld (including %ld at upper bound)n", model->sv_num-1,upsupvecnum);
  1732.      printm(temstr);
  1733.  }
  1734.     }
  1735. if( (!learn_parm->skip_final_opt_check)) 
  1736. {
  1737. loss=0;
  1738. model_length=0; 
  1739. for(i=0;i<totdoc;i++)
  1740. {
  1741. if((lin[i]-model->b)*(double)label[i] < 1.0-learn_parm->epsilon_crit)
  1742. loss+=1.0-(lin[i]-model->b)*(double)label[i];
  1743. model_length+=a[i]*label[i]*lin[i];
  1744. }
  1745. model_length=sqrt(model_length);
  1746. sprintf(temstr,"L1 loss: loss=%.5fn",loss);   printm(temstr);
  1747. sprintf(temstr,"Norm of weight vector: |w|=%.5fn",model_length);printm(temstr);
  1748. example_length=estimate_sphere(model,kernel_parm); 
  1749. sprintf(temstr,"Norm of longest example vector: |x|=%.5fn",  length_of_longest_document_vector(docs,totdoc,kernel_parm));
  1750. printm(temstr);
  1751. sprintf(temstr,"Estimated VCdim of classifier: VCdim<=%.5fn",       estimate_margin_vcdim(model,model_length,example_length,    kernel_parm));
  1752. printm(temstr);
  1753. if((!learn_parm->remove_inconsistent) && (!transduction)) 
  1754. {
  1755. runtime_start_xa=get_runtime();
  1756.                      sprintf(temstr,"Computing XiAlpha-estimates..."); 
  1757.                      printm(temstr);
  1758.                      compute_xa_estimates(model,label,unlabeled,totdoc,docs,lin,a,
  1759.                          kernel_parm,learn_parm,&(model->xa_error),
  1760.                          &(model->xa_recall),&(model->xa_precision));
  1761.                      
  1762.                      
  1763.                      sprintf(temstr,"Runtime for XiAlpha-estimates in cpu-seconds: %.2fn",
  1764.                          (get_runtime()-runtime_start_xa)/100.0);
  1765.                      printm(temstr);
  1766.                      
  1767.                      fprintf(stdout,"XiAlpha-estimate of the error: error<=%.2f%% (rho=%.2f,depth=%ld)n",
  1768.                          model->xa_error,learn_parm->rho,learn_parm->xa_depth);
  1769.                      fprintf(stdout,"XiAlpha-estimate of the recall: recall=>%.2f%% (rho=%.2f,depth=%ld)n",
  1770.                          model->xa_recall,learn_parm->rho,learn_parm->xa_depth);
  1771.                      fprintf(stdout,"XiAlpha-estimate of the precision: precision=>%.2f%% (rho=%.2f,depth=%ld)n",
  1772.                          model->xa_precision,learn_parm->rho,learn_parm->xa_depth);
  1773.                  }
  1774.                  else if(!learn_parm->remove_inconsistent)
  1775.                  {
  1776.                      estimate_transduction_quality(model,label,unlabeled,totdoc,docs,lin);
  1777.                  }
  1778.              }
  1779. if (com_pro.show_trainresult)
  1780. {
  1781. sprintf(temstr,"Number of kernel evaluations: %ldn",com_result.kernel_cache_statistic);
  1782.         printm(temstr);
  1783. }
  1784.              /* leave-one-out testing starts now */
  1785.              if(learn_parm->compute_loo)
  1786.              {
  1787.                  /* save results of training on full dataset for leave-one-out */
  1788.                  runtime_start_loo=get_runtime();
  1789.                  for(i=0;i<totdoc;i++) 
  1790.                  {
  1791.                      xi_fullset[i]=1.0-((lin[i]-model->b)*(double)label[i]);
  1792.                      a_fullset[i]=a[i];
  1793.                  }
  1794.                  sprintf(temstr,"Computing leave-one-out");
  1795.                  printm(temstr);
  1796.                  
  1797.                  /* repeat this loop for every held-out example */
  1798.                  for(heldout=0;(heldout<totdoc);heldout++)
  1799.                  {
  1800.                      if(learn_parm->rho*a_fullset[heldout]*r_delta_sq+xi_fullset[heldout]
  1801.                          < 1.0) 
  1802.                      { 
  1803.                          /* guaranteed to not produce a leave-one-out error */
  1804.                          sprintf(temstr,"+"); 
  1805.                          printm(temstr);
  1806.                      }
  1807.                      else if(xi_fullset[heldout] > 1.0) 
  1808.                      {
  1809.                          /* guaranteed to produce a leave-one-out error */
  1810.                          loo_count++;
  1811.                          if(label[heldout] > 0) loo_count_pos++; else loo_count_neg++;
  1812.                          sprintf(temstr,"-");  printm(temstr);
  1813.                      }
  1814.                      else
  1815.                      {
  1816.                          loocomputed++;
  1817.                          heldout_c=learn_parm->svm_cost[heldout]; /* set upper bound to zero */
  1818.                          learn_parm->svm_cost[heldout]=0;
  1819.                          /* make sure heldout example is not currently  */
  1820.                          /* shrunk away. Assumes that lin is up to date! */
  1821.                          shrink_state.active[heldout]=1;  
  1822.                          
  1823.                          
  1824.                          optimize_to_convergence(docs,label,totdoc,totwords,learn_parm,
  1825.                              kernel_parm,
  1826.                              kernel_cache,&shrink_state,model,inconsistent,unlabeled,
  1827.                              a,lin,&timing_profile,
  1828.                              &maxdiff,heldout,(long)2);
  1829.                          
  1830.                          /* printf("%fn",(lin[heldout]-model->b)*(double)label[heldout]); */
  1831.                          
  1832.                          if(((lin[heldout]-model->b)*(double)label[heldout]) < 0.0)
  1833.                          { 
  1834.                              loo_count++;                           /* there was a loo-error */
  1835.                              if(label[heldout] > 0) loo_count_pos++; else loo_count_neg++;
  1836.                          }
  1837.                          else
  1838.                          {
  1839.                              
  1840.                          }
  1841.                          /* now we need to restore the original data set*/
  1842.                          learn_parm->svm_cost[heldout]=heldout_c; /* restore upper bound */
  1843.                      }
  1844.                  } /* end of leave-one-out loop */
  1845.                  
  1846.                  
  1847.                  sprintf(temstr,"nRetrain on full problem");  printm(temstr);
  1848.                  optimize_to_convergence(docs,label,totdoc,totwords,learn_parm,
  1849.                      kernel_parm,
  1850.                      kernel_cache,&shrink_state,model,inconsistent,unlabeled,
  1851.                      a,lin,&timing_profile,
  1852.                      &maxdiff,(long)-1,(long)1);
  1853.                  
  1854.                  
  1855.                  /* after all leave-one-out computed */
  1856.                  model->loo_error=100.0*loo_count/(double)totdoc;
  1857.                  model->loo_recall=(1.0-(double)loo_count_pos/(double)trainpos)*100.0;
  1858.                  model->loo_precision=(trainpos-loo_count_pos)/
  1859.                      (double)(trainpos-loo_count_pos+loo_count_neg)*100.0;
  1860.                  fprintf(stdout,"Leave-one-out estimate of the error: error=%.2f%%n",
  1861.                      model->loo_error);
  1862.                  fprintf(stdout,"Leave-one-out estimate of the recall: recall=%.2f%%n",
  1863.                      model->loo_recall);
  1864.                  fprintf(stdout,"Leave-one-out estimate of the precision: precision=%.2f%%n",
  1865.                      model->loo_precision);
  1866.                  fprintf(stdout,"Actual leave-one-outs computed:  %ld (rho=%.2f)n",
  1867.                      loocomputed,learn_parm->rho);
  1868.                  sprintf(temstr,"Runtime for leave-one-out in cpu-seconds: %.2fn",
  1869.                      (double)(get_runtime()-runtime_start_loo)/100.0);
  1870.                  printm(temstr);
  1871.              }
  1872.              
  1873.              // if(learn_parm->alphafile[0])
  1874.              //     write_alphas(learn_parm->alphafile,a,label,totdoc);
  1875.              
  1876.              shrink_state_cleanup(&shrink_state);
  1877.              
  1878.              free(inconsistent);
  1879.              free(unlabeled);
  1880.              free(a);
  1881.              free(a_fullset);
  1882.              free(xi_fullset);
  1883.              free(lin);
  1884.              free(learn_parm->svm_cost);
  1885. }
  1886. long CSVM::optimize_to_convergence(
  1887.                              DOC *docs,
  1888.                              long *label,
  1889.                              long totdoc,
  1890.                              long totwords,           
  1891.                              LEARN_PARM *learn_parm,    
  1892.                              KERNEL_PARM *kernel_parm,  
  1893.                              KERNEL_CACHE *kernel_cache,
  1894.                              SHRINK_STATE *shrink_state,
  1895.                              MODEL *model,              
  1896.                              long *inconsistent,
  1897.                              long *unlabeled,
  1898.                              double *a,
  1899.                              double *lin,
  1900.                              TIMING *timing_profile,
  1901.                              double *maxdiff,
  1902.                              long heldout,
  1903.                              long retrain)
  1904. {
  1905.     long *chosen,*key,i,j,jj,*last_suboptimal_at,noshrink;
  1906.     long inconsistentnum,choosenum,already_chosen=0,iteration;
  1907.     long misclassified,supvecnum=0,*active2dnum,inactivenum;
  1908.     long *working2dnum,*selexam;
  1909.     long activenum;
  1910.     double criterion,eq;
  1911.     double *a_old;
  1912.     long t0=0,t1=0,t2=0,t3=0,t4=0,t5=0,t6=0; /* timing */
  1913.     long transductcycle;
  1914.     long transduction;
  1915.     double epsilon_crit_org; 
  1916.     
  1917.     double *selcrit;  /* buffer for sorting */        
  1918.     CFLOAT *aicache;  /* buffer to keep one row of hessian */
  1919.     double *weights;  /* buffer for weight vector in linear case */
  1920.     QP qp;            /* buffer for one quadratic program */
  1921.     
  1922.     epsilon_crit_org=learn_parm->epsilon_crit; /* save org */
  1923.     if(kernel_parm->kernel_type == LINEAR)
  1924.     {
  1925.         learn_parm->epsilon_crit=2.0;
  1926.         kernel_cache=NULL;   /* caching makes no sense for linear kernel */
  1927.     } 
  1928.     learn_parm->epsilon_shrink=2;
  1929.     (*maxdiff)=1;
  1930.     
  1931.     learn_parm->totwords=totwords;
  1932.     
  1933.     chosen = (long *)my_malloc(sizeof(long)*totdoc);
  1934.     last_suboptimal_at = (long *)my_malloc(sizeof(long)*totdoc);
  1935.     key = (long *)my_malloc(sizeof(long)*(totdoc+11)); 
  1936.     selcrit = (double *)my_malloc(sizeof(double)*totdoc);
  1937.     selexam = (long *)my_malloc(sizeof(long)*totdoc);
  1938.     a_old = (double *)my_malloc(sizeof(double)*totdoc);
  1939.     aicache = (CFLOAT *)my_malloc(sizeof(CFLOAT)*totdoc);
  1940.     working2dnum = (long *)my_malloc(sizeof(long)*(totdoc+11));
  1941.     active2dnum = (long *)my_malloc(sizeof(long)*(totdoc+11));
  1942.     qp.opt_ce = (double *)my_malloc(sizeof(double)*learn_parm->svm_maxqpsize);
  1943.     qp.opt_ce0 = (double *)my_malloc(sizeof(double));
  1944.     qp.opt_g = (double *)my_malloc(sizeof(double)*learn_parm->svm_maxqpsize
  1945.         *learn_parm->svm_maxqpsize);
  1946.     qp.opt_g0 = (double *)my_malloc(sizeof(double)*learn_parm->svm_maxqpsize);
  1947.     qp.opt_xinit = (double *)my_malloc(sizeof(double)*learn_parm->svm_maxqpsize);
  1948.     qp.opt_low=(double *)my_malloc(sizeof(double)*learn_parm->svm_maxqpsize);
  1949.     qp.opt_up=(double *)my_malloc(sizeof(double)*learn_parm->svm_maxqpsize);
  1950.     weights=(double *)my_malloc(sizeof(double)*(totwords+1));
  1951.     
  1952.     choosenum=0;
  1953.     inconsistentnum=0;
  1954.     transductcycle=0;
  1955.     transduction=0;
  1956.     if(!retrain) retrain=1;
  1957.     iteration=1;
  1958.     
  1959.     if(kernel_cache)
  1960.     {
  1961.         kernel_cache->time=iteration;  /* for lru cache */
  1962.         kernel_cache_reset_lru(kernel_cache);
  1963.     }
  1964.     
  1965.     for(i=0;i<totdoc;i++)
  1966.     {    /* various inits */
  1967.         chosen[i]=0;
  1968.         a_old[i]=a[i];
  1969.         last_suboptimal_at[i]=1;
  1970.         if(inconsistent[i]) 
  1971.             inconsistentnum++;
  1972.         if(unlabeled[i]) 
  1973.         {
  1974.             transduction=1;
  1975.         }
  1976.     }
  1977.     activenum=compute_index(shrink_state->active,totdoc,active2dnum);
  1978.     inactivenum=totdoc-activenum;
  1979.     clear_index(working2dnum);
  1980.     
  1981.     /* repeat this loop until we have convergence */
  1982.     for(;retrain;iteration++) 
  1983.     {
  1984.         
  1985.         if(kernel_cache)
  1986.             kernel_cache->time=iteration;  /* for lru cache */
  1987.         i=0;
  1988.         for(jj=0;(j=working2dnum[jj])>=0;jj++)
  1989.         { /* clear working set */
  1990.             if((chosen[j]>=(learn_parm->svm_maxqpsize/
  1991.                 minl(learn_parm->svm_maxqpsize,
  1992.                 learn_parm->svm_newvarsinqp))) 
  1993.                 || (inconsistent[j])
  1994.                 || (j == heldout)) 
  1995.             {
  1996.                 chosen[j]=0; 
  1997.                 choosenum--; 
  1998.             }
  1999.             else 
  2000.             {
  2001.                 chosen[j]++;
  2002.                 working2dnum[i++]=j;
  2003.             }
  2004.         }
  2005.         working2dnum[i]=-1;
  2006.         
  2007.         if(retrain == 2)
  2008.         {
  2009.             choosenum=0;
  2010.             for(jj=0;(j=working2dnum[jj])>=0;jj++) 
  2011.             { /* fully clear working set */
  2012.                 chosen[j]=0; 
  2013.             }
  2014.             clear_index(working2dnum);
  2015.             for(i=0;i<totdoc;i++) 
  2016.             { /* set inconsistent examples to zero (-i 1) */
  2017.                 if((inconsistent[i] || (heldout==i)) && (a[i] != 0.0)) 
  2018.                 {
  2019.                     chosen[i]=99999;
  2020.                     choosenum++;
  2021.                     a[i]=0;
  2022.                 }
  2023.             }
  2024.             if(learn_parm->biased_hyperplane)
  2025.             {
  2026.                 eq=0;
  2027.                 for(i=0;i<totdoc;i++) 
  2028.                 { /* make sure we fulfill equality constraint */
  2029.                     eq+=a[i]*label[i];
  2030.                 }
  2031.                 for(i=0;(i<totdoc) && (fabs(eq) > learn_parm->epsilon_a);i++) 
  2032.                 {
  2033.                     if((eq*label[i] > 0) && (a[i] > 0)) 
  2034.                     {
  2035.                         chosen[i]=88888;
  2036.                         choosenum++;
  2037.                         if((eq*label[i]) > a[i]) 
  2038.                         {
  2039.                             eq-=(a[i]*label[i]);
  2040.                             a[i]=0;
  2041.                         }
  2042.                         else 
  2043.                         {
  2044.                             a[i]-=(eq*label[i]);
  2045.                             eq=0;
  2046.                         }
  2047.                     }
  2048.                 }
  2049.             }
  2050.             compute_index(chosen,totdoc,working2dnum);
  2051.         }
  2052.         else
  2053.         {      /* select working set according to steepest gradient */ 
  2054.             if((minl(learn_parm->svm_newvarsinqp,learn_parm->svm_maxqpsize)>=4) 
  2055.                 && (kernel_parm->kernel_type != LINEAR)) 
  2056.             {
  2057.                 /* select part of the working set from cache */
  2058.                 already_chosen=select_next_qp_subproblem_grad_cache(
  2059.                     label,unlabeled,a,lin,totdoc,
  2060.                     minl((long)(learn_parm->svm_maxqpsize-choosenum),
  2061.                     (long)(learn_parm->svm_newvarsinqp/2)),
  2062.                     learn_parm,inconsistent,active2dnum,
  2063.                     working2dnum,selcrit,selexam,kernel_cache,
  2064.                     key,chosen);
  2065.                 choosenum+=already_chosen;
  2066.             }
  2067.             choosenum+=select_next_qp_subproblem_grad(label,unlabeled,a,lin,totdoc,
  2068.                 minl((long)(learn_parm->svm_maxqpsize-choosenum),
  2069.                 (long)(learn_parm->svm_newvarsinqp-already_chosen)),
  2070.                 learn_parm,inconsistent,active2dnum,
  2071.                 working2dnum,selcrit,selexam,kernel_cache,key,
  2072.                 chosen);
  2073.         }
  2074.         
  2075.         //      sprintf(temstr," %ld vectors chosenn",choosenum);  printm(temstr);
  2076.         
  2077.         
  2078.         t1=get_runtime();
  2079.         
  2080.         if(kernel_cache) 
  2081.             cache_multiple_kernel_rows(kernel_cache,docs,working2dnum,choosenum,kernel_parm); 
  2082.         
  2083.         
  2084.         t2=get_runtime();
  2085.         if(retrain != 2)
  2086.         {
  2087.             optimize_svm(docs,label,unlabeled,chosen,active2dnum,model,totdoc,
  2088.                 working2dnum,choosenum,a,lin,learn_parm,aicache,
  2089.                 kernel_parm,&qp,&epsilon_crit_org);
  2090.         }
  2091.         
  2092.         
  2093.         t3=get_runtime();
  2094.         update_linear_component(docs,label,active2dnum,a,a_old,working2dnum,totdoc,
  2095.             totwords,kernel_parm,kernel_cache,lin,aicache,weights);
  2096.         
  2097.         
  2098.         
  2099.         t4=get_runtime();
  2100.         supvecnum=calculate_svm_model(docs,label,unlabeled,lin,a,a_old,learn_parm,
  2101.             working2dnum,model);
  2102.         
  2103.         
  2104.         t5=get_runtime();
  2105.         
  2106.         /* The following computation of the objective function works only */
  2107.         /* relative to the active variables */
  2108.         
  2109.         criterion=compute_objective_function(a,lin,label,active2dnum);
  2110.         //  sprintf(temstr,"Objective function (over active variables): %.16fn",criterion);
  2111.         //  printm(temstr);
  2112.         
  2113.         for(jj=0;(i=working2dnum[jj])>=0;jj++)