int Solver_Core::Solve(int num_basis, double cvm_eps) { timeusedForModelSaving = 0; modelsWritten = 0; algorithmStartTime = pnow(); nextSaveTime = param->saveFactor * (modelsWritten+1) + floor (pow (param->saveExponential, 1)); saveExponential = param->saveExponential; this->maxNumBasis = num_basis; // The convergence of CVM does not require the exact MEB on the core-set. // With the recent advance of core-set approximation, the (1+epsilon/2)-MEB approximation on the core-set // can guarantee the quality and the convergence of the (1+epsilon)-MEB approximation for the whole data set. // See [Kumar, Mitchell, and Yildirim, 2003] // // iterate on epsilons double epsilonFactor = EPS_SCALING; for(double currentEpsilon = INITIAL_EPS; currentEpsilon/epsilonFactor > cvm_eps; currentEpsilon *= epsilonFactor) { // check epsilon currentEpsilon = (currentEpsilon < cvm_eps ? cvm_eps : currentEpsilon); // solve problem with current epsilon (warm start from the previous solution) double maxDistance2 = 0.0; int maxDistance2Idx = 0; double factor = 1.0 + currentEpsilon; factor *= factor; // The convergence of CVM does not require the exact most violating point. // A violating point is enough for the convergence of CVM. // Probabilistic speedup lead to a good tradeoff between convergence and complexity at each iteration // while (maxDistance2Idx != -1) { // get a probabilistic sample maxDistance2 = r2 * factor; maxDistance2Idx = -1; for(int sampleIter = 0; (sampleIter < 7) && (maxDistance2Idx == -1); sampleIter++) maxDistance2 = _maxDistFromSampling(maxDistance2, maxDistance2Idx); // check maximal distance if (maxDistance2Idx != -1) { _UpdateCoreSet(maxDistance2Idx); #ifndef RELEASE_VER printf("#%d eps: %g |c|: %.10f R: %.10f |c-x|: %.10f r: %.10f\n",coreNum, currentEpsilon, coreNorm2, r2, maxDistance2, sqrt(maxDistance2/r2)-1.0); #endif solver->Solve(coreIdx,coreNum,tempD); outAlpha = solver->getAlpha(); ComputeRadius2(); // if (coreNum%20 < 1) info("."); } double currentTime = pnow (); if ((param->saveExponential >= 0.0) && (currentTime - algorithmStartTime >= nextSaveTime + timeusedForModelSaving )) { modelsWritten++; printf( "&%d..", modelsWritten); nextSaveTime = param->saveFactor * (modelsWritten+1) + pow (param->saveExponential, modelsWritten + 1); // std::cout << "Algorithm time is now " << currentTime - algorithmStartTime - timeusedForModelSaving << "\n"; // std::cout << " Saving model now at " << currentTime - startTime << "\n"; double before = pnow(); svm_model *model = Malloc(svm_model,1); model->param = *param; model->free_sv = 0; // XXX model->nr_class = param->nr_classes; model->label = Malloc(int,model->nr_class); for(int i=0;i<model->nr_class;i++) model->label[i] = param->label[i]; model->rho = Malloc(double,1); double *alpha = Malloc(double,param->prob->l); double THRESHOLD = 1e-5/coreNum; for(int i=0;i<1;i++) model->rho[i] = -ComputeSolution(alpha, THRESHOLD); //overwrite alphas! model->nSV = Malloc(int, model->nr_class); // assume all the nonzeros are false at the beginning, // we have binary classification, they will not change in the // outer loop in svm.cpp int total_sv = 0; for(int i=0;i<model->nr_class;i++) { int nSV = 0; for(int j=0;j<param->count[i];j++) { if(fabs(alpha[param->start[i]+j])) { ++nSV; ++total_sv; } } model->nSV[i] = nSV; } model->l = total_sv; //anzahl der sv im model // ASSUME PERMUTATION IS IDENTITY svm_node **x = Malloc(svm_node *,param->prob->l); int i; for(int i=0;i<param->prob->l;i++) x[i] = param->prob->x[i]; // x[i] = param->prob->x[perm[i]]; model->SV = Malloc(svm_node *,total_sv); int p = 0; for(int i=0;i<param->prob->l;i++) { if(fabs(alpha[i]) > 0.0) { model->SV[p++] = x[i]; } } model->sv_coef = Malloc(double *,model->nr_class-1); for(int i=0;i<model->nr_class-1;i++) { model->sv_coef[i] = Malloc(double,total_sv); } // printf ("%d SV class 0, %d SV class 1\n", model->nSV[0], model->nSV[1]); int q = 0; for(int i=0;i<model->nr_class;i++) { for(int j=0;j < param->count[i];j++) { if(fabs(alpha[param->start[i]+j]) > 0.0) { model->sv_coef[0][q++] = alpha[param->start[i]+j];// * param->prob->y[param->start[i]+j]; // printf ("%d -- %f\n", q, alpha[param->start[i]+j]); } } } p = 0; char tmp[1000]; if (strlen(param->modelPath) < 2) { sprintf(tmp,"%s_%d",param->modelFile, (int)floor( before - algorithmStartTime - timeusedForModelSaving) ); } else { sprintf(tmp,"%s/%d.cvm.model",param->modelPath, (int)floor( before - algorithmStartTime - timeusedForModelSaving) ) ; } model->probB = NULL; model->probA = NULL; svm_save_model(tmp, model); // just to keep compability FILE* fModel = fopen(tmp, "a+t"); // append mode fprintf(fModel, "CPU Time = %f second\n", before - algorithmStartTime - timeusedForModelSaving); fclose(fModel); // svm_destroy_model(model); //free(x); double after = pnow(); timeusedForModelSaving += after - before; } // check if we are over the walltime if (pnow() - param->startTime > param->wallTime + timeusedForModelSaving) { printf ("Hit the walltime, exiting now..\n"); return coreNum; } if (IsExitOnMaxIter()) { return coreNum; break; } } }
/* Run with -build_twosided allreduce -pc_type bjacobi -sub_pc_type lu -q 16 -ksp_rtol 1.e-34 (or 1.e-14 for double precision) -q <q> number of spectral elements to use -N <N> maximum number of GLL points per element */ int main(int argc,char **args) { PetscErrorCode ierr; PetscGLL gll; PetscInt N = 80,n,q = 8,xs,xn,j,l; PetscReal **A; Mat K; KSP ksp; PC pc; Vec x,b; PetscInt *rows; PetscReal norm,xc,yc,h; PetscScalar *f; PetscDraw draw; PetscDrawLG lg; PetscDrawAxis axis; DM da; PetscMPIInt rank,size; ierr = PetscInitialize(&argc,&args,NULL,NULL);if (ierr) return ierr; ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,NULL,"-N",&N,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,NULL,"-q",&q,NULL);CHKERRQ(ierr); ierr = PetscDrawCreate(PETSC_COMM_WORLD,NULL,"Log(Error norm) vs Number of GLL points",0,0,500,500,&draw);CHKERRQ(ierr); ierr = PetscDrawSetFromOptions(draw);CHKERRQ(ierr); ierr = PetscDrawLGCreate(draw,1,&lg);CHKERRQ(ierr); ierr = PetscDrawLGSetUseMarkers(lg,PETSC_TRUE);CHKERRQ(ierr); ierr = PetscDrawLGGetAxis(lg,&axis);CHKERRQ(ierr); ierr = PetscDrawAxisSetLabels(axis,NULL,"Number of GLL points","Log(Error Norm)");CHKERRQ(ierr); for (n=4; n<N; n+=2) { /* da contains the information about the parallel layout of the elements */ ierr = DMDACreate1d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,q*(n-1)+1,1,1,NULL,&da);CHKERRQ(ierr); ierr = DMSetFromOptions(da);CHKERRQ(ierr); ierr = DMSetUp(da);CHKERRQ(ierr); ierr = DMDAGetInfo(da,NULL,&q,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr); q = (q-1)/(n-1); /* number of spectral elements */ /* gll simply contains the GLL node and weight values */ ierr = PetscGLLCreate(n,PETSCGLL_VIA_LINEARALGEBRA,&gll);CHKERRQ(ierr); ierr = DMDASetGLLCoordinates(da,&gll);CHKERRQ(ierr); /* Creates the element stiffness matrix for the given gll */ ierr = PetscGLLElementLaplacianCreate(&gll,&A);CHKERRQ(ierr); /* Scale the element stiffness and weights by the size of the element */ h = 2.0/q; for (j=0; j<n; j++) { gll.weights[j] *= .5*h; for (l=0; l<n; l++) { A[j][l] = 2.*A[j][l]/h; } } /* Create the global stiffness matrix and add the element stiffness for each local element */ ierr = DMCreateMatrix(da,&K);CHKERRQ(ierr); ierr = MatSetOption(K,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); ierr = DMDAGetCorners(da,&xs,NULL,NULL,&xn,NULL,NULL);CHKERRQ(ierr); xs = xs/(n-1); xn = xn/(n-1); ierr = PetscMalloc1(n,&rows);CHKERRQ(ierr); /* loop over local elements */ for (j=xs; j<xs+xn; j++) { for (l=0; l<n; l++) rows[l] = j*(n-1)+l; ierr = MatSetValues(K,n,rows,n,rows,&A[0][0],ADD_VALUES);CHKERRQ(ierr); } ierr = MatAssemblyBegin(K,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(K,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatCreateVecs(K,&x,&b);CHKERRQ(ierr); ierr = ComputeRhs(da,&gll,b);CHKERRQ(ierr); /* Replace the first and last rows/columns of the matrix with the identity to obtain the zero Dirichlet boundary conditions */ rows[0] = 0; rows[1] = q*(n-1); ierr = MatZeroRowsColumns(K,2,rows,1.0,x,b);CHKERRQ(ierr); ierr = PetscFree(rows);CHKERRQ(ierr); ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr); ierr = KSPSetOperators(ksp,K,K);CHKERRQ(ierr); ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PCSetType(pc,PCLU);CHKERRQ(ierr); ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); ierr = KSPSolve(ksp,b,x);CHKERRQ(ierr); /* compute the error to the continium problem */ ierr = ComputeSolution(da,&gll,b);CHKERRQ(ierr); ierr = VecAXPY(x,-1.0,b);CHKERRQ(ierr); /* compute the L^2 norm of the error */ ierr = VecGetArray(x,&f);CHKERRQ(ierr); ierr = PetscGLLIntegrate(&gll,f,&norm);CHKERRQ(ierr); ierr = VecRestoreArray(x,&f);CHKERRQ(ierr); norm = PetscSqrtReal(norm); ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"L^2 norm of the error %D %g\n",n,(double)norm);CHKERRQ(ierr); if (n > 10 && norm > 1.e-8) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_PLIB,"Slower convergence than expected"); xc = (PetscReal)n; yc = PetscLog10Real(norm); ierr = PetscDrawLGAddPoint(lg,&xc,&yc);CHKERRQ(ierr); ierr = PetscDrawLGDraw(lg);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = KSPDestroy(&ksp);CHKERRQ(ierr); ierr = MatDestroy(&K);CHKERRQ(ierr); ierr = PetscGLLElementLaplacianDestroy(&gll,&A);CHKERRQ(ierr); ierr = PetscGLLDestroy(&gll);CHKERRQ(ierr); ierr = DMDestroy(&da);CHKERRQ(ierr); } ierr = PetscDrawLGDestroy(&lg);CHKERRQ(ierr); ierr = PetscDrawDestroy(&draw);CHKERRQ(ierr); ierr = PetscFinalize(); return ierr; }