SHOGUN  3.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
QPBSVMLib.cpp
Go to the documentation of this file.
1 /*-----------------------------------------------------------------------
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 3 of the License, or
6  * (at your option) any later version.
7  *
8  * Library for solving QP task required for learning SVM without bias term.
9  *
10  * Written (W) 2006-2009 Vojtech Franc, xfrancv@cmp.felk.cvut.cz
11  * Written (W) 2007 Soeren Sonnenburg
12  * Copyright (C) 2006-2009 Center for Machine Perception, CTU FEL Prague
13  * Copyright (C) 2007-2009 Fraunhofer Institute FIRST
14  *
15  *
16  * min 0.5*x'*H*x + f'*x
17  *
18  * subject to C >= x(i) >= 0 for all i
19  *
20  * H [dim x dim] is symmetric positive semi-definite matrix.
21  * f [dim x 1] is an arbitrary vector.
22  *
23  * The precision of found solution is given by parameters
24  * tmax, tolabs, tolrel which define the stopping conditions:
25  *
26  * t >= tmax -> exit_flag = 0 Number of iterations.
27  * UB-LB <= tolabs -> exit_flag = 1 Abs. tolerance.
28  * UB-LB <= UB*tolrel -> exit_flag = 2 Relative tolerance.
29  *
30  * UB ... Upper bound on the optimal solution.
31  * LB ... Lower bound on the optimal solution.
32  * t ... Number of iterations.
33  * History ... Value of LB and UB wrt. number of iterations.
34  *
35  * 1. Generalized Gauss-Seidel methods
36  * exitflag = qpbsvm_sca( &get_col, diag_H, f, UB, dim, tmax,
37  * tolabs, tolrel, x, Nabla, &t, &History, verb )
38  *
39  * 2. Greedy variant - Udpate variable yielding the best improvement.
40  * exitflag = qpbsvm_scas( &get_col, diag_H, f, UB, dim, tmax,
41  * tolabs, tolrel, x, Nabla, &t, &History, verb )
42  *
43  * 3. Updates variable which most violates the KKT conditions
44  * exitflag = qpbsvm_scamv( &get_col, diag_H, f, UB, dim, tmax,
45  * tolabs, tolrel, tolKKT, x, Nabla, &t, &History, verb )
46  *
47 -------------------------------------------------------------------- */
48 
49 #include <string.h>
50 #include <limits.h>
51 
52 #include <shogun/lib/config.h>
53 #include <shogun/io/SGIO.h>
56 
58 #include <shogun/lib/external/pr_loqo.h>
59 
60 using namespace shogun;
61 
62 #define HISTORY_BUF 1000000
63 
64 #define INDEX(ROW,COL,DIM) ((COL*DIM)+ROW)
65 
67 {
68  SG_UNSTABLE("CQPBSVMLib::CQPBSVMLib()", "\n")
69 
70  m_H=0;
71  m_dim = 0;
72  m_diag_H = NULL;
73 
74  m_f = NULL;
75  m_UB = 0.0;
76  m_tmax = INT_MAX;
77  m_tolabs = 0;
78  m_tolrel = 1e-6;
79  m_tolKKT = 0;
80  m_solver = QPB_SOLVER_SCA;
81 }
82 
84  float64_t* H, int32_t n, float64_t* f, int32_t m, float64_t UB)
85 : CSGObject()
86 {
87  ASSERT(H && n>0)
88  m_H=H;
89  m_dim = n;
90  m_diag_H=NULL;
91 
92  m_f=f;
93  m_UB=UB;
94  m_tmax = INT_MAX;
95  m_tolabs = 0;
96  m_tolrel = 1e-6;
97  m_tolKKT = 0;
98  m_solver = QPB_SOLVER_SCA;
99 }
100 
102 {
103  SG_FREE(m_diag_H);
104 }
105 
106 int32_t CQPBSVMLib::solve_qp(float64_t* result, int32_t len)
107 {
108  int32_t status = -1;
109  ASSERT(len==m_dim)
110  float64_t* Nabla=SG_MALLOC(float64_t, m_dim);
111  for (int32_t i=0; i<m_dim; i++)
112  Nabla[i]=m_f[i];
113 
114  SG_FREE(m_diag_H);
115  m_diag_H=SG_MALLOC(float64_t, m_dim);
116 
117  for (int32_t i=0; i<m_dim; i++)
118  m_diag_H[i]=m_H[i*m_dim+i];
119 
120  float64_t* History=NULL;
121  int32_t t;
122  int32_t verb=0;
123 
124  switch (m_solver)
125  {
126  case QPB_SOLVER_GRADDESC:
127  status = qpbsvm_gradient_descent(result, Nabla, &t, &History, verb );
128  break;
129  case QPB_SOLVER_GS:
130  status = qpbsvm_gauss_seidel(result, Nabla, &t, &History, verb );
131  break;
132  case QPB_SOLVER_SCA:
133  status = qpbsvm_sca(result, Nabla, &t, &History, verb );
134  break;
135  case QPB_SOLVER_SCAS:
136  status = qpbsvm_scas(result, Nabla, &t, &History, verb );
137  break;
138  case QPB_SOLVER_SCAMV:
139  status = qpbsvm_scamv(result, Nabla, &t, &History, verb );
140  break;
141  case QPB_SOLVER_PRLOQO:
142  status = qpbsvm_prloqo(result, Nabla, &t, &History, verb );
143  break;
144 #ifdef USE_CPLEX
145  case QPB_SOLVER_CPLEX:
146  status = qpbsvm_cplex(result, Nabla, &t, &History, verb );
147 #else
148  SG_ERROR("cplex not enabled at compile time - unknow solver\n")
149 #endif
150  break;
151  default:
152  SG_ERROR("unknown solver\n")
153  break;
154  }
155 
156  SG_FREE(History);
157  SG_FREE(Nabla);
158  SG_FREE(m_diag_H);
159  m_diag_H=NULL;
160 
161  return status;
162 }
163 
164 /* --------------------------------------------------------------
165 
166 Usage: exitflag = qpbsvm_sca(m_UB, m_dim, m_tmax,
167  m_tolabs, m_tolrel, m_tolKKT, x, Nabla, &t, &History, verb )
168 
169 -------------------------------------------------------------- */
171  float64_t *Nabla,
172  int32_t *ptr_t,
173  float64_t **ptr_History,
174  int32_t verb)
175 {
176  float64_t *History;
177  float64_t *col_H;
178  float64_t *tmp_ptr;
179  float64_t x_old;
180  float64_t delta_x;
181  float64_t xHx;
182  float64_t Q_P;
183  float64_t Q_D;
184  float64_t xf;
185  float64_t xi_sum;
186  int32_t History_size;
187  int32_t t;
188  int32_t i, j;
189  int32_t exitflag;
190  int32_t KKTsatisf;
191 
192  /* ------------------------------------------------------------ */
193  /* Initialization */
194  /* ------------------------------------------------------------ */
195 
196  t = 0;
197 
198  History_size = (m_tmax < HISTORY_BUF ) ? m_tmax+1 : HISTORY_BUF;
199  History=SG_MALLOC(float64_t, History_size*2);
200  memset(History, 0, sizeof(float64_t)*History_size*2);
201 
202  /* compute Q_P and Q_D */
203  xHx = 0;
204  xf = 0;
205  xi_sum = 0;
206  for(i = 0; i < m_dim; i++ ) {
207  xHx += x[i]*(Nabla[i] - m_f[i]);
208  xf += x[i]*m_f[i];
209  xi_sum += CMath::max(0.0,-Nabla[i]);
210  }
211 
212  Q_P = 0.5*xHx + xf;
213  Q_D = -0.5*xHx - m_UB*xi_sum;
214  History[INDEX(0,t,2)] = Q_P;
215  History[INDEX(1,t,2)] = Q_D;
216 
217  if( verb > 0 ) {
218  SG_PRINT("%d: Q_P=%m_f, Q_D=%m_f, Q_P-Q_D=%m_f, (Q_P-Q_D)/|Q_P|=%m_f \n",
219  t, Q_P, Q_D, Q_P-Q_D,(Q_P-Q_D)/CMath::abs(Q_P));
220  }
221 
222  exitflag = -1;
223  while( exitflag == -1 )
224  {
225  t++;
226 
227  for(i = 0; i < m_dim; i++ ) {
228  if( m_diag_H[i] > 0 ) {
229  /* variable update */
230  x_old = x[i];
231  x[i] = CMath::min(m_UB,CMath::max(0.0, x[i] - Nabla[i]/m_diag_H[i]));
232 
233  /* update Nabla */
234  delta_x = x[i] - x_old;
235  if( delta_x != 0 ) {
236  col_H = (float64_t*)get_col(i);
237  for(j = 0; j < m_dim; j++ ) {
238  Nabla[j] += col_H[j]*delta_x;
239  }
240  }
241 
242  }
243  }
244 
245  /* compute Q_P and Q_D */
246  xHx = 0;
247  xf = 0;
248  xi_sum = 0;
249  KKTsatisf = 1;
250  for(i = 0; i < m_dim; i++ ) {
251  xHx += x[i]*(Nabla[i] - m_f[i]);
252  xf += x[i]*m_f[i];
253  xi_sum += CMath::max(0.0,-Nabla[i]);
254 
255  if((x[i] > 0 && x[i] < m_UB && CMath::abs(Nabla[i]) > m_tolKKT) ||
256  (x[i] == 0 && Nabla[i] < -m_tolKKT) ||
257  (x[i] == m_UB && Nabla[i] > m_tolKKT)) KKTsatisf = 0;
258  }
259 
260  Q_P = 0.5*xHx + xf;
261  Q_D = -0.5*xHx - m_UB*xi_sum;
262 
263  /* stopping conditions */
264  if(t >= m_tmax) exitflag = 0;
265  else if(Q_P-Q_D <= m_tolabs) exitflag = 1;
266  else if(Q_P-Q_D <= CMath::abs(Q_P)*m_tolrel) exitflag = 2;
267  else if(KKTsatisf == 1) exitflag = 3;
268 
269  if( verb > 0 && (t % verb == 0 || t==1)) {
270  SG_PRINT("%d: Q_P=%m_f, Q_D=%m_f, Q_P-Q_D=%m_f, (Q_P-Q_D)/|Q_P|=%m_f \n",
271  t, Q_P, Q_D, Q_P-Q_D,(Q_P-Q_D)/CMath::abs(Q_P));
272  }
273 
274  /* Store m_UB LB to History buffer */
275  if( t < History_size ) {
276  History[INDEX(0,t,2)] = Q_P;
277  History[INDEX(1,t,2)] = Q_D;
278  }
279  else {
280  tmp_ptr=SG_MALLOC(float64_t, (History_size+HISTORY_BUF)*2);
281  memset(tmp_ptr, 0, sizeof(float64_t)*(History_size+HISTORY_BUF)*2);
282 
283  for( i = 0; i < History_size; i++ ) {
284  tmp_ptr[INDEX(0,i,2)] = History[INDEX(0,i,2)];
285  tmp_ptr[INDEX(1,i,2)] = History[INDEX(1,i,2)];
286  }
287  tmp_ptr[INDEX(0,t,2)] = Q_P;
288  tmp_ptr[INDEX(1,t,2)] = Q_D;
289 
290  History_size += HISTORY_BUF;
291  SG_FREE(History);
292  History = tmp_ptr;
293  }
294  }
295 
296  (*ptr_t) = t;
297  (*ptr_History) = History;
298 
299  SG_PRINT("QP: %f QD: %f\n", Q_P, Q_D)
300 
301  return( exitflag );
302 }
303 
304 
305 /* --------------------------------------------------------------
306 
307 Usage: exitflag = qpbsvm_scas(m_UB, m_dim, m_tmax,
308  m_tolabs, m_tolrel, m_tolKKT, x, Nabla, &t, &History, verb )
309 
310 -------------------------------------------------------------- */
312  float64_t *Nabla,
313  int32_t *ptr_t,
314  float64_t **ptr_History,
315  int32_t verb)
316 {
317  float64_t *History;
318  float64_t *col_H;
319  float64_t *tmp_ptr;
320  float64_t x_old;
321  float64_t x_new;
322  float64_t delta_x;
323  float64_t max_x=CMath::INFTY;
324  float64_t xHx;
325  float64_t Q_P;
326  float64_t Q_D;
327  float64_t xf;
328  float64_t xi_sum;
329  float64_t max_update;
330  float64_t curr_update;
331  int32_t History_size;
332  int32_t t;
333  int32_t i, j;
334  int32_t max_i=-1;
335  int32_t exitflag;
336  int32_t KKTsatisf;
337 
338  /* ------------------------------------------------------------ */
339  /* Initialization */
340  /* ------------------------------------------------------------ */
341 
342  t = 0;
343 
344  History_size = (m_tmax < HISTORY_BUF ) ? m_tmax+1 : HISTORY_BUF;
345  History=SG_MALLOC(float64_t, History_size*2);
346  memset(History, 0, sizeof(float64_t)*History_size*2);
347 
348  /* compute Q_P and Q_D */
349  xHx = 0;
350  xf = 0;
351  xi_sum = 0;
352  for(i = 0; i < m_dim; i++ ) {
353  xHx += x[i]*(Nabla[i] - m_f[i]);
354  xf += x[i]*m_f[i];
355  xi_sum += CMath::max(0.0,-Nabla[i]);
356  }
357 
358  Q_P = 0.5*xHx + xf;
359  Q_D = -0.5*xHx - m_UB*xi_sum;
360  History[INDEX(0,t,2)] = Q_P;
361  History[INDEX(1,t,2)] = Q_D;
362 
363  if( verb > 0 ) {
364  SG_PRINT("%d: Q_P=%m_f, Q_D=%m_f, Q_P-Q_D=%m_f, (Q_P-Q_D)/|Q_P|=%m_f \n",
365  t, Q_P, Q_D, Q_P-Q_D,(Q_P-Q_D)/CMath::abs(Q_P));
366  }
367 
368  exitflag = -1;
369  while( exitflag == -1 )
370  {
371  t++;
372 
373  max_update = -CMath::INFTY;
374  for(i = 0; i < m_dim; i++ ) {
375  if( m_diag_H[i] > 0 ) {
376  /* variable update */
377  x_old = x[i];
378  x_new = CMath::min(m_UB,CMath::max(0.0, x[i] - Nabla[i]/m_diag_H[i]));
379 
380  curr_update = -0.5*m_diag_H[i]*(x_new*x_new-x_old*x_old) -
381  (Nabla[i] - m_diag_H[i]*x_old)*(x_new - x_old);
382 
383  if( curr_update > max_update ) {
384  max_i = i;
385  max_update = curr_update;
386  max_x = x_new;
387  }
388  }
389  }
390 
391  x_old = x[max_i];
392  x[max_i] = max_x;
393 
394  /* update Nabla */
395  delta_x = max_x - x_old;
396  if( delta_x != 0 ) {
397  col_H = (float64_t*)get_col(max_i);
398  for(j = 0; j < m_dim; j++ ) {
399  Nabla[j] += col_H[j]*delta_x;
400  }
401  }
402 
403  /* compute Q_P and Q_D */
404  xHx = 0;
405  xf = 0;
406  xi_sum = 0;
407  KKTsatisf = 1;
408  for(i = 0; i < m_dim; i++ ) {
409  xHx += x[i]*(Nabla[i] - m_f[i]);
410  xf += x[i]*m_f[i];
411  xi_sum += CMath::max(0.0,-Nabla[i]);
412 
413  if((x[i] > 0 && x[i] < m_UB && CMath::abs(Nabla[i]) > m_tolKKT) ||
414  (x[i] == 0 && Nabla[i] < -m_tolKKT) ||
415  (x[i] == m_UB && Nabla[i] > m_tolKKT)) KKTsatisf = 0;
416  }
417 
418  Q_P = 0.5*xHx + xf;
419  Q_D = -0.5*xHx - m_UB*xi_sum;
420 
421  /* stopping conditions */
422  if(t >= m_tmax) exitflag = 0;
423  else if(Q_P-Q_D <= m_tolabs) exitflag = 1;
424  else if(Q_P-Q_D <= CMath::abs(Q_P)*m_tolrel) exitflag = 2;
425  else if(KKTsatisf == 1) exitflag = 3;
426 
427  if( verb > 0 && (t % verb == 0 || t==1)) {
428  SG_PRINT("%d: Q_P=%m_f, Q_D=%m_f, Q_P-Q_D=%m_f, (Q_P-Q_D)/|Q_P|=%m_f \n",
429  t, Q_P, Q_D, Q_P-Q_D,(Q_P-Q_D)/CMath::abs(Q_P));
430  }
431 
432  /* Store m_UB LB to History buffer */
433  if( t < History_size ) {
434  History[INDEX(0,t,2)] = Q_P;
435  History[INDEX(1,t,2)] = Q_D;
436  }
437  else {
438  tmp_ptr=SG_MALLOC(float64_t, (History_size+HISTORY_BUF)*2);
439  memset(tmp_ptr, 0, (History_size+HISTORY_BUF)*2*sizeof(float64_t));
440  for( i = 0; i < History_size; i++ ) {
441  tmp_ptr[INDEX(0,i,2)] = History[INDEX(0,i,2)];
442  tmp_ptr[INDEX(1,i,2)] = History[INDEX(1,i,2)];
443  }
444  tmp_ptr[INDEX(0,t,2)] = Q_P;
445  tmp_ptr[INDEX(1,t,2)] = Q_D;
446 
447  History_size += HISTORY_BUF;
448  SG_FREE(History);
449  History = tmp_ptr;
450  }
451  }
452 
453  (*ptr_t) = t;
454  (*ptr_History) = History;
455 
456  return( exitflag );
457 }
458 
459 /* --------------------------------------------------------------
460 
461 Usage: exitflag = qpbsvm_scamv(m_UB, m_dim, m_tmax,
462  m_tolabs, m_tolrel, m_tolKKT, x, Nabla, &t, &History, verb )
463 
464 -------------------------------------------------------------- */
466  float64_t *Nabla,
467  int32_t *ptr_t,
468  float64_t **ptr_History,
469  int32_t verb)
470 {
471  float64_t *History;
472  float64_t *col_H;
473  float64_t delta_x;
474  float64_t x_new;
475  float64_t max_viol;
476  float64_t fval;
477  int32_t t;
478  int32_t i;
479  int32_t u=-1;
480  int32_t exitflag;
481 
482  /* ------------------------------------------------------------ */
483  /* Initialization */
484  /* ------------------------------------------------------------ */
485 
486  t = 0;
487  exitflag = -1;
488  while( exitflag == -1 && t <= m_tmax)
489  {
490  t++;
491 
492  max_viol = 0;
493  for(i = 0; i < m_dim; i++ )
494  {
495  if( x[i] == 0 )
496  {
497  if( max_viol < -Nabla[i]) { u = i; max_viol = -Nabla[i]; }
498  }
499  else if( x[i] > 0 && x[i] < m_UB )
500  {
501  if( max_viol < CMath::abs(Nabla[i]) ) { u = i; max_viol = CMath::abs(Nabla[i]); }
502  }
503  else if( max_viol < Nabla[i]) { u = i; max_viol = Nabla[i]; }
504  }
505 
506 /* SG_PRINT("%d: max_viol=%m_f, u=%d\n", t, max_viol, u)*/
507 
508  if( max_viol <= m_tolKKT )
509  {
510  exitflag = 1;
511  }
512  else
513  {
514  /* update */
515  x_new = CMath::min(m_UB,CMath::max(0.0, x[u] - Nabla[u]/m_diag_H[u]));
516 
517  delta_x = x_new - x[u];
518  x[u] = x_new;
519 
520  col_H = (float64_t*)get_col(u);
521  for(i = 0; i < m_dim; i++ ) {
522  Nabla[i] += col_H[i]*delta_x;
523  }
524  }
525  }
526 
527  History=SG_MALLOC(float64_t, (t+1)*2);
528  memset(History, 0, sizeof(float64_t)*(t+1)*2);
529 
530  fval = 0;
531  for(fval = 0, i = 0; i < m_dim; i++ ) {
532  fval += 0.5*x[i]*(Nabla[i]+m_f[i]);
533  }
534 
535  History[INDEX(0,t,2)] = fval;
536  History[INDEX(1,t,2)] = 0;
537 
538  (*ptr_t) = t;
539  (*ptr_History) = History;
540 
541 
542 
543  return( exitflag );
544 }
545 
546 /* --------------------------------------------------------------
547 
548 Usage: exitflag = qpbsvm_prloqo(m_UB, m_dim, m_tmax,
549  m_tolabs, m_tolrel, m_tolKKT, x, Nabla, &t, &History, verb )
550 
551 -------------------------------------------------------------- */
553  float64_t *Nabla,
554  int32_t *ptr_t,
555  float64_t **ptr_History,
556  int32_t verb)
557 {
558  float64_t* lb=SG_MALLOC(float64_t, m_dim);
559  float64_t* ub=SG_MALLOC(float64_t, m_dim);
560  float64_t* primal=SG_MALLOC(float64_t, 3*m_dim);
561  float64_t* dual=SG_MALLOC(float64_t, 1+2*m_dim);
562  float64_t* a=SG_MALLOC(float64_t, m_dim);
563 
564  for (int32_t i=0; i<m_dim; i++)
565  {
566  a[i]=0.0;
567  lb[i]=0;
568  ub[i]=m_UB;
569  }
570 
571  float64_t b=0;
572 
574  int32_t result=pr_loqo(m_dim, 1, m_f, m_H, a, &b, lb, ub, primal, dual,
575  2, 5, 1, -0.95, 10,0);
576 
577  SG_FREE(a);
578  SG_FREE(lb);
579  SG_FREE(ub);
580  SG_FREE(primal);
581  SG_FREE(dual);
582 
583  *ptr_t=0;
584  *ptr_History=NULL;
585  return result;
586 }
587 
589  float64_t *Nabla,
590  int32_t *ptr_t,
591  float64_t **ptr_History,
592  int32_t verb)
593 {
594  for (int32_t i=0; i<m_dim; i++)
595  x[i]=CMath::random(0.0, 1.0);
596 
597  for (int32_t t=0; t<200; t++)
598  {
599  for (int32_t i=0; i<m_dim; i++)
600  {
601  x[i]= (-m_f[i]-(SGVector<float64_t>::dot(x,&m_H[m_dim*i], m_dim) -
602  m_H[m_dim*i+i]*x[i]))/m_H[m_dim*i+i];
603  x[i]=CMath::clamp(x[i], 0.0, 1.0);
604  }
605  }
606 
607  int32_t atbound=0;
608  for (int32_t i=0; i<m_dim; i++)
609  {
610  if (x[i]==0.0 || x[i]==1.0)
611  atbound++;
612  }
613  SG_PRINT("atbound:%d of %d (%2.2f%%)\n", atbound, m_dim, ((float64_t) 100.0*atbound)/m_dim)
614  *ptr_t=0;
615  *ptr_History=NULL;
616  return 0;
617 }
618 
620  float64_t *Nabla,
621  int32_t *ptr_t,
622  float64_t **ptr_History,
623  int32_t verb)
624 {
625  for (int32_t i=0; i<m_dim; i++)
626  x[i]=CMath::random(0.0, 1.0);
627 
628  for (int32_t t=0; t<2000; t++)
629  {
630  for (int32_t i=0; i<m_dim; i++)
631  {
632  x[i]-=0.001*(SGVector<float64_t>::dot(x,&m_H[m_dim*i], m_dim)+m_f[i]);
633  x[i]=CMath::clamp(x[i], 0.0, 1.0);
634  }
635  }
636 
637  int32_t atbound=0;
638  for (int32_t i=0; i<m_dim; i++)
639  {
640  if (x[i]==0.0 || x[i]==1.0)
641  atbound++;
642  }
643  SG_PRINT("atbound:%d of %d (%2.2f%%)\n", atbound, m_dim, ((float64_t) 100.0*atbound)/m_dim)
644  *ptr_t=0;
645  *ptr_History=NULL;
646  return 0;
647 }
648 
649 #ifdef USE_CPLEX
650 /* --------------------------------------------------------------
651 
652 Usage: exitflag = qpbsvm_prloqo(m_UB, m_dim, m_tmax,
653  m_tolabs, m_tolrel, m_tolKKT, x, Nabla, &t, &History, verb )
654 
655 -------------------------------------------------------------- */
657  float64_t *Nabla,
658  int32_t *ptr_t,
659  float64_t **ptr_History,
660  int32_t verb)
661 {
662  float64_t* lb=SG_MALLOC(float64_t, m_dim);
663  float64_t* ub=SG_MALLOC(float64_t, m_dim);
664 
665  for (int32_t i=0; i<m_dim; i++)
666  {
667  lb[i]=0;
668  ub[i]=m_UB;
669  }
670 
671  CCplex cplex;
672  cplex.init(E_QP);
673  cplex.setup_lp(m_f, NULL, 0, m_dim, NULL, lb, ub);
674  cplex.setup_qp(m_H, m_dim);
675  cplex.optimize(x);
676  cplex.cleanup();
677 
678  SG_FREE(lb);
679  SG_FREE(ub);
680 
681  *ptr_t=0;
682  *ptr_History=NULL;
683  return 0;
684 }
685 #endif

SHOGUN Machine Learning Toolbox - Documentation