// Function definitions.
// -----------------------------------------------------------------
void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    //Input Args
    user_function_data fun;
    double *x0;
    double *ydata;
    double *lb, *ub;

    //Outputs Args
    double *x, *fval, *exitflag, *iter, *feval;

    //Internal Vars
    size_t ndec, ndat, i, j;
    int havJac = 0;
    int printLevel = 0;
    double *bounds = NULL;

    //NL2SOL Vars
    int n;                  //len data
    int p;                  //len x
    int *iv;                //intermediate work array
    double *v;              //intermediate work array
    int liv = 0, lv = 0;    //lengths of intermediate arrays
    int uiparm[2] = {1,0};  //user integer array [citer, printLevel]
    int one = 1, two = 2;
    //Defaults
    int maxfev = 1500;
    int maxiter = 1000;
    double frtol = 1e-7;
    double fatol = 1e-5;
    iterF.enabled = false;

    if (nrhs < 1) {
        if(nlhs < 1)
            printSolverInfo();
        else
            plhs[0] = mxCreateString(NL2SOL_VERSION);

        return;
    }

    //Check user inputs
    checkInputs(prhs,nrhs);

    //Get Sizes
    ndec = mxGetNumberOfElements(pX0);
    ndat = mxGetNumberOfElements(pYDATA);
    //Get Objective Function Handle
    if (mxIsChar(pFUN)) {
        CHECK(mxGetString(pFUN, fun.f, FLEN) == 0,"error reading objective name string");
        fun.nrhs = 1;
        fun.xrhs = 0;
    } else {
        fun.prhs[0] = (mxArray*)pFUN;
        strcpy(fun.f, "feval");
        fun.nrhs = 2;
        fun.xrhs = 1;
    }
    fun.prhs[fun.xrhs] = mxCreateDoubleMatrix(ndec, 1, mxREAL); //x0
    //Check and Get Gradient Function Handle
    if(!mxIsEmpty(pGRAD)) {
        havJac = 1;
        if (mxIsChar(pGRAD)) {
            CHECK(mxGetString(pGRAD, fun.g, FLEN) == 0,"error reading gradient name string");
            fun.nrhs_g = 1;
            fun.xrhs_g = 0;
        } else {
            fun.prhs_g[0] = (mxArray*)pGRAD;
            strcpy(fun.g, "feval");
            fun.nrhs_g = 2;
            fun.xrhs_g = 1;
        }
        fun.prhs_g[fun.xrhs_g] = mxCreateDoubleMatrix(ndec, 1, mxREAL); //x0
    }

    //Get x0 + data
    x0 = mxGetPr(pX0);
    ydata = mxGetPr(pYDATA);

    //Get bounds if specified
    if(nrhs > eUB && !mxIsEmpty(pUB))
    {
        lb = mxGetPr(pLB);
        ub = mxGetPr(pUB);
        bounds = (double*)mxCalloc(2*ndec,sizeof(double));
        //Copy bounds into nlsol b(2,p) array
        for(i=0,j=0; i<2*ndec; i+=2,j++)
        {
            if(mxIsInf(lb[j]))
                bounds[i] = -D1MACH(&two);
            else
                bounds[i] = lb[j];
            if(mxIsInf(ub[j]))
                bounds[i+1] = D1MACH(&two);
            else
                bounds[i+1] = ub[j];
        }
    }

    //Get Options if specified
    if(nrhs > eOPTS) {
        if(mxGetField(pOPTS,0,"display"))
            printLevel = (int)*mxGetPr(mxGetField(pOPTS,0,"display"));
        if(mxGetField(pOPTS,0,"maxfeval"))
            maxfev = (int)*mxGetPr(mxGetField(pOPTS,0,"maxfeval"));
        if(mxGetField(pOPTS,0,"maxiter"))
            maxiter = (int)*mxGetPr(mxGetField(pOPTS,0,"maxiter"));
        if(mxGetField(pOPTS,0,"tolrfun"))
            frtol = *mxGetPr(mxGetField(pOPTS,0,"tolrfun"));
        if(mxGetField(pOPTS,0,"tolafun"))
            fatol = *mxGetPr(mxGetField(pOPTS,0,"tolafun"));
        if(mxGetField(pOPTS,0,"iterfun") && !mxIsEmpty(mxGetField(pOPTS,0,"iterfun")))
        {
            iterF.prhs[0] = (mxArray*)mxGetField(pOPTS,0,"iterfun");
            strcpy(iterF.f, "feval");
            iterF.enabled = true;
            iterF.prhs[1] = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL);
            iterF.prhs[2] = mxCreateDoubleMatrix(1,1,mxREAL);
            iterF.prhs[3] = mxCreateDoubleMatrix(ndec,1,mxREAL);
        }
    }

    //Create Outputs
    plhs[0] = mxCreateDoubleMatrix(ndec,1, mxREAL);
    plhs[1] = mxCreateDoubleMatrix(1,1, mxREAL);
    plhs[2] = mxCreateDoubleMatrix(1,1, mxREAL);
    plhs[3] = mxCreateDoubleMatrix(1,1, mxREAL);
    plhs[4] = mxCreateDoubleMatrix(1,1, mxREAL);
    x = mxGetPr(plhs[0]);
    fval = mxGetPr(plhs[1]);
    exitflag = mxGetPr(plhs[2]);
    iter = mxGetPr(plhs[3]);
    feval = mxGetPr(plhs[4]);

    //Copy initial guess to x
    memcpy(x,x0,ndec*sizeof(double));

    //Print Header
    if(printLevel) {
        mexPrintf("\n------------------------------------------------------------------\n");
        if(havJac) {
            if(bounds)
                mexPrintf(" This is DN2GB (NL2SOL v%s)\n",NL2SOL_VERSION);
            else
                mexPrintf(" This is DN2G (NL2SOL v%s)\n",NL2SOL_VERSION);
        }
        else {
            if(bounds)
                mexPrintf(" This is DN2FB (NL2SNO v%s)\n",NL2SOL_VERSION);
            else
                mexPrintf(" This is DN2F (NL2SNO v%s)\n",NL2SOL_VERSION);
        }

        mexPrintf(" Authors: John Dennis, David Gay, Roy Welsch\n MEX Interface J. Currie 2012\n\n");
        mexPrintf(" Problem Properties:\n");
        mexPrintf(" # Decision Variables:     %4d\n",ndec);
        mexPrintf(" # Data Points:            %4d\n",ndat);

        mexPrintf("------------------------------------------------------------------\n");
    }

    //Assign Arguments
    n = (int)ndat;
    p = (int)ndec;
    if(bounds)
        liv = 82 + 4*p;
    else
        liv = 82+p;
    if(bounds)
        lv = 105 + p*(n + 2*p + 21) + 2*n;
    else
        lv = 105 + p*(n + 2*p + 17) + 2*n;
    iv = (int*)mxCalloc(liv + 10,sizeof(int));
    v  = (double*)mxCalloc(lv + 10,sizeof(double));
    //Set Options
    //DFAULT(iv,v); //set defaults (OLD v2.2)
    DIVSET(&one,iv,&liv,&lv,v);
    iv[13] = iv[14] = 0;        //no covar
    iv[16] = maxfev;    //limit on fevals + gevals
    iv[17] = maxiter;   //max iter
    iv[18] = 0;     //no iteration printing
    iv[19] = 0;     //no default printing
    iv[20] = 0;     //no output unit printing
    iv[21] = 0;     //no x printing
    iv[22] = 0;     //no summary printing
    iv[23] = 0;     //no initial printing
    v[30] = fatol;
    v[31] = frtol;
    //MEX Options
    uiparm[1] = printLevel;

    //Start timer
    start = clock();

    //Call Algorithm based on Derivatives
    if(havJac)
    {
        //NL2SOL(&n,&p,x,CALCR,CALCJ,iv,v,uiparm,ydata,&fun);
        if(bounds)
            DN2GB(&n,&p,x,bounds,CALCR,CALCJ,iv,&liv,&lv,v,uiparm,ydata,&fun);
        else
            DN2G(&n,&p,x,CALCR,CALCJ,iv,&liv,&lv,v,uiparm,ydata,&fun);
    }
    else
    {
        //#ifdef WIN64
        //    mexErrMsgTxt("Currently NL2SNO crashes when compiled on 64bit systems, try NL2SOL instead (supply a gradient)");
        //#else
        //NL2SNO(&n,&p,x,CALCR,iv,v,uiparm,ydata,&fun);
        if(bounds)
            DN2FB(&n,&p,x,bounds,CALCR,iv,&liv,&lv,v,uiparm,ydata,&fun);
        else
            DN2F(&n,&p,x,CALCR,iv,&liv,&lv,v,uiparm,ydata,&fun);
        //#endif
    }

    //Final Rnorm
    *fval = 2*v[9]; //nl2sol uses 1/2 sum(resid^2)
    //Save Status & Iterations
    *exitflag = getStatus(iv[0]);
    *iter = (double)iv[30];
    *feval = (double)uiparm[0];

    //Print Header
    if(printLevel) {
        //Termination Detected
        switch((int)iv[0])
        {
        //Success
        case 3:
            mexPrintf("\n *** SUCCESSFUL TERMINATION ***\n *** x-convergence ***\n");
            break;
        case 4:
            mexPrintf("\n *** SUCCESSFUL TERMINATION ***\n *** relative function convergence ***\n");
            break;
        case 5:
            mexPrintf("\n *** SUCCESSFUL TERMINATION ***\n *** both x and relative function convergence ***\n");
            break;
        case 6:
            mexPrintf("\n *** SUCCESSFUL TERMINATION ***\n *** absolute function convergence ***\n");
            break;
        //Error
        case 9:
            mexPrintf("\n *** MAXIMUM FUNCTION EVALUATIONS REACHED ***\n");
            break;
        case 10:
            mexPrintf("\n *** MAXIMUM ITERATIONS REACHED ***\n");
            break;
        case 13:
            mexPrintf("\n *** ERROR: f(x) cannot be computed at the initial x ***\n");
            break;
        case 14:
            mexPrintf("\n *** ERROR: bad parameters passed to asses ***\n");
            break;
        case 15:
            mexPrintf("\n *** ERROR: the jacobian cannot be computed at x ***\n");
            break;
        case 16:
            mexPrintf("\n *** ERROR: internal parameter n or p out of range ***\n");
            break;
        case 17:
            mexPrintf("\n *** ERROR: restart attempted with n or p changed ***\n");
            break;
        case 50:
            mexPrintf("\n *** ERROR: internal parameter iv(1) is out of range ***\n");
            break;
        //Early Exit
        case 7:
            mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: singular convergence. the hessian near the current iterate appears to be singular or nearly so. ***\n");
            break;
        case 8:
            mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: false convergence. the iterates appear to be converging to a noncritical point. this may mean that the convergence tolerances are too small ***\n");
            break;
        case 11:
            mexPrintf("\n *** TERMINATION: USER EXITED ***\n");
            break;
        //Other Error
        default:
            mexPrintf("\n *** ERROR: internal error code %d ***\n",(int)iv[0]);
            break;
        }

        if(*exitflag==1)
            mexPrintf("\n Final SSE: %12.5g\n In %3.0f iterations\n",*fval,*iter);

        mexPrintf("------------------------------------------------------------------\n\n");
    }

    //Free Memory
    if(iv) mxFree(iv);
    iv = NULL;
    if(v) mxFree(v);
    v = NULL;
    if(bounds) mxFree(bounds);
    bounds = NULL;
}
//Main Function
void mexFunction(int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[])
{
    //Input Args
    double *f, *A = NULL, *b = NULL, *lb = NULL, *ub = NULL, *y0 = NULL;
    double *sdpDIM = NULL, *SDP_pr = NULL;
    
    //Return Args
    double *x, *pval, *dval, *exitflag, *iter, *pdflag;
    
    //Options (most get defaults written in)
    int maxiter = 1500;  
    int reuse=4,rpos=0,drho=1,ndim,sdpnmax=1;
    double penalty,rho,dbound,dlbound,zbar,r0,mu0,ylow,yhigh,gaptol,pnormtol,maxtrust,steptol,inftol,infptol;
    double lpb=1.0, datanorm[3], *dreuse, *fixed = NULL;
    
    //Internal Vars
    size_t nlincon = 0, ndec = 0, ncones = 0, nfix = 0;
    size_t lincon_nz = 0;    
    size_t i, j;
    size_t nLB = 0, nUB = 0;
    int *temp_ir = NULL, *temp_jc = NULL;
    double *temp_pr = NULL;
    const char *onames[2] = {"pval","dval"};
    const char *fnames[11] = {"iter","pdflag","r","mu","pstep","dstep","pnorm","ynorm","tracex","reuse","rho"};    
    double evaltime, *X = NULL;
    int iters = 0, status, indcell = 0;
    
    //DSDP Vars
    DSDP dsdp;
    SDPCone sdpcone = NULL;
    LPCone lpcone   = NULL;
    BCone bcone     = NULL;
    DSDPTerminationReason reason;
    DSDPSolutionType pdfeasible;  

    //Sparse Indicing
    mwIndex *A_ir, *A_jc;
    //Version Return
    if(nrhs < 1) {
        if(nlhs < 1)
            printSolverInfo();
        else
            plhs[0] = mxCreateString(DSDP_VERSION);
        return;
    }        
    
    //Check Inputs
    checkInputs(prhs,nrhs); 
    
    //Get pointers to Input variables
	f = mxGetPr(pF); ndec = mxGetNumberOfElements(pF);
    if(!mxIsEmpty(pA)) {
        A = mxGetPr(pA); 
        A_ir = mxGetIr(pA);
        A_jc = mxGetJc(pA);
        b = mxGetPr(pB);
        nlincon = mxGetM(pA);
        lincon_nz = A_jc[mxGetN(pA)];
    }
    if(nrhs > eLB && !mxIsEmpty(pLB))
        lb = mxGetPr(pLB); 
    if(nrhs > eUB && !mxIsEmpty(pUB))
        ub = mxGetPr(pUB);
    if(nrhs > eSDP && !mxIsEmpty(pSDP)) {
        if(mxIsCell(pSDP))
            ncones = mxGetNumberOfElements(pSDP);
        else
            ncones = 1;
    }
    if(nrhs > eY0 && !mxIsEmpty(pY0))
        y0 = mxGetPr(pY0);
    if(nrhs > eOPTS && !mxIsEmpty(pOPTS) && mxGetField(pOPTS,0,"fixed") && !mxIsEmpty(mxGetField(pOPTS,0,"fixed"))) {
        fixed = mxGetPr(mxGetField(pOPTS,0,"fixed"));
        nfix = mxGetM(mxGetField(pOPTS,0,"fixed")); 
    }
    
    //Create Outputs
    plhs[0] = mxCreateDoubleMatrix(ndec,1, mxREAL);
    plhs[1] = mxCreateStructMatrix(1,1,2,onames);
    mxSetField(plhs[1],0,onames[0],mxCreateDoubleMatrix(1,1, mxREAL));
    mxSetField(plhs[1],0,onames[1],mxCreateDoubleMatrix(1,1, mxREAL));
    plhs[2] = mxCreateDoubleMatrix(1,1, mxREAL);   
    x = mxGetPr(plhs[0]); 
    pval = mxGetPr(mxGetField(plhs[1],0,onames[0]));
    dval = mxGetPr(mxGetField(plhs[1],0,onames[1]));
    exitflag = mxGetPr(plhs[2]);    
    //Info Output    
    plhs[3] = mxCreateStructMatrix(1,1,11,fnames);
    mxSetField(plhs[3],0,fnames[0],mxCreateDoubleMatrix(1,1, mxREAL));
    mxSetField(plhs[3],0,fnames[1],mxCreateDoubleMatrix(1,1, mxREAL));
    mxSetField(plhs[3],0,fnames[2],mxCreateDoubleMatrix(1,1, mxREAL));
    mxSetField(plhs[3],0,fnames[3],mxCreateDoubleMatrix(1,1, mxREAL));
    mxSetField(plhs[3],0,fnames[4],mxCreateDoubleMatrix(1,1, mxREAL));
    mxSetField(plhs[3],0,fnames[5],mxCreateDoubleMatrix(1,1, mxREAL));
    mxSetField(plhs[3],0,fnames[6],mxCreateDoubleMatrix(1,1, mxREAL));
    mxSetField(plhs[3],0,fnames[7],mxCreateDoubleMatrix(1,1, mxREAL));
    mxSetField(plhs[3],0,fnames[8],mxCreateDoubleMatrix(1,1, mxREAL));
    mxSetField(plhs[3],0,fnames[9],mxCreateDoubleMatrix(1,1, mxREAL));
    mxSetField(plhs[3],0,fnames[10],mxCreateDoubleMatrix(1,1, mxREAL));
    iter = mxGetPr(mxGetField(plhs[3],0,fnames[0]));
    pdflag = mxGetPr(mxGetField(plhs[3],0,fnames[1]));   
    dreuse = mxGetPr(mxGetField(plhs[3],0,"reuse"));
    if(nlhs > 4)         
    	plhs[4] = mxCreateCellMatrix(ncones+(int)(nlincon>0)+(int)(nfix>0),1);        
    
    //Set Defaults
    maxtime = 1000;
    printLevel = 0;
    
    //Create DSDP Problem
    DSDP_ERR( DSDPCreate((int)ndec,&dsdp), "Error Creating DSDP Problem");
    //Set Monitor
    DSDP_ERR( DSDPSetMonitor(dsdp,DSDPMonitor,0), "Error Setting DSDP Monitor");
    
    //Set Dual Objective
    for (i=0;i<ndec;i++){
        DSDP_ERR( DSDPSetDualObjective(dsdp,(int)i+1,f[i]), "Error Adding Objective Coefficients"); }
    
    //Check finite bounds for allocation
    if(lb || ub)
        for(i=0;i<ndec;i++) {
            if(lb)
                if(!mxIsInf(lb[i]))
                    nLB++;
            if(ub)
                if(!mxIsInf(ub[i]))
                    nUB++;
        }
    
    //Set Bounds as BCone
    if(nLB || nUB) {
        DSDP_ERR( DSDPCreateBCone(dsdp, &bcone), "Error creating BCone");
        DSDP_ERR( BConeAllocateBounds(bcone, (int)(nLB+nUB)), "Error allocating bounds");        
        for(i=0;i<ndec;i++) {
            if(nLB > 0 && !mxIsInf(lb[i]))
                DSDP_ERR( BConeSetLowerBound(bcone, (int)i+1, lb[i]), "Error setting lower bound");
            if(nUB > 0 && !mxIsInf(ub[i]))
                DSDP_ERR( BConeSetUpperBound(bcone, (int)i+1, ub[i]), "Error setting upper bound");
        }
    }
    
    //Set Linear Inequality Constraints as LPCone
    if(nlincon) {
        int M = (int)mxGetM(pA);
        int N = (int)mxGetN(pA);
        DSDP_ERR( DSDPCreateLPCone(dsdp, &lpcone), "Error creating LPCone (inequalities)");
        //Create Memory to store A*x <= b in dsdp and integer format
        temp_jc = mxCalloc(N+2,sizeof(int));
        temp_ir = mxCalloc(lincon_nz+M,sizeof(int));
        temp_pr = mxCalloc(lincon_nz+M,sizeof(double));
        //Copy over linear A
        for(i=0;i<=(size_t)N;i++)
            temp_jc[i] = (int)A_jc[i];
        for(i=0;i<lincon_nz;i++) {
            temp_ir[i] = (int)A_ir[i];
            temp_pr[i] = A[i];
        }
        //Append linear rhs (b)
        temp_jc[N+1] = temp_jc[N] + M;
        for(i=lincon_nz,j=0;j<(size_t)M;j++) {
            if(b[j] != 0) {
                temp_ir[i] = (int)j;
                temp_pr[i++] = b[j];
            }
            else
                temp_jc[N+1]--;
        }
        #ifdef DEBUG
            mexPrintf("---- Inequality Constraints ----\n");
            for(i=0;i<=(size_t)(N+1);i++)
                mexPrintf("jc[%d] = %d\n",i,temp_jc[i]);
            for(i=0;i<lincon_nz+M;i++)
                mexPrintf("ir[%d] = %d, pr[%d] = %f\n",i,temp_ir[i],i,temp_pr[i]);
        #endif        
        //Set LP Cone Data
        DSDP_ERR( LPConeSetData2(lpcone, M, temp_jc, temp_ir, temp_pr), "Error setting LP Cone data (inequality)" );
        //Optionally set X data
        if(nlhs > 4) {
            mxSetCell(plhs[4],indcell,mxCreateDoubleMatrix(M,1,mxREAL));
            DSDP_ERR( LPConeSetXVec(lpcone,mxGetPr(mxGetCell(plhs[4],indcell++)),M), "Error setting LP Cone X data" );
        }
    }
    
    //Set Semidefinite Constraints as SDPCone
    if(ncones) {
        //Create the cone structure, specifying each constraint as a block
        DSDP_ERR( DSDPCreateSDPCone(dsdp,(int)ncones,&sdpcone), "Error creating SDPCone");
        //Add each constraint cone
        for(i=0;i<ncones;i++) {
            if(ncones == 1 && !mxIsCell(pSDP)) {
                if(nlhs > 4) {
                    mxSetCell(plhs[4],indcell,mxCreateDoubleMatrix(mxGetM(pSDP),1,mxREAL));
                    X = mxGetPr(mxGetCell(plhs[4],indcell++));
                }
                ndim = addSDPCone(sdpcone,pSDP,(int)i,X);
            }
            else {
                if(nlhs > 4) {
                    mxSetCell(plhs[4],indcell,mxCreateDoubleMatrix(mxGetM(mxGetCell(pSDP,i)),1,mxREAL));
                    X = mxGetPr(mxGetCell(plhs[4],indcell++));
                }
                ndim = addSDPCone(sdpcone,mxGetCell(pSDP,i),(int)i,X);
            }
            //Update max dim
            if(sdpnmax < ndim)
                sdpnmax = ndim;
        }
    }
    
    //Set y0
    if (y0)
        for (i=0;i<ndec;i++) {
            DSDP_ERR( DSDPSetY0(dsdp,(int)i+1,y0[i]), "Error setting Y0");            
        }
    
    //Determine whether to reuse schur complement matrix (dsdp authors' heuristic)
    if(ndec == 1)
        reuse = 1/sdpnmax;
    else
        reuse = ((int)ndec-2)/sdpnmax; 
    if (ndec<50 && reuse==0) reuse=1;
    if (reuse>=1) reuse++;
    reuse=reuse*reuse;
    if (ndec<2000 && ndec>10) reuse=10;
    if (ndec>12) reuse=12;    
    
    //Get DSDP Default Options
    DSDP_ERR( DSDPGetR(dsdp,&r0), "Error Getting R");
    DSDP_ERR( DSDPGetPenaltyParameter(dsdp,&penalty), "Error Getting Penalty Parameter");
    DSDP_ERR( DSDPGetPotentialParameter(dsdp,&rho), "Error Getting Potential Parameter");
    DSDP_ERR( DSDPGetDualBound(dsdp,&dbound), "Error Getting Dual Bound");
    DSDP_ERR( DSDPGetGapTolerance(dsdp,&gaptol), "Error Getting Gap Tolerance");
    DSDP_ERR( DSDPGetRTolerance(dsdp,&inftol), "Error Getting R Tolerance");
    DSDP_ERR( DSDPGetBarrierParameter(dsdp,&mu0), "Error Getting Barrier Parameter");
    DSDP_ERR( DSDPGetMaxTrustRadius(dsdp,&maxtrust), "Error Getting Max Trust Radius");
    DSDP_ERR( DSDPGetStepTolerance(dsdp,&steptol), "Error Getting Step Tolerance");
    DSDP_ERR( DSDPGetPTolerance(dsdp,&infptol), "Error Getting P Tolerance");
    DSDP_ERR( DSDPGetPNormTolerance(dsdp,&pnormtol), "Error Getting PNorm Tolerance");
    
    //Get Data Norms to establish y bounds
    DSDP_ERR( DSDPGetDataNorms(dsdp, datanorm), "Error Getting Data Norms");
    DSDP_ERR( DSDPGetYBounds(dsdp,&ylow,&yhigh), "Error Getting Y Bounds");
    if (datanorm[0]==0){DSDP_ERR( DSDPSetYBounds(dsdp,-1.0,1.0), "Error Setting Y Bounds");}
    
    //Get User Options (overwrites defaults above)
    if(nrhs > eOPTS && !mxIsEmpty(pOPTS)) {
        //OPTI Options
        GetIntegerOption(pOPTS,"maxiter",&maxiter);
        GetDoubleOption(pOPTS,"maxtime",&maxtime);
        GetIntegerOption(pOPTS,"display",&printLevel);
        //DSDP Options
        GetDoubleOption(pOPTS,"r0",&r0);
        GetDoubleOption(pOPTS,"penalty",&penalty);
        GetDoubleOption(pOPTS,"rho",&rho);
        GetDoubleOption(pOPTS,"dbound",&dbound);
        GetDoubleOption(pOPTS,"gaptol",&gaptol);
        GetDoubleOption(pOPTS,"rtol",&inftol);
        GetDoubleOption(pOPTS,"mu0",&mu0);
        GetDoubleOption(pOPTS,"maxtrust",&maxtrust);
        GetDoubleOption(pOPTS,"steptol",&steptol);
        GetDoubleOption(pOPTS,"ptol",&infptol);
        GetDoubleOption(pOPTS,"pnormtol",&pnormtol); 
        GetIntegerOption(pOPTS,"reuse",&reuse);
        GetIntegerOption(pOPTS,"rpos",&rpos);
        GetIntegerOption(pOPTS,"drho",&drho);
        //Check and set DSDP options without valid defaults
        if(mxGetField(pOPTS,0,"zbar") && !mxIsEmpty(mxGetField(pOPTS,0,"zbar"))) {
            GetDoubleOption(pOPTS,"zbar",&zbar);
            DSDP_ERR( DSDPSetZBar(dsdp,zbar), "Error Setting Z Bar");
        }
        if(mxGetField(pOPTS,0,"dlbound") && !mxIsEmpty(mxGetField(pOPTS,0,"dlbound"))) {
            GetDoubleOption(pOPTS,"dlbound",&dlbound);
            DSDP_ERR( DSDPSetDualLowerBound(dsdp,dlbound), "Error Setting Dual Lower Bound");
        }
        if(mxGetField(pOPTS,0,"ybound") && !mxIsEmpty(mxGetField(pOPTS,0,"ybound"))) {
            GetDoubleOption(pOPTS,"ybound",&yhigh); ylow = -yhigh;
            DSDP_ERR( DSDPSetYBounds(dsdp,ylow,yhigh), "Error Setting Y Bounds");
        }
    }

    //Set DSDP Options with Defaults
    DSDP_ERR( DSDPSetMaxIts(dsdp,maxiter), "Error Setting Max Iterations");    
    DSDP_ERR( DSDPSetR0(dsdp,r0), "Error Setting Option R0 ");        
    DSDP_ERR( DSDPSetPenaltyParameter(dsdp,penalty), "Error Setting Penalty Parameter");
    DSDP_ERR( DSDPSetPotentialParameter(dsdp,rho), "Error Setting Potential Parameter");
    DSDP_ERR( DSDPSetDualBound(dsdp,dbound), "Error Setting Dual Bound");
    DSDP_ERR( DSDPSetGapTolerance(dsdp,gaptol), "Error Setting Gap Tolerance");
    DSDP_ERR( DSDPSetRTolerance(dsdp,inftol), "Error Setting R Tolerance");
    DSDP_ERR( DSDPSetBarrierParameter(dsdp,mu0), "Error Setting Barrier Parameter");
	DSDP_ERR( DSDPSetMaxTrustRadius(dsdp,maxtrust), "Error Setting Max Trust Radius");
	DSDP_ERR( DSDPSetStepTolerance(dsdp,steptol), "Error Setting Step Tolerance")
    DSDP_ERR( DSDPSetPTolerance(dsdp,infptol), "Error Setting P Tolerance");
    DSDP_ERR( DSDPSetPNormTolerance(dsdp,pnormtol), "Error Setting PNorm Tolerance");   
    if(reuse < 0) reuse = 0; if(reuse > 15) reuse = 15;
    DSDP_ERR( DSDPReuseMatrix(dsdp,reuse), "Error Setting Reuse Matrix");    
    //Set Other DSDP Options
    DSDP_ERR( DSDPUsePenalty(dsdp,rpos), "Error Setting Use Penalty");
    DSDP_ERR( DSDPUseDynamicRho(dsdp,drho), "Error Setting Dynamic Rho");    
    if (lpb<0.1) lpb=0.1;
    if(lpcone) DSDP_ERR( LPConeScaleBarrier(lpcone,lpb), "Error Setting LPCone Scale Barrier");   
    
    //Set Fixed Variables
    if(fixed != NULL) {
        if(nlhs > 4) {            
            mxSetCell(plhs[4],indcell,mxCreateDoubleMatrix(nfix,1,mxREAL));
            X = mxGetPr(mxGetCell(plhs[4],indcell++));
        }
        else
            X = NULL;
        DSDP_ERR( DSDPSetFixedVariables(dsdp, fixed, &fixed[nfix], X, (int)nfix), "Error Setting Fixed Variables");
    }
    
    //Print Header
    if(printLevel) {
        mexPrintf("\n------------------------------------------------------------------\n");
        mexPrintf(" This is DSDP v%s\n",DSDP_VERSION); 
        mexPrintf(" Authors: Steve Benson, Yinyu Ye and Xiong Zhang\n\n");
        mexPrintf(" Problem Properties:\n");
        mexPrintf(" # Decision Variables:        %4d\n",ndec);
        mexPrintf(" # Linear Inequalities:       %4d ",nlincon);
        if(nlincon)
            mexPrintf("[%d nz]\n",lincon_nz);
        else
            mexPrintf("\n");        
        mexPrintf(" # Semidefinite Cones:        %4d\n",ncones);

        mexPrintf("------------------------------------------------------------------\n");
    }
    
    //Start timer
    start = clock();
    //Call DSDP Setup to initialize problem
    DSDP_ERR( DSDPSetup(dsdp), "Error setting up DSDP Problem, likely out of memory");
    //Now Solve the Problem
    status = DSDPSolve(dsdp);
    //Stop Timer
    end = clock();
    evaltime = ((double)(end-start))/CLOCKS_PER_SEC;
    //Determine Stop Reason
    if(status == 0) {
        DSDP_ERR( DSDPStopReason(dsdp,&reason), "Error retrieving post-solve stop reason"); }
    else if(status == DSDP_MAX_TIME || status == DSDP_USER_TERMINATION)
        reason = status;
    else {
        DSDP_ERR( status, "Error solving DSDP Problem!");}
    
    //Computer X and Get Solution Type
    if (reason!=DSDP_INFEASIBLE_START)
        DSDP_ERR( DSDPComputeX(dsdp), "Error computing post-solve x");
    DSDP_ERR( DSDPGetSolutionType(dsdp,&pdfeasible), "Error collecting post-solve solution type");
    
    //Copy Dual Solution
    DSDP_ERR( DSDPGetY(dsdp,x,(int)ndec), "Error returning Solution Vector");
    //Collect Output Statistics
    DSDPGetIts(dsdp,&iters);     
    DSDPGetDObjective(dsdp,dval);    
    DSDPGetPObjective(dsdp,pval);    
    DSDPGetR(dsdp,mxGetPr(mxGetField(plhs[3],0,"r")));
    DSDPGetBarrierParameter(dsdp,mxGetPr(mxGetField(plhs[3],0,"mu")));
    DSDPGetStepLengths(dsdp,mxGetPr(mxGetField(plhs[3],0,"pstep")),mxGetPr(mxGetField(plhs[3],0,"dstep")));
    DSDPGetPnorm(dsdp,mxGetPr(mxGetField(plhs[3],0,"pnorm")));
    DSDPGetYMaxNorm(dsdp,mxGetPr(mxGetField(plhs[3],0,"ynorm")));
    DSDPGetTraceX(dsdp,mxGetPr(mxGetField(plhs[3],0,"tracex")));
    DSDPGetPotentialParameter(dsdp,mxGetPr(mxGetField(plhs[3],0,"rho")));
    *dreuse = (double)reuse;
    
    //Assign to MATLAB
    *iter = (double)iters;    
    *exitflag = (double)reason;
    *pdflag = (double)pdfeasible;
    
    //Print Header
    if(printLevel){            
        //Detail termination reason
        switch(reason)
        {
            //Success
            case DSDP_CONVERGED:	
                mexPrintf("\n *** DSDP CONVERGED ***\n");  break;
            case DSDP_UPPERBOUND:
                mexPrintf("\n *** DSDP CONVERGED: Dual Objective exceeds its bound***\n"); break;
            //Error
            case DSDP_SMALL_STEPS:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: Terminated due to Small Steps ***\n"); break;
            case DSDP_MAX_IT:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: Maximum Iterations Reached ***\n"); break;
            case DSDP_MAX_TIME:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: Maximum Time Reached ***\n"); break;
            case DSDP_INFEASIBLE_START:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: Infeasible Starting Point ***\n"); break;
            case DSDP_USER_TERMINATION:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: User Exited ***\n"); break;            
            //Here is ok too?
            default:
                mexPrintf("\n *** DSDP FINISHED ***\n"); break;
        }
        //Detail solution status
        if(reason == DSDP_CONVERGED || reason == DSDP_UPPERBOUND) {
            switch(pdfeasible)
            {
                //Success
                case DSDP_PDFEASIBLE:
                    mexPrintf(" Solution Status: Both Primal and Dual are Feasible and Bounded\n"); break;             
                //Error
                case DSDP_UNBOUNDED:
                    mexPrintf(" Solution Status: Dual Unbounded, Primal Infeasible\n"); break;
                case DSDP_INFEASIBLE:
                    mexPrintf(" Solution Status: Primal Unbounded, Dual Infeasible\n"); break;
                case DSDP_PDUNKNOWN:
                default:
                    mexPrintf(" Solution Status: Unknown - Check Dual Bounds\n"); break;
            }
        }

        if(reason==DSDP_CONVERGED)
        	mexPrintf("\n Final Primal Objective:  %2.5g\n Final Dual Objective:    %2.5g\n In %5d iterations\n    %5.2f seconds\n",*pval,*dval,iters,evaltime);

        mexPrintf("------------------------------------------------------------------\n\n");
    }  

    //Free DSDP Problem
    DSDP_ERR( DSDPDestroy(dsdp), "Error Destroying DSDP Problem");
    //Free Temporary memory
    if(temp_jc)  {mxFree(temp_jc);  temp_jc  = NULL;}
    if(temp_ir)  {mxFree(temp_ir);  temp_ir  = NULL;}
    if(temp_pr)  {mxFree(temp_pr);  temp_pr  = NULL;}
}               
// Function definitions. 
// -----------------------------------------------------------------
void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 
{
    //Input Args
    user_function_data fun;
    double *x0, *ydata = NULL, *lb = NULL, *ub = NULL, *A = NULL, *b = NULL, *Aeq = NULL, *beq = NULL;
    //Options
    int maxIter = 500;
    double info[LM_INFO_SZ];
    double opts[LM_OPTS_SZ]={J_INIT_MU, J_STOP_THRESH, J_STOP_THRESH, J_STOP_THRESH, LM_DIFF_DELTA};
    
    //Outputs Args
    double *x, *fval, *exitflag, *iter, *feval;
    double *pcovar = NULL;
    
    //Internal Vars
    size_t ndec, ndat;   
    int i, status, havJac = 0, conMode = 0;
    int nineq=0, neq=0;
    double *covar = NULL;
    double *Apr, *bpr;
    double *llb, *lub;
    citer = 1;
    iterF.enabled = false;
    
    if (nrhs < 1) {
        if(nlhs < 1)
            printSolverInfo();
        else
            plhs[0] = mxCreateString(LM_VERSION);   
        return;
    }

    //Check user inputs & get constraint information
    checkInputs(prhs,nrhs,&conMode);

    //Get Sizes
    ndec = mxGetNumberOfElements(prhs[2]);
    ndat = mxGetNumberOfElements(prhs[3]);
    //Get Objective Function Handle
    if (mxIsChar(prhs[0])) {
        CHECK(mxGetString(prhs[0], fun.f, FLEN) == 0,"error reading objective name string");
        fun.nrhs = 1;
        fun.xrhs = 0;
    } else {
        fun.prhs[0] = (mxArray*)prhs[0];
        strcpy(fun.f, "feval");
        fun.nrhs = 2;
        fun.xrhs = 1;
    }
    fun.prhs[fun.xrhs] = mxCreateDoubleMatrix(ndec, 1, mxREAL); //x0
    fun.print = 0;
    //Check and Get Gradient Function Handle
    if(!mxIsEmpty(prhs[1])) {  
        havJac = 1;
        if (mxIsChar(prhs[1])) {
            CHECK(mxGetString(prhs[1], fun.g, FLEN) == 0,"error reading gradient name string");
            fun.nrhs_g = 1;
            fun.xrhs_g = 0;
        } else {
            fun.prhs_g[0] = (mxArray*)prhs[1];
            strcpy(fun.g, "feval");
            fun.nrhs_g = 2;
            fun.xrhs_g = 1;
        }   
        fun.prhs_g[fun.xrhs_g] = mxCreateDoubleMatrix(ndec, 1, mxREAL); //x0
    }

    //Get x0 + data
    x0 = mxGetPr(prhs[2]);
    ydata = mxGetPr(prhs[3]);
    fun.ydata = ydata;
    
    //Get Bounds
    if(conMode & 1) {
        //LB
        if(!mxIsEmpty(prhs[4])){
            llb = mxGetPr(prhs[4]);
            lb = mxCalloc(ndec,sizeof(double));
            memcpy(lb,llb,ndec*sizeof(double));
            for(i=0;i<ndec;i++) {
                if(mxIsInf(lb[i]))
                    lb[i] = -DBL_MAX;
            }
        }
        else {
            lb = mxCalloc(ndec,sizeof(double));
            for(i=0;i<ndec;i++)
                lb[i] = -DBL_MAX;
        }
        //UB
        if(nrhs > 5 && !mxIsEmpty(prhs[5])){
            lub = mxGetPr(prhs[5]);
            ub = mxCalloc(ndec,sizeof(double));
            memcpy(ub,lub,ndec*sizeof(double));
            for(i=0;i<ndec;i++) {
                if(mxIsInf(ub[i]))
                    ub[i] = DBL_MAX;
            }
        }
        else {
            ub = mxCalloc(ndec,sizeof(double));
            for(i=0;i<ndec;i++)
                ub[i] = DBL_MAX;
        }
    }
    //Get Linear Inequality Constraints
    if(conMode & 2) {
        nineq = (int)mxGetM(prhs[7]);
        Apr = mxGetPr(prhs[6]);
        bpr = mxGetPr(prhs[7]);
        //Need to flip >= to <=
        A = mxCalloc(ndec*nineq,sizeof(double));
        b = mxCalloc(nineq,sizeof(double));
        for(i=0;i<ndec*nineq;i++)
            A[i] = -Apr[i];
        for(i=0;i<nineq;i++)
            b[i] = -bpr[i];
    }
    //Get Linear Equality Constraints
    if(conMode & 4) {
        Aeq = mxGetPr(prhs[8]);
        beq = mxGetPr(prhs[9]);
        neq = (int)mxGetM(prhs[9]);
    }
    
    //Get Options if specified
    if(nrhs > 10) {
        if(mxGetField(prhs[10],0,"maxiter"))
            maxIter = (int)*mxGetPr(mxGetField(prhs[10],0,"maxiter"));
        if(mxGetField(prhs[10],0,"display"))
            fun.print = (int)*mxGetPr(mxGetField(prhs[10],0,"display"));
        if(mxGetField(prhs[10],0,"iterfun") && !mxIsEmpty(mxGetField(prhs[10],0,"iterfun")))
        {
            iterF.prhs[0] = (mxArray*)mxGetField(prhs[10],0,"iterfun");
            strcpy(iterF.f, "feval");
            iterF.enabled = true;  
            iterF.prhs[1] = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL);
            iterF.prhs[2] = mxCreateDoubleMatrix(1,1,mxREAL);
            iterF.prhs[3] = mxCreateDoubleMatrix(ndec,1,mxREAL);
        }
    }                       

    //Create Outputs
    plhs[0] = mxCreateDoubleMatrix(ndec,1, mxREAL);
    plhs[1] = mxCreateDoubleMatrix(1,1, mxREAL);
    plhs[2] = mxCreateDoubleMatrix(1,1, mxREAL);
    plhs[3] = mxCreateDoubleMatrix(1,1, mxREAL);
    plhs[4] = mxCreateDoubleMatrix(1,1, mxREAL);
    x = mxGetPr(plhs[0]); 
    fval = mxGetPr(plhs[1]); 
    exitflag = mxGetPr(plhs[2]);    
    iter = mxGetPr(plhs[3]);
    feval = mxGetPr(plhs[4]);
    
    //Copy initial guess to x
    memcpy(x,x0,ndec*sizeof(double));
    //Create Covariance Matrix if Required
    if(nlhs>4)
        covar=mxCalloc(ndec*ndec,sizeof(double));
    
    //Print Header
    if(fun.print) {
        mexPrintf("\n------------------------------------------------------------------\n");
        
        mexPrintf(" This is LEVMAR v2.5\n");
            
        mexPrintf(" Author: Manolis Lourakis\n MEX Interface J. Currie 2011\n\n");
        mexPrintf(" Problem Properties:\n");
        mexPrintf(" # Decision Variables:     %4d\n",ndec);
        mexPrintf(" # Data Points:            %4d\n",ndat);

        mexPrintf("------------------------------------------------------------------\n");
    }
  
    //Solve based on constraints
    switch(conMode)
    {
        case MIN_UNCONSTRAINED:
            //mexPrintf("Unc Problem\n");
            if(havJac)
                status = dlevmar_der(func, jac, x, ydata, (int)ndec, (int)ndat, maxIter, opts, info, NULL, covar, &fun);
            else
                status = dlevmar_dif(func, x, ydata, (int)ndec, (int)ndat, maxIter, opts, info, NULL, covar, &fun);            
            break;
        case MIN_CONSTRAINED_BC:
            //mexPrintf("Box Constrained Problem\n");
            if(havJac)
                status = dlevmar_bc_der(func, jac, x, ydata, (int)ndec, (int)ndat, lb, ub, NULL, maxIter, opts, info, NULL, covar, &fun);
            else
                status = dlevmar_bc_dif(func, x, ydata, (int)ndec, (int)ndat, lb, ub, NULL, maxIter, opts, info, NULL, covar, &fun);
            break;
        case MIN_CONSTRAINED_LIC:
            //mexPrintf("Linear Inequality Problem\n");
            if(havJac)
                status = dlevmar_lic_der(func, jac, x, ydata, (int)ndec, (int)ndat, A, b, nineq, maxIter, opts, info, NULL, covar, &fun);
            else
                status = dlevmar_lic_dif(func, x, ydata, (int)ndec, (int)ndat, A, b, nineq, maxIter, opts, info, NULL, covar, &fun);
            break;
        case MIN_CONSTRAINED_BLIC:
            //mexPrintf("Boxed Linear Inequality Problem\n");
            if(havJac)
                status = dlevmar_blic_der(func, jac, x, ydata, (int)ndec, (int)ndat, lb, ub, A, b, nineq, maxIter, opts, info, NULL, covar, &fun);
            else
                status = dlevmar_blic_dif(func, x, ydata, (int)ndec, (int)ndat, lb, ub, A, b, nineq, maxIter, opts, info, NULL, covar, &fun);
            break;
        case MIN_CONSTRAINED_LEC:
            //mexPrintf("Linear Equality Problem\n");
            if(havJac)
                status = dlevmar_lec_der(func, jac, x, ydata, (int)ndec, (int)ndat, Aeq, beq, neq, maxIter, opts, info, NULL, covar, &fun);
            else
                status = dlevmar_lec_dif(func, x, ydata, (int)ndec, (int)ndat, Aeq, beq, neq, maxIter, opts, info, NULL, covar, &fun);
            break;
        case MIN_CONSTRAINED_BLEC:
            //mexPrintf("Boxed Linear Equality Problem\n");
            if(havJac)
                status = dlevmar_blec_der(func, jac, x, ydata, (int)ndec, (int)ndat, lb, ub, Aeq, beq, neq, NULL, maxIter, opts, info, NULL, covar, &fun);
            else
                status = dlevmar_blec_dif(func, x, ydata, (int)ndec, (int)ndat, lb, ub, Aeq, beq, neq, NULL, maxIter, opts, info, NULL, covar, &fun);
            break;
        case MIN_CONSTRAINED_LEIC:
            //mexPrintf("Linear Inequality + Equality Problem\n");
            if(havJac)
                status = dlevmar_leic_der(func, jac, x, ydata, (int)ndec, (int)ndat, Aeq, beq, neq, A, b, nineq, maxIter, opts, info, NULL, covar, &fun);
            else
                status = dlevmar_leic_dif(func, x, ydata, (int)ndec, (int)ndat, Aeq, beq, neq, A, b, nineq, maxIter, opts, info, NULL, covar, &fun);
            break;
        case MIN_CONSTRAINED_BLEIC:
            //mexPrintf("Boxed Linear Inequality + Equality Problem\n");
            if(havJac)
                status = dlevmar_bleic_der(func, jac, x, ydata, (int)ndec, (int)ndat, lb, ub, Aeq, beq, neq, A, b, nineq, maxIter, opts, info, NULL, covar, &fun);
            else
                status = dlevmar_bleic_dif(func, x, ydata, (int)ndec, (int)ndat, lb, ub, Aeq, beq, neq, A, b, nineq, maxIter, opts, info, NULL, covar, &fun);
            break;
        default:
            mexErrMsgTxt("Unknown constraint configuration");
    }
       
    //Save Status & Iterations
    *fval = info[1];
    *exitflag = getStatus(info[6]);
    *iter = (double)status;
    *feval = (double)citer;
    
    //Save Covariance if Required
    if(nlhs > 5) {
        plhs[5] = mxCreateDoubleMatrix(ndec, ndec, mxREAL);
        pcovar = mxGetPr(plhs[5]);
        memcpy(pcovar,covar,ndec*ndec*sizeof(double));
    }
    
    //Print Header
    if(fun.print){            
        //Termination Detected
        if(*exitflag == 1)
            mexPrintf("\n *** SUCCESSFUL TERMINATION ***\n");
        else if(*exitflag == 0)
            mexPrintf("\n *** MAXIMUM ITERATIONS REACHED ***\n");
        else if(*exitflag == -1)
            mexPrintf("\n *** TERMINATION: TOLERANCE TOO SMALL ***\n");
        else if(*exitflag == -2)
            mexPrintf("\n *** TERMINATION: ROUTINE ERROR ***\n");     

        if(*exitflag==1)
            mexPrintf(" Final SSE: %12.5g\n In %3.0f iterations\n",*fval,*iter);

        mexPrintf("------------------------------------------------------------------\n\n");
    }
    
    //Clean Up
    if(lb) mxFree(lb);
    if(ub) mxFree(ub);
    if(covar) mxFree(covar);
    if(A) mxFree(A);
    if(b) mxFree(b);
}
Beispiel #4
0
// Function definitions. 
// -----------------------------------------------------------------
void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 
{
    //Input Args         
    double *x0 = NULL, *lb = NULL, *ub = NULL, *A = NULL, *b = NULL;  
    
    //Outputs Args
    double *x, *fval, *exitflag, *iter, *feval;
    
    //Internal Vars
    double *llb, *lub;
    size_t ndec;   
    int i, exit_code;    
    
    //PSwarm Vars
    double *sol = NULL;
    int lincon = 0;

    if (nrhs < 1) {
        if(nlhs < 1)
            printSolverInfo();
        else
            plhs[0] = mxCreateString(PSWARM_VERSION);
        return;
    }
    
    //Check user inputs
    checkInputs(prhs,nrhs,&lincon);
    
    //Set Defaults    
    printLevel = 0;
    maxtime = 1000;
    noFeval = 0;
    ctrlCExit = false;
    iterF.enabled = false;
    //Reset Stats
    stats.solveriters = 0;
    stats.objfunctions = 0;
    stats.pollsteps = 0;
    stats.sucpollsteps = 0;
    //Set PSwarm Defaults
    opt.s = 42;
    opt.mu = 0.5; opt.nu = 0.5;
    opt.maxvfactor = 0.5; opt.maxiter = 1500;
    opt.maxf = 10000;       
    opt.iweight = 0.9; opt.fweight = 0.4;
    opt.n2grd = 0.5;
    opt.blim = 10;
    opt.tol = 1e-5;
    opt.delta = Inf; opt.fdelta = 5.0; opt.idelta = 2.0; opt.ddelta = 0.5;
    opt.pollbasis = 0; opt.EpsilonActive = 0.1;
    opt.IPrint = 10;    
    opt.vectorized = 0;     //important, otherwise will pass whole swarm
    opt.outfcn = &iterfcn;  //iteration + ctrl c

    //Get Sizes
    ndec = mxGetNumberOfElements(prhs[1]);
    //Get Objective Function Handle
    if (mxIsChar(prhs[0])) {
        CHECK(mxGetString(prhs[0], fun.f, FLEN) == 0,"error reading objective name string");
        fun.nrhs = 1;
        fun.xrhs = 0;
    } else {
        fun.prhs[0] = (mxArray*)prhs[0];
        strcpy(fun.f, "feval");
        fun.nrhs = 2;
        fun.xrhs = 1;
    }    

    //Get x0
    x0 = mxGetPr(prhs[1]);   
    
    //Get Bounds
    //LB
    if(!mxIsEmpty(prhs[2])){
        llb = mxGetPr(prhs[2]);
        lb = mxCalloc(ndec,sizeof(double));
        memcpy(lb,llb,ndec*sizeof(double));
        for(i=0;i<ndec;i++) {
            if(mxIsInf(lb[i]))
                lb[i] = -1e19;
        }
    }
    else {
        lb = mxCalloc(ndec,sizeof(double));
        for(i=0;i<ndec;i++)
            lb[i] = -1e19;
    }
    //UB
    if(nrhs > 3 && !mxIsEmpty(prhs[3])){
        lub = mxGetPr(prhs[3]);
        ub = mxCalloc(ndec,sizeof(double));
        memcpy(ub,lub,ndec*sizeof(double));
        for(i=0;i<ndec;i++) {
            if(mxIsInf(ub[i]))
                ub[i] = 1e19;
        }
    }
    else {
        ub = mxCalloc(ndec,sizeof(double));
        for(i=0;i<ndec;i++)
            ub[i] = 1e19;
    }
    
    //Get Linear Inequality Constraints
    if(nrhs > 4) {
        if(!mxIsEmpty(prhs[4]) && !mxIsEmpty(prhs[5])) {
            A = mxGetPr(prhs[4]);
            b = mxGetPr(prhs[5]);
        }
    }
    
    //Get Options if specified
    if(nrhs > 6) {
        if(mxGetField(prhs[6],0,"display"))
            printLevel = (int)*mxGetPr(mxGetField(prhs[6],0,"display"));
        if(mxGetField(prhs[6],0,"maxiter"))
            opt.maxiter = (int)*mxGetPr(mxGetField(prhs[6],0,"maxiter"));
        if(mxGetField(prhs[6],0,"maxtime"))
            maxtime = *mxGetPr(mxGetField(prhs[6],0,"maxtime"));
        if(mxGetField(prhs[6],0,"tolfun"))
            opt.tol = *mxGetPr(mxGetField(prhs[6],0,"tolfun"));
        if(mxGetField(prhs[6],0,"maxfeval"))
            opt.maxf = (int)*mxGetPr(mxGetField(prhs[6],0,"maxfeval"));
        if(mxGetField(prhs[6],0,"swarm_size"))
            opt.s = (int)*mxGetPr(mxGetField(prhs[6],0,"swarm_size"));
        if(mxGetField(prhs[6],0,"vectorized"))
            opt.vectorized = (int)*mxGetPr(mxGetField(prhs[6],0,"vectorized"));
        if(mxGetField(prhs[6],0,"mu"))
            opt.mu = *mxGetPr(mxGetField(prhs[6],0,"mu"));
        if(mxGetField(prhs[6],0,"nu"))
            opt.nu = *mxGetPr(mxGetField(prhs[6],0,"nu"));
        if(mxGetField(prhs[6],0,"iweight"))
            opt.iweight = *mxGetPr(mxGetField(prhs[6],0,"iweight"));
        if(mxGetField(prhs[6],0,"fweight"))
            opt.fweight = *mxGetPr(mxGetField(prhs[6],0,"fweight"));
        if(mxGetField(prhs[6],0,"delta"))
            opt.delta = *mxGetPr(mxGetField(prhs[6],0,"delta"));
        if(mxGetField(prhs[6],0,"idelta"))
            opt.idelta = *mxGetPr(mxGetField(prhs[6],0,"idelta"));
        if(mxGetField(prhs[6],0,"ddelta"))
            opt.ddelta = *mxGetPr(mxGetField(prhs[6],0,"ddelta"));
        if(mxGetField(prhs[6],0,"iterfun") && !mxIsEmpty(mxGetField(prhs[6],0,"iterfun")))
        {
            iterF.prhs[0] = (mxArray*)mxGetField(prhs[6],0,"iterfun");
            strcpy(iterF.f, "feval");
            iterF.enabled = true;  
            iterF.prhs[1] = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL);
            iterF.prhs[2] = mxCreateDoubleMatrix(1,1,mxREAL);
            iterF.prhs[3] = mxCreateDoubleMatrix(ndec,1,mxREAL);
        }
    }       
    
    //If not vectorized, we can create x now, otherwise must be done in callback
    if(!opt.vectorized)
        fun.prhs[fun.xrhs] = mxCreateDoubleMatrix(ndec, 1, mxREAL);
    
    //Create Outputs
    plhs[0] = mxCreateDoubleMatrix(ndec,1, mxREAL);
    plhs[1] = mxCreateDoubleMatrix(1,1, mxREAL);
    plhs[2] = mxCreateDoubleMatrix(1,1, mxREAL);
    plhs[3] = mxCreateDoubleMatrix(1,1, mxREAL);
    plhs[4] = mxCreateDoubleMatrix(1,1, mxREAL);
    x = mxGetPr(plhs[0]); 
    fval = mxGetPr(plhs[1]); 
    exitflag = mxGetPr(plhs[2]);    
    iter = mxGetPr(plhs[3]);
    feval = mxGetPr(plhs[4]);

    //Print Header
    if(printLevel) {
        mexPrintf("\n------------------------------------------------------------------\n");
        mexPrintf(" This is PSwarm v1.5\n");
            
        mexPrintf(" Authors: A.I.F Vaz and L.N. Vicente\n\n");
        mexPrintf(" Problem Properties:\n");
        mexPrintf(" # Decision Variables:     %4d\n",ndec);
        mexPrintf(" # Linear Constraints:     %4d\n",lincon);

        mexPrintf("------------------------------------------------------------------\n");
    }
    
    //Run PSwarm
    start = clock();
    exit_code = PSwarm((int)ndec, &func, lb, ub, lincon, A, b, &sol, fval, x0);
    
    if(exit_code == 0) {
        //Copy Solution
        memcpy(x,sol,ndec*sizeof(double));
        free(sol);
        *iter = (double)stats.solveriters;
        *feval = (double)stats.objfunctions;
    }

    //Save Status & Iterations
    *exitflag = getStatus(exit_code,stats.solveriters,stats.objfunctions); 
    
    //Print Header
    if(printLevel){            
        //Termination Detected
        switch((int)*exitflag)
        {
            //Success
            case 1:
                mexPrintf("\n *** SUCCESSFUL TERMINATION ***\n *** Normal Exit ***\n"); break;
            //Error
            case -1:
                mexPrintf("\n *** ERROR: Abnormal Exit ***\n"); break;
            case 0:
                if(stats.solveriters >= (opt.maxiter-5))
                    mexPrintf("\n *** MAXIMUM ITERATIONS REACHED ***\n"); 
                else if(((double)(end-start))/CLOCKS_PER_SEC > maxtime)
                    mexPrintf("\n *** MAXIMUM TIME EXCEEDED ***\n");
                else
                    mexPrintf("\n *** MAXIMUM FUNCTION EVALUATIONS REACHED ***\n"); 
                
                break;
            //Early Exit
            case -2:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: Failed to allocate memory ***\n"); break;
            case -3:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: Unable to initialize population - check constraints are feasible ***\n"); break;
            case -5:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: User Exit (Ctrl C) ***\n"); break;
        }

        if(*exitflag==1)
            mexPrintf("\n Final Objective: %12.5g\n In %3d iterations and\n   %4d function evaluations\n",*fval,stats.solveriters,stats.objfunctions);

        mexPrintf("------------------------------------------------------------------\n\n");
    }
    
    //Free Memory
    if(lb) mxFree(lb);
    if(ub) mxFree(ub);    
}
Beispiel #5
0
// Function definitions. 
// -----------------------------------------------------------------
void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 
{
    //Input Args
    double *x0;          

    //Outputs Args
    double *x, *fval, *exitflag, *iter, *feval;
    
    //Internal Vars
    size_t ndec;  
    int printLevel = 0;
    
    //M1QN3 Vars
    int m = 5, n, indic, ndz;
    int uiparm[2] = {1,0};  //user integer array [citer, printLevel]
    double *g, dxmin = 1e-8, df1, epsg = 1e-6, *dz;
    char *normtype = "dfn";
    int impres = 0, io = 0, omode = 0, reverse = 0;
    int imode[3] = {0,0,0}; //DIS, cold start, no SIMUL with indic = 1
    int iz[5];
    float *rzs = NULL; double *dzs = NULL; //dummy args
    //Defaults
    int maxfev = 1500;
    int maxiter = 1000;
    maxtime = 1000;
    iterF.enabled = false;

    if (nrhs < 1) {
        if(nlhs < 1)
            printSolverInfo();
        else
            plhs[0] = mxCreateString(M1QN3_VERSION);
            
        return;
    }

    //Check user inputs
    checkInputs(prhs,nrhs);

    //Get Sizes
    ndec = mxGetNumberOfElements(pX0);
    //Get Objective Function Handle
    if (mxIsChar(pFUN)) {
        CHECK(mxGetString(pFUN, fun.f, FLEN) == 0,"error reading objective name string");
        fun.nrhs = 1;
        fun.xrhs = 0;
    } else {
        fun.prhs[0] = (mxArray*)pFUN;
        strcpy(fun.f, "feval");
        fun.nrhs = 2;
        fun.xrhs = 1;
    }
    fun.prhs[fun.xrhs] = mxCreateDoubleMatrix(ndec, 1, mxREAL); //x0
    //Get Gradient Function Handle 
    if (mxIsChar(pGRAD)) {
        CHECK(mxGetString(pGRAD, fun.g, FLEN) == 0,"error reading gradient name string");
        fun.nrhs_g = 1;
        fun.xrhs_g = 0;
    } else {
        fun.prhs_g[0] = (mxArray*)pGRAD;
        strcpy(fun.g, "feval");
        fun.nrhs_g = 2;
        fun.xrhs_g = 1;
    }   
    fun.prhs_g[fun.xrhs_g] = mxCreateDoubleMatrix(ndec, 1, mxREAL); //x0   

    //Get x0
    x0 = mxGetPr(pX0);
    
    //Get Options if specified
    if(nrhs > eOPTS) {
        if(mxGetField(pOPTS,0,"display"))
            printLevel = (int)*mxGetPr(mxGetField(pOPTS,0,"display"));
        if(mxGetField(pOPTS,0,"maxfeval"))
            maxfev = (int)*mxGetPr(mxGetField(pOPTS,0,"maxfeval"));
        if(mxGetField(pOPTS,0,"maxiter"))
            maxiter = (int)*mxGetPr(mxGetField(pOPTS,0,"maxiter"));
        if(mxGetField(pOPTS,0,"maxtime"))
            maxtime = *mxGetPr(mxGetField(pOPTS,0,"maxtime"));
        if(mxGetField(pOPTS,0,"tolafun"))
            epsg = *mxGetPr(mxGetField(pOPTS,0,"tolafun")); //not function tolerance (gradient)
        if(mxGetField(pOPTS,0,"nupdates"))
            m = (int)*mxGetPr(mxGetField(pOPTS,0,"nupdates")); //number of l-bfgs updates
        if(mxGetField(pOPTS,0,"iterfun") && !mxIsEmpty(mxGetField(pOPTS,0,"iterfun")))
        {
            iterF.prhs[0] = (mxArray*)mxGetField(pOPTS,0,"iterfun");
            strcpy(iterF.f, "feval");
            iterF.enabled = true;  
            iterF.prhs[1] = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL);
            iterF.prhs[2] = mxCreateDoubleMatrix(1,1,mxREAL);
            iterF.prhs[3] = mxCreateDoubleMatrix(ndec,1,mxREAL);
        }
    }       
    
    //Create Outputs
    plhs[0] = mxCreateDoubleMatrix(ndec,1, mxREAL);
    plhs[1] = mxCreateDoubleMatrix(1,1, mxREAL);
    plhs[2] = mxCreateDoubleMatrix(1,1, mxREAL);
    plhs[3] = mxCreateDoubleMatrix(1,1, mxREAL);
    plhs[4] = mxCreateDoubleMatrix(1,1, mxREAL);
    x = mxGetPr(plhs[0]); 
    fval = mxGetPr(plhs[1]); 
    exitflag = mxGetPr(plhs[2]);    
    iter = mxGetPr(plhs[3]);
    feval = mxGetPr(plhs[4]);
    
    //Copy initial guess to x
    memcpy(x,x0,ndec*sizeof(double));
    
    //Print Header
    if(printLevel) {
        mexPrintf("\n------------------------------------------------------------------\n");
        mexPrintf(" This is M1QN3 v%s\n",M1QN3_VERSION);  
        mexPrintf(" Authors: Jean Charles Gilbert, Claude Lemarechal, INRIA\n MEX Interface J. Currie 2012\n\n");
        mexPrintf(" Problem Properties:\n");
        mexPrintf(" # Decision Variables:     %4d\n",ndec);

        mexPrintf("------------------------------------------------------------------\n");
    }
    
    //Assign Arguments
    n = (int)ndec;
    indic = 4;
    g = (double*)mxCalloc(n,sizeof(double)); //allocate memory for gradient
    ndz = 4*n + m*(2*n + 1);
    dz = (double*)mxCalloc(ndz,sizeof(double));
    
    //Start timer
    start = clock();
    
    //Initialization Call
    SIMUL(&indic, &n, x, fval, g, uiparm, NULL, NULL);    
    //Set df1 (initial estiamte of f reduction)
    df1 = *fval;
    
    //MEX Options
    uiparm[0] = 1;
    uiparm[1] = printLevel;
    
    //Call Algorithm
    M1QN3(SIMUL,EUCLID,CTONBE,CTCABE,&n,x,fval,g,&dxmin,&df1,&epsg,normtype,
          &impres,&io,imode,&omode,&maxiter,&maxfev,iz,dz,&ndz,&reverse,&indic,
          uiparm,rzs,dzs);

    //Save Status & Iterations
    *exitflag = (double)omode;
    *iter = maxiter;
    *feval = maxfev;
    
    //Check if maxtime exceeded
    if(((double)(end-start))/CLOCKS_PER_SEC > maxtime)
        *exitflag = 8;
    
    //Print Header
    if(printLevel){            
        //Termination Detected
        switch((int)*exitflag)
        {
            //Success
            case 1:
                mexPrintf("\n *** SUCCESSFUL TERMINATION ***\n *** gradient convergence |gk|/|g1| < epsg ***\n"); break;
            //Error
            case 5:
                mexPrintf("\n *** MAXIMUM FUNCTION EVALUATIONS REACHED ***\n"); break;
            case 4:
                mexPrintf("\n *** MAXIMUM ITERATIONS REACHED ***\n"); break;                       
            case 8:
                mexPrintf("\n *** MAXIMUM TIME REACHED ***\n"); break;  
            case 2:
                mexPrintf("\n *** ERROR: one of the input arguments is not well initialized ***\n"); break;
            case 3:
                mexPrintf("\n *** ERROR: the line-search is blocked on tmax = 10^20 ***\n"); break;    
            case 6:
                mexPrintf("\n *** ERROR: stop dxmin during the line-search ***\n"); break;       
            case 7:
                mexPrintf("\n *** ERROR: either (g,d) is nonnegative or (y,s) is nonpositive ***\n"); break;
            //Early Exit
            case 0:
                mexPrintf("\n *** TERMINATION: USER EXITED ***\n"); break;
            //Other Error
            default:
                mexPrintf("\n *** ERROR: internal error code %d ***\n",omode); break;
        }
        
        if(*exitflag==1)
            mexPrintf("\n Final fval: %12.5g\n In %3.0f iterations\n",*fval,*iter);

        mexPrintf("------------------------------------------------------------------\n\n");
    }
    
    //Free Memory
    mxFree(g);
    mxFree(dz);
}
Beispiel #6
0
// Function definitions. 
// -----------------------------------------------------------------
void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 
{
    //Outputs Args
    double *x, *fval, *exitflag, *iter;
    
    //Internal Vars
    double *mptr;
    size_t ndec, ndat;   
    int i, havJac = 0;
    
    //LMDIF + LMDER Vars
    int m;                  //len data
    int n;                  //len x
    double *x0;             //initial guess + sol
    double *fvec;           //final fvec
    double ftol = 1e-7;     //function tolerance
    double xtol = 1e-7;     //iterate tolerance
    double gtol = 1e-7;     //gradient tolerance
    int maxfev = 1500;      //max fevals
    double epsfcn = mxGetEps(); //FD max error
    double *diag;           //scaling (ignored in mode 1)   
    int mode = 1;           //internal scaling
    double factor = 100;    //used for initial step bound
    int nprint = -1;        //no printing
    int info = 0;           //output status
    int nfev = 0;           //number of fevals
    int njev = 0;           //number of jevals
    double *fjac;           //final jacobian
    int ldfjac;             //ld of jac
    int *ipvt;              //permutation
    double *qtf;            //qt * fvec    
    double *wa1, *wa2, *wa3, *wa4;  //work vectors

    if (nrhs < 1) {
        if(nlhs < 1)
            printSolverInfo();
        else
            plhs[0] = mxCreateString("");  //no version info? 
        return;
    }

    //Check user inputs
    checkInputs(prhs,nrhs);
    
    //Set Defaults
    citer = 1;
    printLevel = 0;
    iterF.enabled = false;
    maxtime = 1000;

    //Get Sizes
    ndec = mxGetNumberOfElements(prhs[2]);
    ndat = mxGetNumberOfElements(prhs[3]);
    //Get Objective Function Handle
    if (mxIsChar(prhs[0])) {
        CHECK(mxGetString(prhs[0], fun.f, FLEN) == 0,"error reading objective name string");
        fun.nrhs = 1;
        fun.xrhs = 0;
    } else {
        fun.prhs[0] = (mxArray*)prhs[0];
        strcpy(fun.f, "feval");
        fun.nrhs = 2;
        fun.xrhs = 1;
    }
    fun.prhs[fun.xrhs] = mxCreateDoubleMatrix(ndec, 1, mxREAL); //x0
    //Check and Get Gradient Function Handle
    if(!mxIsEmpty(prhs[1])) {  
        havJac = 1;
        if (mxIsChar(prhs[1])) {
            CHECK(mxGetString(prhs[1], grad.f, FLEN) == 0,"error reading gradient name string");
            grad.nrhs = 1;
            grad.xrhs = 0;
        } else {
            grad.prhs[0] = (mxArray*)prhs[1];
            strcpy(grad.f, "feval");
            grad.nrhs = 2;
            grad.xrhs = 1;
        }   
        grad.prhs[grad.xrhs] = mxCreateDoubleMatrix(ndec, 1, mxREAL); //x0
    }

    //Get x0 + data
    x0 = mxGetPr(prhs[2]);
    ydata = mxGetPr(prhs[3]);        
    
    //Get Options if specified
    if(nrhs > 4) {
        if(mxGetField(prhs[4],0,"display"))
            printLevel = (int)*mxGetPr(mxGetField(prhs[4],0,"display"));
        if(mxGetField(prhs[4],0,"maxfeval"))
            maxfev = (int)*mxGetPr(mxGetField(prhs[4],0,"maxfeval"));
        if(mxGetField(prhs[4],0,"maxtime"))
            maxtime = *mxGetPr(mxGetField(prhs[4],0,"maxtime"));
        if(mxGetField(prhs[4],0,"tolrfun"))
            ftol = *mxGetPr(mxGetField(prhs[4],0,"tolrfun"));
        if(mxGetField(prhs[4],0,"iterfun") && !mxIsEmpty(mxGetField(prhs[4],0,"iterfun")))
        {
            iterF.prhs[0] = (mxArray*)mxGetField(prhs[4],0,"iterfun");
            strcpy(iterF.f, "feval");
            iterF.enabled = true;  
            iterF.prhs[1] = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL);
            iterF.prhs[2] = mxCreateDoubleMatrix(1,1,mxREAL);
            iterF.prhs[3] = mxCreateDoubleMatrix(ndec,1,mxREAL);
        }
    }       
    
    //Create Outputs
    plhs[0] = mxCreateDoubleMatrix(ndec,1, mxREAL);
    plhs[1] = mxCreateDoubleMatrix(1,1, mxREAL);
    plhs[2] = mxCreateDoubleMatrix(1,1, mxREAL);
    plhs[3] = mxCreateDoubleMatrix(1,1, mxREAL);
    x = mxGetPr(plhs[0]); 
    fval = mxGetPr(plhs[1]); 
    exitflag = mxGetPr(plhs[2]);    
    iter = mxGetPr(plhs[3]);
    
    //Copy initial guess to x
    memcpy(x,x0,ndec*sizeof(double));
    
    //Print Header
    if(printLevel) {
        mexPrintf("\n------------------------------------------------------------------\n");
        if(havJac)
            mexPrintf(" This is LM_DER\n");
        else
            mexPrintf(" This is LM_DIF\n");
            
        mexPrintf(" Authors: Burton S. Garbow, Kenneth E. Hillstrom, Jorge J. More\n MEX Interface J. Currie 2011\n\n");
        mexPrintf(" Problem Properties:\n");
        mexPrintf(" # Decision Variables:     %4d\n",ndec);
        mexPrintf(" # Data Points:            %4d\n",ndat);

        mexPrintf("------------------------------------------------------------------\n");
    }
    
    //Assign Arguments
    m = (int)ndat; ldfjac = m;
    n = (int)ndec;
    diag = mxCalloc(ndec,sizeof(double));
    fvec = mxCalloc(ndat,sizeof(double));
    fjac = mxCalloc(ndec*ndat,sizeof(double));
    ipvt = mxCalloc(ndec,sizeof(int));
    qtf = mxCalloc(ndec,sizeof(double));   
    //Get Work Memory
    mptr = mxCalloc(3*ndec+ndat,sizeof(double)); i = 0;
    wa1 = &mptr[i]; i += (int)ndec;
    wa2 = &mptr[i]; i += (int)ndec;
    wa3 = &mptr[i]; i += (int)ndec;
    wa4 = &mptr[i];
    
    //Start Timer
    start = clock();
    
    //Call Algorithm based on Derivatives
    if(havJac)
        LMDER(jacfunc,&m,&n,x,fvec,fjac,&ldfjac,&ftol,&xtol,&gtol,&maxfev,diag,&mode,&factor,&nprint,&info,&nfev,&njev,ipvt,qtf,wa1,wa2,wa3,wa4);
    else
        LMDIF(func,&m,&n,x,fvec,&ftol,&xtol,&gtol,&maxfev,&epsfcn,diag,&mode,&factor,&nprint,&info,&nfev,fjac,&ldfjac,ipvt,qtf,wa1,wa2,wa3,wa4);
    
    //Calculate final Rnorm
    *fval = 0;
    for(i=0;i<m;i++)
        *fval += fvec[i]*fvec[i];
    
    //Check if maxtime exceeded
    if(((double)(end-start))/CLOCKS_PER_SEC > maxtime)
        info = 15;
    
    //Save Status & Iterations
    *exitflag = getStatus(info);
    *iter = (double)nfev;
    
    //Print Header
    if(printLevel){            
        //Termination Detected
        switch((int)info)
        {
            //Success
            case 1:
                mexPrintf("\n *** SUCCESSFUL TERMINATION ***\n *** Both actual and predicted relative reductions in the sum of squares are at most ftol ***\n"); break;
            case 2:
                mexPrintf("\n *** SUCCESSFUL TERMINATION ***\n *** Relative error between two consecutive iterates is at most xtol ***\n"); break;
            case 3:
                mexPrintf("\n *** SUCCESSFUL TERMINATION ***\n *** Reductions in the sum of squares are at most ftol AND relative error between two consecutive iterates is at most xtol ***\n"); break;
            case 4:
                mexPrintf("\n *** SUCCESSFUL TERMINATION ***\n *** The cosine of the angle between fvec and any column of the jacobian is at most gtol in absolute value ***\n"); break;
            //Error
            case 0:
                mexPrintf("\n *** ERROR: IMPROPER INPUT PARAMETERS ***\n"); break;
            case 5:
                mexPrintf("\n *** MAXIMUM FUNCTION EVALUATIONS REACHED ***\n"); break;
            case 15:
                mexPrintf("\n *** MAXIMUM TIME REACHED ***\n"); break;
            //Early Exit
            case 6:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: ftol is too small (OPTI setting tolfun). No further improvement in the sum of squares is possible ***\n"); break;
            case 7:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: xtol is too small (OPTI hard-codes 1e-7). No further improvement in the approximate solution x is possible ***\n"); break;
            case 8:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: gtol is too small (OPTI hard-codes 1e-7). Fvec is orthogonal to the columns of the jacobian to machine precision ***\n"); break;
            case -1:
                mexPrintf("\n *** TERMINATION: USER EXITED ***\n"); break;
        }

        if(*exitflag==1)
            mexPrintf("\n Final SSE: %12.5g\n In %3.0f function evaluations\n",*fval,*iter);

        mexPrintf("------------------------------------------------------------------\n\n");
    }
    
    //Free Memory
    if(diag) mxFree(diag);
    if(fvec) mxFree(fvec);
    if(fjac) mxFree(fjac);
    if(ipvt) mxFree(ipvt);
    if(qtf)  mxFree(qtf);
    if(mptr) mxFree(mptr);
}
Beispiel #7
0
void mexFunction(int nlhs, mxArray *plhs[ ],
		 int nrhs, const mxArray *prhs[ ]) { 
  
  int i,j,pos;
  int *ptr_int;
  double *ptr_double;
  double *ptr_matlab;
#if MUMPS_ARITH == MUMPS_ARITH_z
  double *ptri_matlab;
#endif
  mwSize tmp_m,tmp_n;

  /* C pointer for input parameters */
  size_t inst_address;
  mwSize n,m,ne, netrue ;
  int inst,job;
  mwIndex *irn_in,*jcn_in;
  
  /* variable for multiple and sparse rhs */
  int posrhs;
          mwSize  nbrhs,ldrhs, nz_rhs;
  mwIndex *irhs_ptr, *irhs_sparse;
  double *rhs_sparse;
#if MUMPS_ARITH == MUMPS_ARITH_z
  double *im_rhs_sparse;
#endif

  DMUMPS_STRUC_C *dmumps_par;
  int dosolve = 0;
  int donullspace = 0;
  int doanal = 0;
  
  if(nrhs < 1) {
      if(nlhs < 1)
            printSolverInfo();
      else
            plhs[0] = mxCreateString("4.10.0");
      return;
  }         
  
  EXTRACT_FROM_MATLAB_TOVAL(JOB,job);


  dosolve = (job == 3 || job == 5 || job == 6);
  doanal = (job == 1 || job == 4 || job == 6);

  if(job == -1){
    DMUMPS_alloc(&dmumps_par);
    EXTRACT_FROM_MATLAB_TOVAL(SYM,dmumps_par->sym);
    dmumps_par->job = -1;
    dmumps_par->par = 1;
    dmumps_c(dmumps_par);
    dmumps_par->nz = -1;
    dmumps_par->nz_alloc = -1;
  }else{
    EXTRACT_FROM_MATLAB_TOVAL(INST,inst_address);
    ptr_int = (int *) inst_address;
    
    dmumps_par = (DMUMPS_STRUC_C *) ptr_int;
    
    if(job == -2){
      dmumps_par->job = -2;
      dmumps_c(dmumps_par);
      DMUMPS_free(&dmumps_par);
    }else{
      
      /* check of input arguments */
      n = mxGetN(A_IN);
      m = mxGetM(A_IN);
			
      if (!mxIsSparse(A_IN) || n != m )
          mexErrMsgTxt("Input matrix must be a sparse square matrix");
      
      jcn_in = mxGetJc(A_IN);
      ne = jcn_in[n];
      irn_in = mxGetIr(A_IN);
      dmumps_par->n = (int)n;
      if(dmumps_par->n != n)
          mexErrMsgTxt("Input is too big; will not work...barfing out\n");
      
      if(dmumps_par->sym != 0)
          netrue = (n+ne)/2;
      else
          netrue = ne;
      
      if(dmumps_par->nz_alloc < netrue || dmumps_par->nz_alloc >= 2*netrue){  
	MYFREE(dmumps_par->jcn);
	MYFREE(dmumps_par->irn);
	MYFREE(dmumps_par->a);
	MYMALLOC((dmumps_par->jcn),(int)netrue,int);
	MYMALLOC((dmumps_par->irn),(int)netrue,int);
	MYMALLOC((dmumps_par->a),(int)netrue,double2);
	dmumps_par->nz_alloc = (int)netrue;
    if (dmumps_par->nz_alloc != netrue)
        mexErrMsgTxt("Input is too big; will not work...barfing out\n");
      }


      if(dmumps_par->sym == 0){
	/* if analysis already performed then we only need to read
	   numerical values
	   Note that we suppose that matlab did not change the internal
	   format of the matrix between the 2 calls */
	if(doanal){ 
	  /* || dmumps_par->info[22] == 0 */
	  for(i=0;i<dmumps_par->n;i++){
	    for(j=jcn_in[i];j<jcn_in[i+1];j++){
	      (dmumps_par->jcn)[j] = i+1;
	      (dmumps_par->irn)[j] = ((int)irn_in[j])+1;
	    }
	  }
	}
    dmumps_par->nz = (int)ne;
    if( dmumps_par->nz != ne)
        mexErrMsgTxt("Input is too big; will not work...barfing out\n");
#if MUMPS_ARITH == MUMPS_ARITH_z
	ptr_matlab = mxGetPr(A_IN);
	for(i=0;i<dmumps_par->nz;i++){                                                   
	  ((dmumps_par->a)[i]).r = ptr_matlab[i];
	}
	ptr_matlab = mxGetPi(A_IN);
	if(ptr_matlab){
	  for(i=0;i<dmumps_par->nz;i++){                                                   
	    ((dmumps_par->a)[i]).i = ptr_matlab[i];
	  }
	}else{
	  for(i=0;i<dmumps_par->nz;i++){                                                   
	    ((dmumps_par->a)[i]).i = 0.0;
	  }
	}
#else
	ptr_matlab = mxGetPr(A_IN);
	for(i=0;i<dmumps_par->nz;i++){                                                   
	  (dmumps_par->a)[i] = ptr_matlab[i];
	}
#endif
	
      }else{
	/* in the symmetric case we do not need to check doanal */
	pos = 0;
	ptr_matlab = mxGetPr(A_IN);
#if MUMPS_ARITH == MUMPS_ARITH_z
	ptri_matlab = mxGetPi(A_IN);
#endif
	for(i=0;i<dmumps_par->n;i++){
	  for(j=jcn_in[i];j<jcn_in[i+1];j++){
	    if(irn_in[j] >= i){
	      if(pos >= netrue)
              mexErrMsgTxt("Input matrix must be symmetric");
	      (dmumps_par->jcn)[pos] = i+1;
	      (dmumps_par->irn)[pos] = (int)irn_in[j]+1;
#if MUMPS_ARITH == MUMPS_ARITH_z
	      ((dmumps_par->a)[pos]).r = ptr_matlab[j];
	      if(ptri_matlab){
		((dmumps_par->a)[pos]).i = ptri_matlab[j];
	      }else{
		((dmumps_par->a)[pos]).i = 0.0;
	      }
#else
	      (dmumps_par->a)[pos] = ptr_matlab[j];
#endif
	      pos++;
	    }
	  }
	}
	dmumps_par->nz = pos;
      }
    

      EXTRACT_FROM_MATLAB_TOVAL(JOB,dmumps_par->job);
      EXTRACT_FROM_MATLAB_TOARR(ICNTL,dmumps_par->icntl,int,40);
      EXTRACT_FROM_MATLAB_TOARR(CNTL,dmumps_par->cntl,double,15);
      EXTRACT_FROM_MATLAB_TOPTR(PERM_IN,(dmumps_par->perm_in),int,((int)n));

      EXTRACT_FROM_MATLAB_TOPTR(COLSCA,(dmumps_par->colsca),double,((int)n));
      EXTRACT_FROM_MATLAB_TOPTR(ROWSCA,(dmumps_par->rowsca),double,((int)n));

      dmumps_par->size_schur = (int)mxGetN(VAR_SCHUR);
      EXTRACT_FROM_MATLAB_TOPTR(VAR_SCHUR,(dmumps_par->listvar_schur),int,dmumps_par->size_schur);
      if(!dmumps_par->listvar_schur) dmumps_par->size_schur = 0;

      ptr_matlab = mxGetPr (RHS);

/*
 * To follow the "spirit" of the matlab/scilab interfaces, treat case of null
 * space separately. In that case, we initialize lrhs and nrhs automatically
 * allocate the space needed, and do not rely on what is provided by the user
 * in component RHS, that is not touched.
 *
 * Note that at the moment the user should not call the solution step combined
 * with the factorization step when he/she sets icntl[25-1] to a non-zero value.
 * Hence we suppose infog[28-1] is available and we can use it.
 * 
 * For users of scilab/matlab, it would still be nice to be able to set ICNTL(25)=-1,
 * and use JOB=6. If we want to make this functionality available, we should
 * call separately job=2 and job=3 even if job=5 or 6 and set nbrhs (and allocate
 * space correctly) between job=2 and job=3 calls to MUMPS.
 *
 */
      if ( dmumps_par->icntl[25-1] == -1 && dmumps_par->infog[28-1] > 0 ) {
          dmumps_par->nrhs=dmumps_par->infog[28-1];
          donullspace = dosolve;
         }
      else if ( dmumps_par->icntl[25-1] > 0 && dmumps_par->icntl[25-1] <= dmumps_par->infog[28-1] ) {
           dmumps_par->nrhs=1;
           donullspace = dosolve;
         }
      else {
	    donullspace=0;
	 }
      if (donullspace) {
        nbrhs=dmumps_par->nrhs; ldrhs=n;
	dmumps_par->lrhs=(int)n;
	MYMALLOC((dmumps_par->rhs),((dmumps_par->n)*(dmumps_par->nrhs)),double2);
         }
      else if((!dosolve) || ptr_matlab[0] == -9999 ) { /* rhs not already provided, or not used */
/*JY:  Case where dosolve is true and ptr_matlab[0]=-9999, this could cause problems:
 *        1/ RHS was not initialized while it should have been
 *        2/ RHS was explicitely initialized to -9999 but is not allocated of the right size
 */
        EXTRACT_CMPLX_FROM_MATLAB_TOPTR(RHS,(dmumps_par->rhs),double,1);
      }else{
Beispiel #8
0
// Function definitions. 
// -----------------------------------------------------------------
void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 
{
    //Input Args
    user_function_data fun, grad;
    iter_fun_data iterF;
    double *x0, *lb, *ub;
    //Options
    int printLevel = 0, maxIter = 1000, nupdate = 5, maxFeval = 1500;    
    double ftol = 1e-7, pgtol = 1e-5, maxtime = 1000;
    iterF.enabled = false;
    
    //Outputs Args
    double *x, *fval, *exitflag, *iter, *feval;
    
    //Internal Vars
    size_t ndec;
    int iiter, nfeval;
    
    if (nrhs < 1) {
        if(nlhs < 1)
            printSolverInfo();
        else
            plhs[0] = mxCreateString(LBFGSB_VERSION);
        return;
    }

    //Check user inputs
    checkInputs(prhs,nrhs);

    try 
    {
        //Get Size
        ndec = mxGetNumberOfElements(prhs[4]);
        //Get Function Handles
        if (mxIsChar(prhs[0])) {
            CHECK(mxGetString(prhs[0], fun.f, FLEN) == 0,"error reading objective name string");
            fun.nrhs = 1;
            fun.xrhs = 0;
        } else {
            fun.prhs[0] = (mxArray*)prhs[0];
            strcpy(fun.f, "feval");
            fun.nrhs = 2;
            fun.xrhs = 1;
        }
        if (mxIsChar(prhs[1])) {
            CHECK(mxGetString(prhs[1], grad.f, FLEN) == 0,"error reading gradient name string");
            grad.nrhs = 1;
            grad.xrhs = 0;
        } else {
            grad.prhs[0] = (mxArray*)prhs[1];
            strcpy(grad.f, "feval");
            grad.nrhs = 2;
            grad.xrhs = 1;
        }
        fun.prhs[fun.xrhs] = mxCreateDoubleMatrix(ndec, 1, mxREAL); //x0
        grad.prhs[grad.xrhs] = mxCreateDoubleMatrix(ndec, 1, mxREAL);
        
        //Get Bounds + x0
        lb = mxGetPr(prhs[2]);
        ub = mxGetPr(prhs[3]);
        x0 = mxGetPr(prhs[4]);
        
        //Get Options if specified
        if(nrhs > 5) {
            GetIntegerOption(prhs[5], "display", &printLevel);
            GetIntegerOption(prhs[5], "maxiter", &maxIter);
            GetIntegerOption(prhs[5], "maxfeval", &maxFeval);
            GetIntegerOption(prhs[5], "nupdate", &nupdate);
            GetDoubleOption(prhs[5], "tolrfun", &ftol);
            GetDoubleOption(prhs[5], "tolrfun", &ftol);
            GetDoubleOption(prhs[5], "pgtol", &pgtol);
            GetDoubleOption(prhs[5], "maxtime", &maxtime);            
            if(mxGetField(prhs[5],0,"iterfun") && !mxIsEmpty(mxGetField(prhs[5],0,"iterfun")))
            {
                iterF.prhs[0] = (mxArray*)mxGetField(prhs[5],0,"iterfun");
                strcpy(iterF.f, "feval");
                iterF.enabled = true;  
                iterF.prhs[1] = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL);
                iterF.prhs[2] = mxCreateDoubleMatrix(1,1,mxREAL);
                iterF.prhs[3] = mxCreateDoubleMatrix(ndec,1,mxREAL);
            }
        }                        
        
        //Create Outputs
        plhs[0] = mxCreateDoubleMatrix(ndec,1, mxREAL);
        plhs[1] = mxCreateDoubleMatrix(1,1, mxREAL);
        plhs[2] = mxCreateDoubleMatrix(1,1, mxREAL);
        plhs[3] = mxCreateDoubleMatrix(1,1, mxREAL);
        plhs[4] = mxCreateDoubleMatrix(1,1, mxREAL);
        x = mxGetPr(plhs[0]); 
        fval = mxGetPr(plhs[1]); 
        exitflag = mxGetPr(plhs[2]);    
        iter = mxGetPr(plhs[3]);
        feval = mxGetPr(plhs[4]);
        
        //Create Class for Peter's L-BFGS-B Interface
        lbfgsb_program solver(&fun,&grad,&iterF,ndec,lb,ub,x0,x,fval,iter,printLevel,maxIter,maxFeval,maxtime,ftol,nupdate,pgtol);
        
        //Run the Solver
        int exitStatus = solver.runSolver(iiter,nfeval,*fval);
        //Save Status & Iterations
        *exitflag = (double)exitStatus;
        *iter = (double)iiter;
        *feval = (double)nfeval;

    } 
    catch (std::exception& error) 
    {
        mexErrMsgTxt(error.what());
    }
}
//Main Function
void mexFunction(int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[])
{
    //Input Args
    double *f, *blin = NULL, *lb = NULL, *ub = NULL, *y0 = NULL;
    
    //Return Args
    double *x, *pval, *dval, *exitflag, *iter, *pinf, *dinf, *realgap, *xzgap;
    
    //Options (most get defaults written in)
    int maxiter = 1500;  
    
    //Internal Vars
    size_t ndec = 0, nlincon = 0, lincon_nz = 0, total_dim = 0, ncones = 0; 
    size_t i, j;
    const char *onames[2] = {"pval","dval"};
    const char *fnames[5] = {"iter","pinf","dinf","realgap","xzgap"};    
    double evaltime;
    int status = -1, nb = 0, linoffset = 0, indlb = 1, indub = 1, nLB = 0, nUB = 0;
    mwIndex *jc;
    
    //CSDP Problem Data
    struct blockmatrix C;
    double *b, *y, *xx, objconstant = 0.0;
    struct constraintmatrix *constraints;
    struct blockmatrix X, Z;
    struct sparseblock *blockptr;
    struct paramstruc params;

    //Version Return
    if(nrhs < 1) {
        if(nlhs < 1)
            printSolverInfo();
        else
            plhs[0] = mxCreateString(CSDP_VERSION);
        return;
    }        
    
    //Check Inputs
    checkInputs(prhs,nrhs); 
    
    //Get pointers to Input variables
	f = mxGetPr(pF); ndec = mxGetNumberOfElements(pF);
    if(!mxIsEmpty(pA)) {
        blin = mxGetPr(pB);
        nlincon = mxGetM(pA);
        jc = mxGetJc(pA);
        lincon_nz = jc[ndec];        
    }
    if(nrhs > eLB && !mxIsEmpty(pLB)) {
        lb = mxGetPr(pLB); 
        //Ensure we have at least one finite bound
        for(i=0,j=0;i<ndec;i++)
            if(mxIsInf(lb[i]))
                j++;
        if(j==ndec)
            lb = NULL;
    }
    if(nrhs > eUB && !mxIsEmpty(pUB)) {
        ub = mxGetPr(pUB);
        //Ensure we have at least one finite bound
        for(i=0,j=0;i<ndec;i++)
            if(mxIsInf(ub[i]))
                j++;
        if(j==ndec)
            ub = NULL;
    }
    if(nrhs > eSDP && !mxIsEmpty(pSDP)) {
        if(mxIsCell(pSDP))
            ncones = mxGetNumberOfElements(pSDP);
        else
            ncones = 1;
    }
    if(nrhs > eY0 && !mxIsEmpty(pY0))
        y0 = mxGetPr(pY0);
    
    //Create Outputs
    plhs[0] = mxCreateDoubleMatrix(ndec,1, mxREAL);
    plhs[1] = mxCreateStructMatrix(1,1,2,onames);
    mxSetField(plhs[1],0,onames[0],mxCreateDoubleMatrix(1,1, mxREAL));
    mxSetField(plhs[1],0,onames[1],mxCreateDoubleMatrix(1,1, mxREAL));
    plhs[2] = mxCreateDoubleMatrix(1,1, mxREAL);   
    x = mxGetPr(plhs[0]); 
    pval = mxGetPr(mxGetField(plhs[1],0,onames[0]));
    dval = mxGetPr(mxGetField(plhs[1],0,onames[1]));
    exitflag = mxGetPr(plhs[2]);    
    //Info Output    
    plhs[3] = mxCreateStructMatrix(1,1,5,fnames);
    mxSetField(plhs[3],0,fnames[0],mxCreateDoubleMatrix(1,1, mxREAL));
    mxSetField(plhs[3],0,fnames[1],mxCreateDoubleMatrix(1,1, mxREAL));
    mxSetField(plhs[3],0,fnames[2],mxCreateDoubleMatrix(1,1, mxREAL));
    mxSetField(plhs[3],0,fnames[3],mxCreateDoubleMatrix(1,1, mxREAL));
    mxSetField(plhs[3],0,fnames[4],mxCreateDoubleMatrix(1,1, mxREAL));
    iter = mxGetPr(mxGetField(plhs[3],0,fnames[0]));
    pinf = mxGetPr(mxGetField(plhs[3],0,fnames[1]));
    dinf = mxGetPr(mxGetField(plhs[3],0,fnames[2]));
    realgap = mxGetPr(mxGetField(plhs[3],0,fnames[3]));
    xzgap = mxGetPr(mxGetField(plhs[3],0,fnames[4]));
    
    //Set Defaults
    citer = 0;
    maxtime = 1000;
    printLevel = 0;
    
    //Allocate Initial Storage for the Problem
    b = (double*)malloc((ndec+1)*sizeof(double));       //objective vector
    //C matrices [LB UB LIN SD]
    nb = (int)ncones+(int)(nlincon>0)+(int)(lb!=NULL)+(int)(ub!=NULL);
    #ifdef DEBUG
        mexPrintf("Number of blocks (including bounds, linear and sdcones): %d\n",nb);
    #endif            
    C.nblocks   = nb;
    C.blocks    = (struct blockrec*)malloc((nb+1)*sizeof(struct blockrec)); //+1 due to fortran index
    if(C.blocks == NULL)
        mexErrMsgTxt("Error allocating memory for C matrices");
    //Constraints (i.e. 1 per decision variable)
    constraints = (struct constraintmatrix*)malloc((ndec+1)*sizeof(struct constraintmatrix)); //+1 due to fortran index
    if(constraints == NULL) {
        free(C.blocks);
        mexErrMsgTxt("Error allocating memory for A matrices");
    }
    for(i=1;i<=ndec;i++)
        constraints[i].blocks=NULL; //initially set as NULL
    
    //Copy in and negate objective vector
    for(i=0;i<ndec;i++)
        b[i+1] = -f[i];
    
    //Create Bounds if Present
    if(lb || ub)
        linoffset += addBounds(C,lb,ub,ndec,&nLB,&nUB);
    
    //Create Linear Cone (diagonal) if present
    if(nlincon) {
        //Initialize C
        C.blocks[linoffset+1].blockcategory = DIAG;
        C.blocks[linoffset+1].blocksize = (int)nlincon;
        C.blocks[linoffset+1].data.vec = (double*)malloc((nlincon+1)*sizeof(double));
        if(C.blocks[linoffset+1].data.vec == NULL)
            mexErrMsgTxt("Error allocating memory for LP C diagonal");
        #ifdef DEBUG
            mexPrintf("LP C[%d] Vector size: %d\n",linoffset+1,nlincon);
        #endif        
        //Copy Elements
        for(i=0;i<nlincon;i++) {
            C.blocks[linoffset+1].data.vec[i+1] = -blin[i];
            #ifdef DEBUG
                mexPrintf("  C vec[%d] = %f\n",i+1,-blin[i]);
            #endif
        }
        linoffset++;
    }
    
    #ifdef DEBUG
        mexPrintf("\nBlock offset after bounds + linear con: %d\n\n",linoffset);
    #endif
    
    //Setup Semidefinite C matrices (note all full matrices, dense, in order from 1)
    for(i=1;i<=ncones;i++) {
        //Single Cone
        if(ncones == 1 && !mxIsCell(pSDP))
            total_dim += addCMatrix(C,pSDP,(int)i+linoffset);
        //Multiple Cones
        else 
            total_dim += addCMatrix(C,mxGetCell(pSDP,i-1),(int)i+linoffset);     
    }    
    //Add Linear Dims
    total_dim += nLB+nUB+nlincon;
    
    #ifdef DEBUG
        mexPrintf("\nTotal dimension of all cones: %d\n\n",total_dim);
    #endif
    
    //Setup Each Constraint (for each decision var) (in order from 1)
    indlb = 1; indub = 1;
    for(i=1;i<=ndec;i++) { 
        //For each Semidefinte A matrix (sparse triu, in reverse order, i.e. [SD, LP, UB, LB])
        for(j=ncones;j>0;j--) {
            //Create an A matrix            
            blockptr=(struct sparseblock*)malloc(sizeof(struct sparseblock));
            if(blockptr==NULL) {
                sprintf(msgbuf,"Error allocating memory for Semidefinite A[%d,%d]",i,j+linoffset);
                mexErrMsgTxt(msgbuf);
            }            
            //Single Cone
            if(ncones == 1 && !mxIsCell(pSDP)) 
                addAMatrix(blockptr,pSDP,(int)i,(int)j+linoffset); 
            //Multiple Cones
            else 
                addAMatrix(blockptr,mxGetCell(pSDP,j-1),(int)i,(int)j+linoffset);
            
            //Insert A matrix into constraint list
            blockptr->next=constraints[i].blocks;
            constraints[i].blocks=blockptr;
        }  
        
        //Linear Inequality Constraints
        if(nlincon) {
            //Create an A matrix
             blockptr=(struct sparseblock*)malloc(sizeof(struct sparseblock));
            if(blockptr==NULL) {
                sprintf(msgbuf,"Error allocating memory for LP A[%d]",i);
                mexErrMsgTxt(msgbuf);
            }
            //Insert LP A entries
            j = 1 + (int)(nUB > 0) + (int)(nLB > 0);
            insertLPVector(blockptr, pA, (int)i, (int)j);             
            //Insert A matrix into constraint list
            blockptr->next=constraints[i].blocks;
            constraints[i].blocks=blockptr;
        }
        
        //Upper Bounds
        if(nUB) {
            //Create an A matrix
            blockptr=(struct sparseblock*)malloc(sizeof(struct sparseblock));
            if(blockptr==NULL) {
                sprintf(msgbuf,"Error allocating memory for UB A[%d]",i);
                mexErrMsgTxt(msgbuf);
            }            
            //Insert Bound A matrix entries
            if(nLB > 0)
                indub += insertBound(blockptr,ub,nUB,(int)i,2,indub,1.0); //block 2 ([LB,UB,..] 1.0 for ub)
            else
                indub += insertBound(blockptr,ub,nUB,(int)i,1,indub,1.0); //block 1 (first block, 1.0 for ub)
            //Insert A matrix into constraint list
            blockptr->next=constraints[i].blocks;
            constraints[i].blocks=blockptr;
        }
        
        //Lower Bounds
        if(nLB) {
            //Create an A matrix
            blockptr=(struct sparseblock*)malloc(sizeof(struct sparseblock));
            if(blockptr==NULL) {
                sprintf(msgbuf,"Error allocating memory for LB A[%d]",i);
                mexErrMsgTxt(msgbuf);
            }            
            //Insert Bound A matrix entries
            indlb += insertBound(blockptr,lb,nLB,(int)i,1,indlb,-1.0); //block 1 (always first block, -1.0 for lb)
            //Insert A matrix into constraint list
            blockptr->next=constraints[i].blocks;
            constraints[i].blocks=blockptr;
        }
    }

//     //Set y0
//     if (y0)
//         for (i=0;i<ndec;i++) {
//             DSDP_ERR( DSDPSetY0(dsdp,(int)i+1,y0[i]), "Error setting Y0");            
//         }
//     
    
    //Get CSDP Default Options
    initparams(&params,&printLevel); 
    //Set OPTI default printLevel (none)
    printLevel = 0;
    
    //Get User Options (overwrites defaults above)
    if(nrhs > eOPTS && !mxIsEmpty(pOPTS)) {
        //OPTI Options
        GetIntegerOption(pOPTS,"maxiter",&params.maxiter);
        GetDoubleOption(pOPTS,"maxtime",&maxtime);
        GetIntegerOption(pOPTS,"display",&printLevel);
        GetDoubleOption(pOPTS,"objconstant",&objconstant);
        //CSDP Options
        GetDoubleOption(pOPTS,"axtol",&params.axtol);
        GetDoubleOption(pOPTS,"atytol",&params.atytol);
        GetDoubleOption(pOPTS,"objtol",&params.objtol);
        GetDoubleOption(pOPTS,"pinftol",&params.pinftol);
        GetDoubleOption(pOPTS,"dinftol",&params.dinftol);
        GetDoubleOption(pOPTS,"minstepfrac",&params.minstepfrac);
        GetDoubleOption(pOPTS,"maxstepfrac",&params.maxstepfrac);
        GetDoubleOption(pOPTS,"minstepp",&params.minstepp);
        GetDoubleOption(pOPTS,"minstepd",&params.minstepd);
        GetIntegerOption(pOPTS,"usexzgap",&params.usexzgap);
        GetIntegerOption(pOPTS,"tweakgap",&params.tweakgap); 
        GetIntegerOption(pOPTS,"affine",&params.affine);
        GetDoubleOption(pOPTS,"perturbobj",&params.perturbobj);
        //Optionally write problem to a SDPA sparse file
        if(mxGetField(pOPTS,0,"writeprob") && !mxIsEmpty(mxGetField(pOPTS,0,"writeprob")) && mxIsChar(mxGetField(pOPTS,0,"writeprob"))) {
            mxGetString(mxGetField(pOPTS,0,"writeprob"),msgbuf,1024);
            write_prob(msgbuf,(int)total_dim,(int)ndec,C,b,constraints);
        }
    }

    //Print Header
    if(printLevel) {
        mexPrintf("\n------------------------------------------------------------------\n");
        mexPrintf(" This is CSDP v%s\n",CSDP_VERSION); 
        mexPrintf(" Author: Brian Borchers\n MEX Interface J. Currie 2013\n\n");
        mexPrintf(" Problem Properties:\n");
        mexPrintf(" # Decision Variables:        %4d\n",ndec);   
        mexPrintf(" # Linear Inequalities:       %4d ",nlincon);
        if(nlincon)
            mexPrintf("[%d nz]\n",lincon_nz);
        else
            mexPrintf("\n");   
        mexPrintf(" # Semidefinite Cones:        %4d\n",ncones);

        mexPrintf("------------------------------------------------------------------\n");
    }
    
    //Start timer
    start = clock();
    //Find Initial Solution
    initsoln((int)total_dim,(int)ndec,C,b,constraints,&X,&y,&Z);
    //Solve the problem
    status=easy_sdp((int)total_dim,(int)ndec,C,b,constraints,objconstant,params,&X,&y,&Z,pval,dval,pinf,dinf,realgap,xzgap);
    //Stop Timer
    end = clock();
    evaltime = ((double)(end-start))/CLOCKS_PER_SEC;
    
    //Copy and negate solution
    for(i=0;i<ndec;i++)
        x[i] = -y[i+1];
    //Assign other MATLAB outputs
    *iter = (double)citer-1;    
    *exitflag = (double)status;
     
    //Print Header
    if(printLevel){            
        //Detail termination reason
        switch(status)
        {
            //Success
            case 0:	
                mexPrintf("\n *** CSDP CONVERGED ***\n");  break;
            //Infeasible
            case 1:
                mexPrintf("\n *** TERMINATION: Primal Infeasible ***\n");  break;
            case 2:
                mexPrintf("\n *** TERMINATION: Dual Infeasible ***\n");  break;
            //Partial Success
            case 3:
                mexPrintf("\n *** TERMINATION: PARTIAL SUCESS ***\n *** A Solution is found but full accuracy was not achieved ***\n"); break;
            //Error
            case 4:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: Maximum Iterations Reached ***\n"); break;
            case CSDP_MAX_TIME:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: Maximum Time Reached ***\n"); break;
            case 5:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: Stuck at edge of primal feasibility ***\n"); break;
            case 6:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: Stuck at edge of dual infeasibility ***\n"); break;
            case 7:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: Lack of progress ***\n"); break;
            case 8:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: X, Z, or O was singular ***\n"); break;
            case 9:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: Detected NaN or Inf values ***\n"); break;
            case 10:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: Easy-SDP General Failure ***\n"); break;
            case 11:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: Failed C Check - Check Symmetry! ***\n"); break;
            case 12:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: Failed Constraints Check ***\n"); break;
            case CSDP_USER_TERMINATION:
                mexPrintf("\n *** TERMINATION: EARLY EXIT ***\n *** CAUSE: User Exited ***\n"); break;            
            //Here is ok too?
            default:
                mexPrintf("\n *** CSDP FINISHED ***\n"); break;
        }

        if(status==0 || status==3)
        	mexPrintf("\n Final Primal Objective:  %2.5g\n Final Dual Objective:    %2.5g\n In %5d iterations\n    %5.2f seconds\n",*pval,*dval,citer-1,evaltime);

        mexPrintf("------------------------------------------------------------------\n\n");
    }  
    
    //Optionally write solution to a SDPA sparse file
    if(nrhs > eOPTS && !mxIsEmpty(pOPTS) && mxGetField(pOPTS,0,"writesol") && !mxIsEmpty(mxGetField(pOPTS,0,"writesol")) && mxIsChar(mxGetField(pOPTS,0,"writesol"))) {
        mxGetString(mxGetField(pOPTS,0,"writesol"),msgbuf,1024);
        write_sol(msgbuf,(int)total_dim,(int)ndec,X,y,Z);
    }
    
    //Optionally retrieve X
    if(nlhs > 4) {
        plhs[4] = mxCreateCellMatrix(X.nblocks,1);
        for(i=0;i<X.nblocks;i++) {            
            //Set Block Values
            if(X.blocks[i+1].blockcategory == DIAG) {
                mxSetCell(plhs[4],i,mxCreateDoubleMatrix(X.blocks[i+1].blocksize,1,mxREAL)); //create vector
                xx = mxGetPr(mxGetCell(plhs[4],i));
                for(j=0;j<X.blocks[i+1].blocksize;j++)
                    xx[j] = X.blocks[i+1].data.vec[j+1]; 
            }
            else {
                mxSetCell(plhs[4],i,mxCreateDoubleMatrix(X.blocks[i+1].blocksize,X.blocks[i+1].blocksize,mxREAL)); //create matrix
                xx = mxGetPr(mxGetCell(plhs[4],i));
                for(j=0;j<(X.blocks[i+1].blocksize*X.blocks[i+1].blocksize);j++)
                    xx[j] = X.blocks[i+1].data.mat[j];           
            }
        }        
    }

    //Free CSDP Problem (including all allocated memory)
    free_prob((int)total_dim,(int)ndec,C,b,constraints,X,y,Z);
}