void mexFunction(int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[]) { double *c=NULL, *b=NULL, *A=NULL, *Q=NULL, *H=NULL, *l=NULL, *u=NULL, *x=NULL, *lambda=NULL, *x0=NULL, *primal=NULL, *dual=NULL; double *tmpdp=NULL; double big=Inf; unsigned int neq=0; long nmat=0, mmat=0; long how=0; int i; unsigned int verb = 0; double sigfig_max = 8; int counter_max = 100000; double margin = 0.95; double bound = 10; int restart = 0; static char *str[] = { "STILL_RUNNING", "OPTIMAL_SOLUTION", "SUBOPTIMAL_SOLUTION", "ITERATION_LIMIT", "PRIMAL_INFEASIBLE", "DUAL_INFEASIBLE", "PRIMAL_AND_DUAL_INFEASIBLE", "INCONSISTENT", "PRIMAL_UNBOUNDED", "DUAL_UNBOUNDED", "TIME_LIMIT"}; if (nrhs > 9 || nrhs < 1) { mexErrMsgTxt("Usage: [x,lambda,how] = qp(H,c,A,b,l,u,x0,neqcstr,verbosity)"); return; } switch (nrhs) { case 9: if (mxGetM(prhs[8]) != 0 || mxGetN(prhs[8]) != 0) { if (!mxIsNumeric(prhs[8]) || mxIsComplex(prhs[8]) || mxIsSparse(prhs[8]) || !(mxGetM(prhs[8])==1 && mxGetN(prhs[8])==1)) { mexErrMsgTxt("Ninth argument (display) must be " "an integer scalar."); return; } verb = (unsigned int)*mxGetPr(prhs[8]); } case 8: if (mxGetM(prhs[7]) != 0 || mxGetN(prhs[7]) != 0) { if (!mxIsNumeric(prhs[7]) || mxIsComplex(prhs[7]) || mxIsSparse(prhs[7]) || !(mxGetM(prhs[7])==1 && mxGetN(prhs[7])==1)) { mexErrMsgTxt("Eighth argument (neqcstr) must be " "an integer scalar."); return; } neq = (unsigned int)*mxGetPr(prhs[7]); } case 7: if (mxGetM(prhs[6]) != 0 || mxGetN(prhs[6]) != 0) { if (!mxIsNumeric(prhs[6]) || mxIsComplex(prhs[6]) || mxIsSparse(prhs[6]) || !mxIsDouble(prhs[6]) || mxGetN(prhs[6])!=1 ) { mexErrMsgTxt("Seventh argument (x0) must be " "a column vector."); return; } x0 = mxGetPr(prhs[6]); nmat = mxGetM(prhs[6]); } case 6: if (mxGetM(prhs[5]) != 0 || mxGetN(prhs[5]) != 0) { if (!mxIsNumeric(prhs[5]) || mxIsComplex(prhs[5]) || mxIsSparse(prhs[5]) || !mxIsDouble(prhs[5]) || mxGetN(prhs[5])!=1 ) { mexErrMsgTxt("Sixth argument (u) must be " "a column vector."); return; } if (nmat != 0 && nmat != mxGetM(prhs[5])) { mexErrMsgTxt("Dimension error (arg 6 and later)."); return; } u = mxGetPr(prhs[5]); nmat = mxGetM(prhs[5]); } case 5: if (mxGetM(prhs[4]) != 0 || mxGetN(prhs[4]) != 0) { if (!mxIsNumeric(prhs[4]) || mxIsComplex(prhs[4]) || mxIsSparse(prhs[4]) || !mxIsDouble(prhs[4]) || mxGetN(prhs[4])!=1 ) { mexErrMsgTxt("Fifth argument (l) must be " "a column vector."); return; } if (nmat != 0 && nmat != mxGetM(prhs[4])) { mexErrMsgTxt("Dimension error (arg 5 and later)."); return; } l = mxGetPr(prhs[4]); nmat = mxGetM(prhs[4]); } case 4: if (mxIsEmpty(prhs[3])) { /* No Constraints*/ mmat = 0; } else { /*Constraints*/ if (mxGetM(prhs[3]) != 0 || mxGetN(prhs[3]) != 0) { if (!mxIsNumeric(prhs[3]) || mxIsComplex(prhs[3]) || mxIsSparse(prhs[3]) || !mxIsDouble(prhs[3]) || mxGetN(prhs[3])!=1 ) { mexErrMsgTxt("Fourth argument (b) must be " "a column vector."); return; } if (mmat != 0 && mmat != mxGetM(prhs[3])) { mexErrMsgTxt("Dimension error (arg 4 and later)."); return; } b = mxGetPr(prhs[3]); } } case 3: if (mxIsEmpty(prhs[2])) { /* No Constraints */ if (mmat != 0) { mexErrMsgTxt("Dimension error (arg 3 and later)."); return; } } else { /* Constraints */ if (mxGetM(prhs[2]) != 0 || mxGetN(prhs[2]) != 0) { if (!mxIsNumeric(prhs[2]) || mxIsComplex(prhs[2]) || mxIsSparse(prhs[2]) ) { mexErrMsgTxt("Third argument (A) must be " "a matrix."); return; } if (mmat != 0 && mmat != mxGetM(prhs[2])) { mexErrMsgTxt("Dimension error (arg 3 and later)."); return; } if (nmat != 0 && nmat != mxGetN(prhs[2])) { mexErrMsgTxt("Dimension error (arg 3 and later)."); return; } mmat = mxGetM(prhs[2]); nmat = mxGetN(prhs[2]); A = mxGetPr(prhs[2]); } } tmpdp = (double *)malloc((nmat+mmat)*sizeof(double)); for(i=0;i<nmat;i++) tmpdp[i] = (l[i] < -Inf ? -Inf : l[i]); l = tmpdp; tmpdp = (double *)malloc((nmat+mmat)*sizeof(double)); for(i=0;i<nmat;i++) tmpdp[i] = (u[i] > Inf ? Inf : u[i]); u = tmpdp; for(i=nmat;i<(int)(nmat+neq);i++) { l[i] = u[i] = 0; } for(i=nmat + neq;i<nmat+mmat;i++) { l[i] = -Inf; u[i] = 0; } case 2: if (mxGetM(prhs[1]) != 0 || mxGetN(prhs[1]) != 0) { if (!mxIsNumeric(prhs[1]) || mxIsComplex(prhs[1]) || mxIsSparse(prhs[1]) || !mxIsDouble(prhs[1]) || mxGetN(prhs[1])!=1 ) { mexErrMsgTxt("Second argument (c) must be " "a column vector."); return; } if (nmat != 0 && nmat != mxGetM(prhs[1])) { mexErrMsgTxt("Dimension error (arg 2 and later)."); return; } c = mxGetPr(prhs[1]); nmat = mxGetM(prhs[1]); } case 1: if (mxIsEmpty(prhs[0])) { H = (double *)calloc(nmat*nmat,sizeof(double)); } else { if (mxGetM(prhs[0]) != 0 || mxGetN(prhs[0]) != 0) { if (!mxIsNumeric(prhs[0]) || mxIsComplex(prhs[0]) || mxIsSparse(prhs[0]) ) { mexErrMsgTxt("First argument (H) must be " "a matrix."); return; } if (nmat != 0 && nmat != mxGetM(prhs[0])) { mexErrMsgTxt("Dimension error (arg 1 and later)."); return; } if (nmat != 0 && nmat != mxGetN(prhs[0])) { mexErrMsgTxt("Dimension error (arg 1 and later)."); return; } nmat = mxGetN(prhs[0]); Q = mxGetPr(prhs[0]); H = (double *)calloc(nmat*nmat,sizeof(double)); for(i=0;i<nmat*nmat;i++) H[i] = Q[i]; } } break; } if (nlhs > 3 || nlhs < 1) { mexErrMsgTxt("Usage: [x,lambda,how] = qp(H,c,A,b,l,u,x0,neqcstr,verbosity)"); return; } primal = (double *)calloc((3*nmat),sizeof(double)); dual = (double *)calloc((mmat+2*nmat),sizeof(double)); how = pr_loqo(nmat, mmat, c, H, A, b, l, u, primal, dual, verb, sigfig_max, counter_max, margin, bound, restart); switch (nlhs) { case 3: plhs[2] = mxCreateString(str[how]); case 2: plhs[1] = mxCreateDoubleMatrix(mmat, 1, mxREAL); lambda = mxGetPr(plhs[1]); for(i=0; i<mmat; i++) lambda[i] = dual[i]; case 1: plhs[0] = mxCreateDoubleMatrix(nmat, 1, mxREAL); x = mxGetPr(plhs[0]); for(i=0; i<nmat; i++) x[i] = primal[i]; break; } /* Free up memory */ free(l); free(u); free(primal); free(dual); free(H); }
double *optimize_qp2( QP *qp, double *epsilon_crit, long nx, /* Maximum number of variables in QP */ double *threshold, LEARN_PARM *learn_parm) /* start the optimizer and return the optimal values */ { register long i,j,result; double margin,obj_before,obj_after; double sigdig,dist,epsilon_loqo; int iter; if(!primal1) { /* allocate memory at first call */ primal1=(double *)my_malloc(sizeof(double)*nx*3); dual1=(double *)my_malloc(sizeof(double)*(nx*2+1)); } if(verbosity3>=4) { /* really verbose */ printf("\n\n"); for(i=0;i<qp->opt_n;i++) { printf("%f: ",qp->opt_g0[i]); for(j=0;j<qp->opt_n;j++) { printf("%f ",qp->opt_g[i*qp->opt_n+j]); } printf(": a%ld=%.10f < %f",i,qp->opt_xinit[i],qp->opt_up[i]); printf(": y=%f\n",qp->opt_ce[i]); } for(j=0;j<qp->opt_m;j++) { printf("EQ-%ld: %f*a0",j,qp->opt_ce[j]); for(i=1;i<qp->opt_n;i++) { printf(" + %f*a%ld",qp->opt_ce[i],i); } printf(" = %f\n\n",-qp->opt_ce0[0]); } } obj_before=0; /* calculate objective before optimization */ for(i=0;i<qp->opt_n;i++) { obj_before+=(qp->opt_g0[i]*qp->opt_xinit[i]); obj_before+=(0.5*qp->opt_xinit[i]*qp->opt_xinit[i]*qp->opt_g[i*qp->opt_n+i]); for(j=0;j<i;j++) { obj_before+=(qp->opt_xinit[j]*qp->opt_xinit[i]*qp->opt_g[j*qp->opt_n+i]); } } result=STILL_RUNNING; qp->opt_ce0[0]*=(-1.0); /* Run pr_loqo. If a run fails, try again with parameters which lead */ /* to a slower, but more robust setting. */ for(margin=init_margin,iter=init_iter; (margin<=0.9999999) && (result!=OPTIMAL_SOLUTION);) { sigdig=-log10(opt_precision2); result=pr_loqo((int)qp->opt_n,(int)qp->opt_m, (double *)qp->opt_g0,(double *)qp->opt_g, (double *)qp->opt_ce,(double *)qp->opt_ce0, (double *)qp->opt_low,(double *)qp->opt_up, (double *)primal1,(double *)dual1, (int)(verbosity3-2), (double)sigdig,(int)iter, (double)margin,(double)(qp->opt_up[0])/4.0,(int)0); if(isnan(dual1[0])) { /* check for choldc problem */ if(verbosity3>=2) { printf("NOTICE: Restarting PR_LOQO with more conservative parameters.\n"); } if(init_margin<0.80) { /* become more conservative in general */ init_margin=(4.0*margin+1.0)/5.0; } margin=(margin+1.0)/2.0; (opt_precision2)*=10.0; /* reduce precision */ if(verbosity3>=2) { printf("NOTICE: Reducing precision of PR_LOQO.\n"); } } else if(result!=OPTIMAL_SOLUTION) { iter+=2000; init_iter+=10; (opt_precision2)*=10.0; /* reduce precision */ if(verbosity3>=2) { printf("NOTICE: Reducing precision of PR_LOQO due to (%ld).\n",result); } } } if(qp->opt_m) /* Thanks to Alex Smola for this hint */ model_b=dual1[0]; else model_b=0; /* Check the precision of the alphas. If results of current optimization */ /* violate KT-Conditions, relax the epsilon on the bounds on alphas. */ epsilon_loqo=1E-10; for(i=0;i<qp->opt_n;i++) { dist=-model_b*qp->opt_ce[i]; dist+=(qp->opt_g0[i]+1.0); for(j=0;j<i;j++) { dist+=(primal1[j]*qp->opt_g[j*qp->opt_n+i]); } for(j=i;j<qp->opt_n;j++) { dist+=(primal1[j]*qp->opt_g[i*qp->opt_n+j]); } /* printf("LOQO: a[%d]=%f, dist=%f, b=%f\n",i,primal1[i],dist,dual1[0]); */ if((primal1[i]<(qp->opt_up[i]-epsilon_loqo)) && (dist < (1.0-(*epsilon_crit)))) { epsilon_loqo=(qp->opt_up[i]-primal1[i])*2.0; } else if((primal1[i]>(0+epsilon_loqo)) && (dist > (1.0+(*epsilon_crit)))) { epsilon_loqo=primal1[i]*2.0; } } for(i=0;i<qp->opt_n;i++) { /* clip alphas to bounds */ if(primal1[i]<=(0+epsilon_loqo)) { primal1[i]=0; } else if(primal1[i]>=(qp->opt_up[i]-epsilon_loqo)) { primal1[i]=qp->opt_up[i]; } } obj_after=0; /* calculate objective after optimization */ for(i=0;i<qp->opt_n;i++) { obj_after+=(qp->opt_g0[i]*primal1[i]); obj_after+=(0.5*primal1[i]*primal1[i]*qp->opt_g[i*qp->opt_n+i]); for(j=0;j<i;j++) { obj_after+=(primal1[j]*primal1[i]*qp->opt_g[j*qp->opt_n+i]); } } /* if optimizer returned NAN values, reset and retry with smaller */ /* working set. */ if(isnan(obj_after) || isnan(model_b)) { for(i=0;i<qp->opt_n;i++) { primal1[i]=qp->opt_xinit[i]; } model_b=0; if(learn_parm->svm_maxqpsize>2) { learn_parm->svm_maxqpsize--; /* decrease size of qp-subproblems */ } } if(obj_after >= obj_before) { /* check whether there was progress */ (opt_precision2)/=100.0; precision_violations2++; if(verbosity3>=2) { printf("NOTICE: Increasing Precision of PR_LOQO.\n"); } } if(precision_violations2 > 500) { (*epsilon_crit)*=10.0; precision_violations2=0; if(verbosity3>=1) { printf("\nWARNING: Relaxing epsilon on KT-Conditions.\n"); } } (*threshold)=model_b; if(result!=OPTIMAL_SOLUTION) { printf("\nERROR: PR_LOQO did not converge. \n"); return(qp->opt_xinit); } else { return(primal1); } }