EnergyMinimization.cpp

Go to the documentation of this file.
00001 
00006 #include "EnergyMinimization.h"
00007 #include "CirclePattern.h"
00008 #ifdef _WIN32
00009 #ifndef MSKDLL 
00010 #define MSKDLL 
00011 #endif
00012 #endif
00013 #include "mosek.h"   /* Include the MOSEK definition file. */
00014 #include "util.h"
00015 #include <fstream>
00016 #include <iomanip>
00017 
00018 using namespace std;
00019 
00020 
00024 static int MSKAPI nlspar(void *nlhandle, int  *numgrdobjnz, int  *grdobjsub, int  i,
00025                             int  *convali, int  *grdconinz, int  *grdconisub, int  yo,
00026                             int  numycnz, int  ycsub[], int  maxnumhesnz,
00027                             int  *numhesnz, int  *hessubi, int  *hessubj) 
00028 {
00029 
00030    Mesh * mesh = (Mesh *)nlhandle;
00031    Mesh::HalfEdgeIterator hIter = mesh->halfEdgeIterator();
00032    int NumInteriorEdges = mesh->numEdges() - mesh->numBoundary();
00033 
00034    if ( numgrdobjnz ) {
00036       numgrdobjnz[0] = mesh->numFaces();
00037 
00038       if ( grdobjsub ) {
00040           for (int i = 0; i <  mesh->numFaces(); i++)
00041              grdobjsub[i] = i;
00042       }
00043    }
00044 
00045    if ( convali )
00046       convali[0] = 0;    /* Zero because no nonlinear expression in the constraint. */
00047 
00048    if ( grdconinz )
00049       grdconinz[0] = 0;  /* Zero because no nonlinear expression in the constraint. */
00050 
00051    if ( numhesnz ) {
00052       if (yo)
00053           numhesnz[0] = NumInteriorEdges + mesh->numFaces();   
00054       else
00055           numhesnz[0] = 0;
00056    }
00057 
00058    if ( maxnumhesnz ) {
00059       check_error (maxnumhesnz < (NumInteriorEdges + mesh->numFaces()), "Not enough space was allocated for hessian.");
00060       if (yo) {
00061           if  (hessubi && hessubj) 
00062              CirclePattern::buildSparsityForHessian(mesh, hessubi, hessubj);
00063       }
00064    }
00065    return ( MSK_RES_OK );
00066 } /* nlspar */
00067 
00068 
00071 static int MSKAPI nleval(void   *nlhandle, double *xx, double yo, double *yc,
00072                             double *objval, int    *numgrdobjnz, int    *grdobjsub,
00073                             double *grdobjval, int    numi, int    *subi, double *conval,
00074                             int    *grdconptrb, int    *grdconptre, int    *grdconsub,
00075                             double *grdconval, double *grdlag, int    maxnumhesnz,
00076                             int    *numhesnz, int    *hessubi, int    *hessubj, 
00077                             double *hesval)
00078 {
00079    Mesh * mesh = (Mesh *)nlhandle;
00080    int NumInteriorEdges = mesh->numEdges() - mesh->numBoundary();
00081 
00082    if ( objval) {
00083       objval[0] = CirclePattern::evaluateEnergy(mesh, xx);   
00084    }
00085    if ( numgrdobjnz ) {
00086       numgrdobjnz[0] = mesh->numFaces();                     
00087       for (int k = 0; k < mesh->numFaces(); k++) 
00088           grdobjsub[k] = k;
00089       CirclePattern::computeGradient(mesh, xx, grdobjval);
00090    }
00091    if ( conval )
00092       for(int k=0; k<numi; ++k)
00093           conval[k] = 0.0;
00094 
00095    if ( grdlag ) 
00096       CirclePattern::computeGradient(mesh, xx, grdlag);
00097 
00098    if ( maxnumhesnz ) {
00099       if ( yo==0.0 ) 
00100           numhesnz[0] = 0;
00101       else {                                                
00103           check_error (maxnumhesnz < (NumInteriorEdges + mesh->numFaces()), 
00104              "Not enough space was allocated for hessian.");
00105           numhesnz[0] = NumInteriorEdges + mesh->numFaces();
00106 
00107           if ( hessubi && hessubj && hesval ) {
00108              CirclePattern::buildSparsityForHessian(mesh, hessubi, hessubj);
00109              CirclePattern::computeHessian(mesh, xx, hesval);
00110           }
00111       }
00112    }
00113    return ( MSK_RES_OK );
00114 } /* nleval */
00115 
00116 EnergyMinimization::EnergyMinimization(Mesh * _mesh, const MSKenv_t & env) {
00117    mesh = _mesh;
00118 
00119    NUMVAR = mesh->numFaces();
00120    NUMCON = 1;
00121    NUMANZ = NUMVAR;
00122 
00124    int r = MSK_RES_OK;
00125    r = MSK_maketask(env, NUMCON, NUMVAR, &task);
00126    check_error (r != MSK_RES_OK, "Cannot make MOSEK task for radii energy minimization.");
00127    r = MSK_linkfiletotaskstream(task, MSK_STREAM_LOG, "_RadiiMinMosekOut.txt", 0);
00128    check_error (r != MSK_RES_OK, "Cannot link MOSEK \"_RadiiMinMosekOut.txt\" output file.");
00129 }
00130 
00131 void EnergyMinimization::doSolve() {
00132    allocateMosekArrays();
00133    setDataStructres();
00134    minimize();   
00135 }
00136 
00137 void EnergyMinimization::setDataStructres() {
00145    bkc[0] = MSK_BK_FX;
00146    blc[0] = 0.0;
00147    buc[0] = 0.0;
00148 
00151    for (int i = 0; i < NUMVAR; i++){
00152       c[i]     = 1.0;
00153       ptrb[i]  = i;  ptre[i] = i+1;
00154       sub[i]   = 0;  val[i]  = 1.0;
00155 
00156       bkx[i]   = MSK_BK_FR;
00157       blx[i]   = -MSK_INFINITY;
00158       bux[i]   = MSK_INFINITY;
00159    }
00160 }
00161 
00162 void EnergyMinimization::minimize() {
00163    int r = MSK_RES_OK;
00164 
00166    r = MSK_inputdata(task, NUMCON, NUMVAR, NUMCON, NUMVAR, c, 0.0, ptrb, ptre, sub, val, bkc, blc, buc, bkx, blx, bux);
00167    check_error ( r != MSK_RES_OK, 
00168       "Could not input constraints for radii minimization.\n Check  \"RadiiMinMosekOut.txt\" for output." );
00169 
00171    r = MSK_putnlfunc(task, mesh, nlspar, nleval);
00172    check_error ( r != MSK_RES_OK, 
00173       "Could not input nonlinear function for radii minimization.\n Check  \"RadiiMinMosekOut.txt\" for output." );
00174 
00176    r = MSK_optimize(task);
00177    check_error ( r != MSK_RES_OK, 
00178       "Could not solve for radii minimization.\n Check  \"RadiiMinMosekOut.txt\" for output." );
00179 
00180    r = MSK_getsolutionslice(task, MSK_SOL_ITR, MSK_SOL_ITEM_XX, 0, NUMVAR, xx);
00181    check_error ( r != MSK_RES_OK, "Could not get radii solution.\n Check  \"RadiiMinMosekOut.txt\" for output." );
00182 
00183    MSK_solutionsummary(task, MSK_STREAM_ERR);
00184 
00186    Mesh::FaceIterator fIter = mesh->faceIterator();
00187    for (int i = 0; !fIter.end(); fIter++) { 
00188       fIter.face()->r = exp(xx[i++]);
00189    }
00190 }
00191 
00192 void EnergyMinimization::allocateMosekArrays() {
00193    bkc = new int[NUMCON];
00194    bkx = new int[NUMVAR];
00195    ptrb = new int[NUMVAR];
00196    ptre = new int[NUMVAR];
00197    sub = new int[NUMANZ];
00198    blc = new double[NUMCON];
00199    buc = new double[NUMCON];
00200    c = new double[NUMVAR];
00201    blx = new double[NUMVAR];
00202    bux = new double[NUMVAR];
00203    val = new double[NUMANZ];
00204    xx = new double[NUMVAR];
00205 }
00206 
00207 void EnergyMinimization::clearMosekArrays() {
00208    if (task) {
00209 
00210       delete [] bkc;
00211       delete [] bkx;
00212       delete [] ptrb;
00213       delete [] ptre;
00214       delete [] sub;
00215       delete [] blc;
00216       delete [] buc;
00217       delete [] c;
00218       delete [] blx;
00219       delete [] bux;
00220       delete [] val;
00221       MSK_deletetask(&task);
00222       task = NULL;
00223    }
00224 }
00225 

Generated on Sat Jun 3 13:33:41 2006 for CirclePatterns by  doxygen 1.4.5