nlopt_opt make_opt(const mxArray *opts, unsigned n)
{
     nlopt_opt opt = NULL, local_opt = NULL;
     nlopt_algorithm algorithm;
     double *tmp = NULL;
     unsigned i;

     algorithm = (nlopt_algorithm)
	  struct_val_default(opts, "algorithm", NLOPT_NUM_ALGORITHMS);
     CHECK1(((int)algorithm) >= 0 && algorithm < NLOPT_NUM_ALGORITHMS,
	    "invalid opt.algorithm");

     tmp = (double *) mxCalloc(n, sizeof(double));
     opt = nlopt_create(algorithm, n);
     CHECK1(opt, "nlopt: out of memory");

     nlopt_set_lower_bounds(opt, struct_arrval(opts, "lower_bounds", n,
					       fill(tmp, n, -HUGE_VAL)));
     nlopt_set_upper_bounds(opt, struct_arrval(opts, "upper_bounds", n,
					       fill(tmp, n, +HUGE_VAL)));

     nlopt_set_stopval(opt, struct_val_default(opts, "stopval", -HUGE_VAL));
     nlopt_set_ftol_rel(opt, struct_val_default(opts, "ftol_rel", 0.0));
     nlopt_set_ftol_abs(opt, struct_val_default(opts, "ftol_abs", 0.0));
     nlopt_set_xtol_rel(opt, struct_val_default(opts, "xtol_rel", 0.0));
     nlopt_set_xtol_abs(opt, struct_arrval(opts, "xtol_abs", n,
					   fill(tmp, n, 0.0)));
     nlopt_set_maxeval(opt, struct_val_default(opts, "maxeval", 0.0) < 0 ?
		       0 : struct_val_default(opts, "maxeval", 0.0));
     nlopt_set_maxtime(opt, struct_val_default(opts, "maxtime", 0.0));

     nlopt_set_population(opt, struct_val_default(opts, "population", 0));
     nlopt_set_vector_storage(opt, struct_val_default(opts, "vector_storage", 0));

     if (struct_arrval(opts, "initial_step", n, NULL))
	  nlopt_set_initial_step(opt,
				 struct_arrval(opts, "initial_step", n, NULL));
     
     if (mxGetField(opts, 0, "local_optimizer")) {
	  const mxArray *local_opts = mxGetField(opts, 0, "local_optimizer");
	  CHECK1(mxIsStruct(local_opts),
		 "opt.local_optimizer must be a structure");
	  CHECK1(local_opt = make_opt(local_opts, n),
		 "error initializing local optimizer");
	  nlopt_set_local_optimizer(opt, local_opt);
	  nlopt_destroy(local_opt); local_opt = NULL;
     }

     mxFree(tmp);
     return opt;
}
Ejemplo n.º 2
0
double Do_Geometry_Optimization(CMol *pMol)
{
	int i, nAtom, nDim, iPos, Return_Opt;
	double x[MAX_NUM_ATOM*3], x_Ini[MAX_NUM_ATOM], y_Ini[MAX_NUM_ATOM], z_Ini[MAX_NUM_ATOM], E_min=1.0E100;

//	pMol->Restrain_All_Torsions(1);

	nAtom = pMol->nAtom;
	nDim = 3*nAtom;

	// for a large molecule with many soft dihedrals, we prefer the optimizer in nlopt since it is around 8 times faster
	memcpy(x_Ini, pMol->x, sizeof(double)*nAtom);	// backup the structure
	memcpy(y_Ini, pMol->y, sizeof(double)*nAtom);
	memcpy(z_Ini, pMol->z, sizeof(double)*nAtom);

	opt_Geo = nlopt_create(NLOPT_LD_LBFGS, nDim);	// fast for non-polarizable model. Not applicable for drude model
	nlopt_set_min_objective(opt_Geo, func_Geo_Optimization, pMol);
	nlopt_set_ftol_rel(opt_Geo, 5E-12);

	for(i=0; i<nAtom; i++)	{	// to set up the initial parameters
		iPos = 3*i;
		x[iPos  ] = pMol->x[i];
		x[iPos+1] = pMol->y[i];
		x[iPos+2] = pMol->z[i];
	}
	Iter_Geo_Opt = 0;
	Return_Opt = nlopt_optimize(opt_Geo, x, &E_min);
	nlopt_destroy(opt_Geo);

	if( (Return_Opt == NLOPT_FTOL_REACHED) || (Return_Opt == NLOPT_SUCCESS) )	{	// success in optimization
		pMol->Restrain_All_Torsions(0);
		return (pMol->Cal_E(0));
	}
	else	{	// try FullGeometryOptimization_LBFGS()
		memcpy(pMol->x, x_Ini, sizeof(double)*nAtom);	// restore the structure
		memcpy(pMol->y, y_Ini, sizeof(double)*nAtom);
		memcpy(pMol->z, z_Ini, sizeof(double)*nAtom);
		
		pMol->FullGeometryOptimization_LBFGS_step(0);
		pMol->Restrain_All_Torsions(0);
		E_min = pMol->Cal_E(0);
		return E_min;
	}
}
Ejemplo n.º 3
0
double NLfit::run_method(vector<realt>* best_a)
{
    if (opt_ != NULL && na_ != (int) nlopt_get_dimension(opt_)) {
        nlopt_destroy(opt_);
        opt_ = NULL;
    }

    if (opt_ == NULL) {
        opt_ = nlopt_create(algorithm_, na_);
        nlopt_set_min_objective(opt_, calculate_for_nlopt, this);
    }

    // this is also handled in Fit::common_termination_criteria()
    nlopt_set_maxtime(opt_, F_->get_settings()->max_fitting_time);
    nlopt_set_maxeval(opt_, max_eval() - 1); // save 1 eval for final calc.
    nlopt_set_ftol_rel(opt_, F_->get_settings()->ftol_rel);
    nlopt_set_xtol_rel(opt_, F_->get_settings()->xtol_rel);

    double *lb = new double[na_];
    double *ub = new double[na_];
    for (int i = 0; i < na_; ++i) {
        const RealRange& d = F_->mgr.get_variable(i)->domain;
        lb[i] = d.lo;
        ub[i] = d.hi;
    }
    nlopt_set_lower_bounds(opt_, lb);
    nlopt_set_upper_bounds(opt_, ub);
    delete [] lb;
    delete [] ub;

    double opt_f;
    double *a = new double[na_];
    for (int i = 0; i < na_; ++i)
        a[i] = a_orig_[i];
    nlopt_result r = nlopt_optimize(opt_, a, &opt_f);
    F_->msg("NLopt says: " + S(nlresult_to_string(r)));
    best_a->assign(a, a+na_);
    delete [] a;
    return opt_f;
}
Ejemplo n.º 4
0
int main(int argc, char **argv)
{
  /* -------Initialize and Get the parameters from command line ------*/
  PetscInitialize(&argc, &argv, PETSC_NULL, PETSC_NULL);
  PetscPrintf(PETSC_COMM_WORLD,"--------Initializing------ \n");
  PetscErrorCode ierr;

  PetscBool flg;

  int myrank;
  MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
  if(myrank==0) 
    mma_verbose=1;
    
  /*-------------------------------------------------*/
  int Mx,My,Mz,Mzslab, Npmlx,Npmly,Npmlz,DegFree, anisotropic;

  PetscOptionsGetInt(PETSC_NULL,"-Nx",&Nx,&flg);  MyCheckAndOutputInt(flg,Nx,"Nx","Nx");
  PetscOptionsGetInt(PETSC_NULL,"-Ny",&Ny,&flg);  MyCheckAndOutputInt(flg,Ny,"Ny","Nx");
  PetscOptionsGetInt(PETSC_NULL,"-Nz",&Nz,&flg);  MyCheckAndOutputInt(flg,Nz,"Nz","Nz");
  PetscOptionsGetInt(PETSC_NULL,"-Mx",&Mx,&flg);  MyCheckAndOutputInt(flg,Mx,"Mx","Mx");
  PetscOptionsGetInt(PETSC_NULL,"-My",&My,&flg);  MyCheckAndOutputInt(flg,My,"My","My");
  PetscOptionsGetInt(PETSC_NULL,"-Mz",&Mz,&flg);  MyCheckAndOutputInt(flg,Mz,"Mz","Mz");
  PetscOptionsGetInt(PETSC_NULL,"-Mzslab",&Mzslab,&flg);  MyCheckAndOutputInt(flg,Mzslab,"Mzslab","Mzslab");
  PetscOptionsGetInt(PETSC_NULL,"-Npmlx",&Npmlx,&flg);  MyCheckAndOutputInt(flg,Npmlx,"Npmlx","Npmlx");
  PetscOptionsGetInt(PETSC_NULL,"-Npmly",&Npmly,&flg);  MyCheckAndOutputInt(flg,Npmly,"Npmly","Npmly");
  PetscOptionsGetInt(PETSC_NULL,"-Npmlz",&Npmlz,&flg);  MyCheckAndOutputInt(flg,Npmlz,"Npmlz","Npmlz");

  Nxyz = Nx*Ny*Nz;

  // if anisotropic !=0, Degree of Freedom = 3*Mx*My*Mz; else DegFree = Mx*My*Mz;
  PetscOptionsGetInt(PETSC_NULL,"-anisotropic",&anisotropic,&flg);
  if(!flg) anisotropic = 0; // by default, it is isotropc.
  DegFree = (anisotropic ? 3 : 1 )*Mx*My*((Mzslab==0)?Mz:1); 
  PetscPrintf(PETSC_COMM_WORLD," the Degree of Freedoms is %d \n ", DegFree);
  
  int DegFreeAll=DegFree+1;
  PetscPrintf(PETSC_COMM_WORLD," the Degree of Freedoms ALL is %d \n ", DegFreeAll);

  int BCPeriod, Jdirection, Jdirectiontwo, LowerPML;
  int bx[2], by[2], bz[2];
  PetscOptionsGetInt(PETSC_NULL,"-BCPeriod",&BCPeriod,&flg);  MyCheckAndOutputInt(flg,BCPeriod,"BCPeriod","BCPeriod given");
  PetscOptionsGetInt(PETSC_NULL,"-Jdirection",&Jdirection,&flg);  MyCheckAndOutputInt(flg,Jdirection,"Jdirection","Diapole current direction");
  PetscOptionsGetInt(PETSC_NULL,"-Jdirectiontwo",&Jdirectiontwo,&flg);  MyCheckAndOutputInt(flg,Jdirectiontwo,"Jdirectiontwo","Diapole current direction for source two");
  PetscOptionsGetInt(PETSC_NULL,"-LowerPML",&LowerPML,&flg);  MyCheckAndOutputInt(flg,LowerPML,"LowerPML","PML in the lower xyz boundary");
  PetscOptionsGetInt(PETSC_NULL,"-bxl",bx,&flg);  MyCheckAndOutputInt(flg,bx[0],"bxl","BC at x lower");
  PetscOptionsGetInt(PETSC_NULL,"-bxu",bx+1,&flg);  MyCheckAndOutputInt(flg,bx[1],"bxu","BC at x upper");
  PetscOptionsGetInt(PETSC_NULL,"-byl",by,&flg);  MyCheckAndOutputInt(flg,by[0],"byl","BC at y lower");
  PetscOptionsGetInt(PETSC_NULL,"-byu",by+1,&flg);  MyCheckAndOutputInt(flg,by[1],"byu","BC at y upper");
  PetscOptionsGetInt(PETSC_NULL,"-bzl",bz,&flg);  MyCheckAndOutputInt(flg,bz[0],"bzl","BC at z lower");
  PetscOptionsGetInt(PETSC_NULL,"-bzu",bz+1,&flg);  MyCheckAndOutputInt(flg,bz[1],"bzu","BC at z upper");


  double  epssub, RRT, sigmax, sigmay, sigmaz ;
   
  PetscOptionsGetReal(PETSC_NULL,"-hx",&hx,&flg);  MyCheckAndOutputDouble(flg,hx,"hx","hx");
  hy = hx;
  hz = hx;
  hxyz = (Nz==1)*hx*hy + (Nz>1)*hx*hy*hz;  

  double omega, omegaone, omegatwo, wratio;
  PetscOptionsGetReal(PETSC_NULL,"-omega",&omega,&flg);  MyCheckAndOutputDouble(flg,omega,"omega","omega");
   PetscOptionsGetReal(PETSC_NULL,"-wratio",&wratio,&flg);  MyCheckAndOutputDouble(flg,wratio,"wratio","wratio");
  omegaone=omega;
  omegatwo=wratio*omega;
  PetscPrintf(PETSC_COMM_WORLD,"---omegaone is %.16e and omegatwo is %.16e ---\n",omegaone, omegatwo);

  PetscOptionsGetReal(PETSC_NULL,"-Qabs",&Qabs,&flg); 
  if (flg && Qabs>1e+15)
    Qabs=1.0/0.0;
  MyCheckAndOutputDouble(flg,Qabs,"Qabs","Qabs");
  PetscOptionsGetReal(PETSC_NULL,"-epsair",&epsair,&flg);  MyCheckAndOutputDouble(flg,epsair,"epsair","epsair");
  PetscOptionsGetReal(PETSC_NULL,"-epssub",&epssub,&flg);  MyCheckAndOutputDouble(flg,epssub,"epssub","epssub");
  PetscOptionsGetReal(PETSC_NULL,"-RRT",&RRT,&flg);  MyCheckAndOutputDouble(flg,RRT,"RRT","RRT given");
  sigmax = pmlsigma(RRT,Npmlx*hx);
  sigmay = pmlsigma(RRT,Npmly*hy);
  sigmaz = pmlsigma(RRT,Npmlz*hz);  
  PetscPrintf(PETSC_COMM_WORLD,"----sigmax is %.12e \n",sigmax);
  PetscPrintf(PETSC_COMM_WORLD,"----sigmay is %.12e \n",sigmay);
  PetscPrintf(PETSC_COMM_WORLD,"----sigmaz is %.12e \n",sigmaz);

  char initialdata[PETSC_MAX_PATH_LEN]; //filenameComm[PETSC_MAX_PATH_LEN];
  PetscOptionsGetString(PETSC_NULL,"-initialdata",initialdata,PETSC_MAX_PATH_LEN,&flg); MyCheckAndOutputChar(flg,initialdata,"initialdata","Inputdata file");
  PetscOptionsGetString(PETSC_NULL,"-filenameComm",filenameComm,PETSC_MAX_PATH_LEN,&flg); MyCheckAndOutputChar(flg,filenameComm,"filenameComm","Output filenameComm");


  // add cx, cy, cz to indicate where the diapole current is;

  int cx, cy, cz;
  PetscOptionsGetInt(PETSC_NULL,"-cx",&cx,&flg); 
  if (!flg)
    {cx=(LowerPML)*floor(Nx/2); PetscPrintf(PETSC_COMM_WORLD,"cx is %d by default \n",cx);}
  else
    {PetscPrintf(PETSC_COMM_WORLD,"the current poisiont cx is %d \n",cx);}
  

  PetscOptionsGetInt(PETSC_NULL,"-cy",&cy,&flg); 
  if (!flg)
    {cy=(LowerPML)*floor(Ny/2); PetscPrintf(PETSC_COMM_WORLD,"cy is %d by default \n",cy);}
 else
    {PetscPrintf(PETSC_COMM_WORLD,"the current poisiont cy is %d \n",cy);}
  

  PetscOptionsGetInt(PETSC_NULL,"-cz",&cz,&flg); 
  if (!flg)
    {cz=(LowerPML)*floor(Nz/2); PetscPrintf(PETSC_COMM_WORLD,"cz is %d by default \n",cz);}
  else
    {PetscPrintf(PETSC_COMM_WORLD,"the current poisiont cz is %d \n",cz);}
    
  posj = (cx*Ny+ cy)*Nz + cz;
  PetscPrintf(PETSC_COMM_WORLD,"the posj is %d \n. ", posj);

  int fixpteps;
  PetscOptionsGetInt(PETSC_NULL,"-fixpteps",&fixpteps,&flg);  MyCheckAndOutputInt(flg,fixpteps,"fixpteps","fixpteps");

  // Get minapproach;
  PetscOptionsGetInt(PETSC_NULL,"-minapproach",&minapproach,&flg);  MyCheckAndOutputInt(flg,minapproach,"minapproach","minapproach");
   
  // Get withepsinldos;
  PetscOptionsGetInt(PETSC_NULL,"-withepsinldos",&withepsinldos,&flg);  MyCheckAndOutputInt(flg,withepsinldos,"withepsinldos","withepsinldos");
  
  // Get outputbase;
  PetscOptionsGetInt(PETSC_NULL,"-outputbase",&outputbase,&flg);  MyCheckAndOutputInt(flg,outputbase,"outputbase","outputbase");
  // Get cavityverbose;
  PetscOptionsGetInt(PETSC_NULL,"-cavityverbose",&cavityverbose,&flg);
  if(!flg) cavityverbose=0;
  PetscPrintf(PETSC_COMM_WORLD,"the cavity verbose is set as %d \n", cavityverbose); 
  // Get refinedldos;
  PetscOptionsGetInt(PETSC_NULL,"-refinedldos",&refinedldos,&flg);
  if(!flg) refinedldos=0;
  PetscPrintf(PETSC_COMM_WORLD,"the refinedldos is set as %d \n", refinedldos);
  // Get cmpwrhs;
  int cmpwrhs;
   PetscOptionsGetInt(PETSC_NULL,"-cmpwrhs",&cmpwrhs,&flg);
  if(!flg) cmpwrhs=0;
  PetscPrintf(PETSC_COMM_WORLD,"the cmpwrhs is set as %d \n", cmpwrhs);
  // Get lrzsqr;
   PetscOptionsGetInt(PETSC_NULL,"-lrzsqr",&lrzsqr,&flg);
  if(!flg) lrzsqr=0;
  PetscPrintf(PETSC_COMM_WORLD,"the lrzsqr is set as %d \n", lrzsqr);
  // Get newQdef;
   PetscOptionsGetInt(PETSC_NULL,"-newQdef",&newQdef,&flg);
  if(!flg) newQdef=0;
  PetscPrintf(PETSC_COMM_WORLD,"the newQdef is set as %d \n", newQdef);
  /*--------------------------------------------------------*/

  /*--------------------------------------------------------*/


  /*---------- Set the current source---------*/
  //Mat D; //ImaginaryIMatrix;
  ImagIMat(PETSC_COMM_WORLD, &D,6*Nxyz);

  Vec J;
  ierr = VecCreateMPI(PETSC_COMM_WORLD, PETSC_DECIDE, 6*Nxyz, &J);CHKERRQ(ierr);
  ierr = PetscObjectSetName((PetscObject) J, "Source");CHKERRQ(ierr);
  VecSet(J,0.0); //initialization;

  if (Jdirection == 1)
    SourceSingleSetX(PETSC_COMM_WORLD, J, Nx, Ny, Nz, cx, cy, cz,1.0/hxyz);
  else if (Jdirection ==2)
    SourceSingleSetY(PETSC_COMM_WORLD, J, Nx, Ny, Nz, cx, cy, cz,1.0/hxyz);
  else if (Jdirection == 3)
    SourceSingleSetZ(PETSC_COMM_WORLD, J, Nx, Ny, Nz, cx, cy, cz,1.0/hxyz);
  else
    PetscPrintf(PETSC_COMM_WORLD," Please specify correct direction of current: x (1) , y (2) or z (3)\n "); 

  Vec Jtwo;
  ierr = VecDuplicate(J, &Jtwo);CHKERRQ(ierr);
  ierr = PetscObjectSetName((PetscObject) Jtwo, "Sourcetwo");CHKERRQ(ierr);
  VecSet(Jtwo,0.0); //initialization;

  if (Jdirectiontwo == 1)
    SourceSingleSetX(PETSC_COMM_WORLD, Jtwo, Nx, Ny, Nz, cx, cy, cz,1.0/hxyz);
  else if (Jdirectiontwo ==2)
    SourceSingleSetY(PETSC_COMM_WORLD, Jtwo, Nx, Ny, Nz, cx, cy, cz,1.0/hxyz);
  else if (Jdirectiontwo == 3)
    SourceSingleSetZ(PETSC_COMM_WORLD, Jtwo, Nx, Ny, Nz, cx, cy, cz,1.0/hxyz);
  else
    PetscPrintf(PETSC_COMM_WORLD," Please specify correct direction of current two: x (1) , y (2) or z (3)\n "); 


  //Vec b; // b= i*omega*J;
  Vec bone, btwo;

  ierr = VecDuplicate(J,&b);CHKERRQ(ierr);
  ierr = PetscObjectSetName((PetscObject) b, "rhsone");CHKERRQ(ierr);

  ierr = VecDuplicate(J,&bone);CHKERRQ(ierr);
  ierr = PetscObjectSetName((PetscObject) bone, "rhsone");CHKERRQ(ierr);

  ierr = VecDuplicate(Jtwo,&btwo);CHKERRQ(ierr);
  ierr = PetscObjectSetName((PetscObject) btwo, "rhstwo");CHKERRQ(ierr);

  if (cmpwrhs==0)
    {
      ierr = MatMult(D,J,b);CHKERRQ(ierr);
      ierr = MatMult(D,Jtwo,btwo);CHKERRQ(ierr);
      
      VecCopy(b,bone);
      VecScale(bone,omegaone);

      VecScale(btwo,omegatwo);

      VecScale(b,omega);      
    }
  else
    {
      double complex cmpiomega;
      cmpiomega = cpow(1+I/Qabs,newQdef+1);
      double sqrtiomegaR = -omega*cimag(csqrt(cmpiomega));
      double sqrtiomegaI = omega*creal(csqrt(cmpiomega));
      PetscPrintf(PETSC_COMM_WORLD,"the real part of sqrt cmpomega is %g and imag sqrt is % g ", sqrtiomegaR, sqrtiomegaI);
      Vec tmpi;
      ierr = VecDuplicate(J,&tmpi);
      VecSet(b,0.0);
      VecSet(tmpi,0.0);
      CmpVecScale(J,b,sqrtiomegaR,sqrtiomegaI,D,tmpi);
      VecDestroy(&tmpi);
    }

  /*-------Get the weight vector ------------------*/
  //Vec weight;
  ierr = VecDuplicate(J,&weight); CHKERRQ(ierr);
  ierr = PetscObjectSetName((PetscObject) weight, "weight");CHKERRQ(ierr);

  if(LowerPML==0)
    GetWeightVec(weight, Nx, Ny,Nz); // new code handles both 3D and 2D;
  else
    VecSet(weight,1.0);

  Vec weightedJ;
  ierr = VecDuplicate(J,&weightedJ); CHKERRQ(ierr);
  ierr = VecPointwiseMult(weightedJ,J,weight);
  ierr = PetscObjectSetName((PetscObject) weightedJ, "weightedJ");CHKERRQ(ierr);

  Vec weightedJtwo;
  ierr = VecDuplicate(Jtwo,&weightedJtwo); CHKERRQ(ierr);
  ierr = VecPointwiseMult(weightedJtwo,Jtwo,weight);
  ierr = PetscObjectSetName((PetscObject) weightedJtwo, "weightedJtwo");CHKERRQ(ierr);

  //Vec vR;
  ierr = VecDuplicate(J,&vR); CHKERRQ(ierr);
  GetRealPartVec(vR, 6*Nxyz);

  // VecFReal;
  if (lrzsqr)
    { ierr = VecDuplicate(J,&epsFReal); CHKERRQ(ierr); 
      ierr = PetscObjectSetName((PetscObject) epsFReal, "epsFReal");CHKERRQ(ierr);

      if (newQdef==0)
	{
	  sqrtomegaI = omega*cimag(csqrt(1+I/Qabs));
	  PetscPrintf(PETSC_COMM_WORLD,"the real part of sqrt cmpomega is %g and imag sqrt is % g ", omega*creal(csqrt(1+I/Qabs)), sqrtomegaI);
	  betar = 2*sqrtomegaI;
	  betai = betar/Qabs;
	}
      else
	{
	  double gamma;
	  gamma = omega/Qabs;
	  betar = 2*gamma*(1-1.0/pow(Qabs,2));
	  betai = 2*gamma*(2.0/Qabs);
	}

      ierr = VecDuplicate(J,&nb); CHKERRQ(ierr);
      ierr = PetscObjectSetName((PetscObject) nb, "nb"); CHKERRQ(ierr);
      
      ierr = VecDuplicate(J,&y); CHKERRQ(ierr);
      ierr = PetscObjectSetName((PetscObject) y, "y"); CHKERRQ(ierr);
      
      ierr = VecDuplicate(J,&xsqr); CHKERRQ(ierr); // xsqr = x*x;
      ierr = PetscObjectSetName((PetscObject) xsqr, "xsqr"); CHKERRQ(ierr);
      CongMat(PETSC_COMM_WORLD, &C, 6*Nxyz);
}
  /*----------- Define PML muinv vectors  */
 
  Vec muinvpml;
  MuinvPMLFull(PETSC_COMM_SELF, &muinvpml,Nx,Ny,Nz,Npmlx,Npmly,Npmlz,sigmax,sigmay,sigmaz,omega, LowerPML); 

  //double *muinv;
  muinv = (double *) malloc(sizeof(double)*6*Nxyz);
  int add=0;
  AddMuAbsorption(muinv,muinvpml,Qabs,add);
  ierr = VecDestroy(&muinvpml); CHKERRQ(ierr);  

  /*---------- Define PML eps vectors: epspml---------- */  
  Vec epspml; //epspmlQ, epscoef;
  ierr = VecDuplicate(J,&epspml);CHKERRQ(ierr);
  ierr = PetscObjectSetName((PetscObject) epspml,"EpsPMLFull"); CHKERRQ(ierr);
  EpsPMLFull(PETSC_COMM_WORLD, epspml,Nx,Ny,Nz,Npmlx,Npmly,Npmlz,sigmax,sigmay,sigmaz,omega, LowerPML);

  ierr = VecDuplicate(J,&epspmlQ);CHKERRQ(ierr);


  Vec epscoefone, epscoeftwo;
  ierr = VecDuplicate(J,&epscoefone);CHKERRQ(ierr);
  ierr = VecDuplicate(J,&epscoeftwo);CHKERRQ(ierr);
 
  // compute epspmlQ,epscoef;
  EpsCombine(D, weight, epspml, epspmlQ, epscoefone, Qabs, omegaone);
  EpsCombine(D, weight, epspml, epspmlQ, epscoeftwo, Qabs, omegatwo);
  /*--------- Setup the interp matrix ----------------------- */
  /* for a samll eps block, interp it into yee-lattice. The interp matrix A and PML epspml only need to generated once;*/
  

  //Mat A; 
  //new routine for myinterp;
  myinterp(PETSC_COMM_WORLD, &A, Nx,Ny,Nz, LowerPML*floor((Nx-Mx)/2),LowerPML*floor((Ny-My)/2),LowerPML*floor((Nz-Mz)/2), Mx,My,Mz,Mzslab, anisotropic); // LoweerPML*Npmlx,..,.., specify where the interp starts;  

  //Vec epsSReal, epsgrad, vgrad; // create compatiable vectors with A.
  ierr = MatGetVecs(A,&epsSReal, &epsgrad); CHKERRQ(ierr);  
  ierr = PetscObjectSetName((PetscObject) epsgrad, "epsgrad");CHKERRQ(ierr);
  ierr = VecDuplicate(epsSReal, &vgrad); CHKERRQ(ierr);
  ierr = PetscObjectSetName((PetscObject) epsSReal, "epsSReal");CHKERRQ(ierr);
  ierr = PetscObjectSetName((PetscObject) vgrad, "vgrad");CHKERRQ(ierr);
  
  /*---------Setup the epsmedium vector----------------*/
  //Vec epsmedium;
  ierr = VecDuplicate(J,&epsmedium); CHKERRQ(ierr);
  GetMediumVec(epsmedium,Nz,Mz,epsair,epssub);
 
  /*--------- Setup the finitie difference matrix-------------*/
  //Mat M;
  MoperatorGeneral(PETSC_COMM_WORLD, &M, Nx,Ny,Nz,hx,hy,hz, bx, by, bz,muinv,BCPeriod);
  free(muinv);

  /*--------Setup the KSP variables ---------------*/
  
  KSP kspone;
  PC pcone; 
  ierr = KSPCreate(PETSC_COMM_WORLD,&kspone);CHKERRQ(ierr);
  //ierr = KSPSetType(ksp, KSPPREONLY);CHKERRQ(ierr);
  ierr = KSPSetType(kspone, KSPGMRES);CHKERRQ(ierr);
  ierr = KSPGetPC(kspone,&pcone);CHKERRQ(ierr);
  ierr = PCSetType(pcone,PCLU);CHKERRQ(ierr);
  ierr = PCFactorSetMatSolverPackage(pcone,MATSOLVERPASTIX);CHKERRQ(ierr);
  ierr = PCSetFromOptions(pcone);
  int maxkspit = 20;
  ierr = KSPSetTolerances(kspone,1e-14,PETSC_DEFAULT,PETSC_DEFAULT,maxkspit);CHKERRQ(ierr);
  ierr = KSPSetFromOptions(kspone);CHKERRQ(ierr);

  KSP ksptwo;
  PC pctwo;
   ierr = KSPCreate(PETSC_COMM_WORLD,&ksptwo);CHKERRQ(ierr);
  //ierr = KSPSetType(ksp, KSPPREONLY);CHKERRQ(ierr);
  ierr = KSPSetType(ksptwo, KSPGMRES);CHKERRQ(ierr);
  ierr = KSPGetPC(ksptwo,&pctwo);CHKERRQ(ierr);
  ierr = PCSetType(pctwo,PCLU);CHKERRQ(ierr);
  ierr = PCFactorSetMatSolverPackage(pctwo,MATSOLVERPASTIX);CHKERRQ(ierr);
  ierr = PCSetFromOptions(pctwo);
  ierr = KSPSetTolerances(ksptwo,1e-14,PETSC_DEFAULT,PETSC_DEFAULT,maxkspit);CHKERRQ(ierr);
  ierr = KSPSetFromOptions(ksptwo);CHKERRQ(ierr);

  /*--------- Create the space for solution vector -------------*/
  //Vec x;
  ierr = VecDuplicate(J,&x);CHKERRQ(ierr);
  ierr = PetscObjectSetName((PetscObject) x, "Solution");CHKERRQ(ierr); 
  
  /*----------- Create the space for final eps -------------*/

  //Vec epsC, epsCi, epsP;
  ierr = VecDuplicate(J,&epsC);CHKERRQ(ierr);
  ierr = PetscObjectSetName((PetscObject) epsC, "EpsC");CHKERRQ(ierr);
  ierr = VecDuplicate(J,&epsCi);CHKERRQ(ierr);
  ierr = VecDuplicate(J,&epsP);CHKERRQ(ierr);

  ierr = VecSet(epsP,0.0); CHKERRQ(ierr);
  ierr = VecAssemblyBegin(epsP); CHKERRQ(ierr);
  ierr = VecAssemblyEnd(epsP); CHKERRQ(ierr); 

  /*------------ Create space used in the solver ------------*/
  //Vec vgradlocal,tmp, tmpa,tmpb;
  ierr = VecCreateSeq(PETSC_COMM_SELF, DegFree, &vgradlocal); CHKERRQ(ierr);
  ierr = VecDuplicate(J,&tmp); CHKERRQ(ierr);
  ierr = VecDuplicate(J,&tmpa); CHKERRQ(ierr);
  ierr = VecDuplicate(J,&tmpb); CHKERRQ(ierr);
 
  // Vec pickposvec; this vector is zero except that first entry is one;
  if (withepsinldos)
    { ierr = VecDuplicate(J,&pickposvec); CHKERRQ(ierr);
      ierr = VecSet(pickposvec,0.0); CHKERRQ(ierr);
      ierr = VecSetValue(pickposvec,posj+Jdirection*Nxyz,1.0,INSERT_VALUES);
      VecAssemblyBegin(pickposvec);
      VecAssemblyEnd(pickposvec);
    }
  /*------------ Create scatter used in the solver -----------*/
  //VecScatter scatter;
  //IS from, to;
  ierr =ISCreateStride(PETSC_COMM_SELF,DegFree,0,1,&from); CHKERRQ(ierr);
  ierr =ISCreateStride(PETSC_COMM_SELF,DegFree,0,1,&to); CHKERRQ(ierr);

  /*-------------Read the input file -------------------------*/

  double *epsoptAll;
  epsoptAll = (double *) malloc(DegFreeAll*sizeof(double));

  FILE *ptf;
  ptf = fopen(initialdata,"r");
  PetscPrintf(PETSC_COMM_WORLD,"reading from input files \n");

  int i;
  // set the dielectric at the center is fixed, and alwyas high
  //epsopt[0]=myub; is defined below near lb and ub;
  for (i=0;i<DegFree;i++)
    { //PetscPrintf(PETSC_COMM_WORLD,"current eps reading is %lf \n",epsopt[i]);
      fscanf(ptf,"%lf",&epsoptAll[i]);
    }
  epsoptAll[DegFreeAll-1]=0; //initialize auxiliary variable;
  fclose(ptf);



  /*----declare these data types, althought they may not be used for job 2 -----------------*/
 
  double mylb,myub, *lb=NULL, *ub=NULL;
  int maxeval, maxtime, mynloptalg;
  double maxf;
  nlopt_opt  opt;
  nlopt_result result;
  /*--------------------------------------------------------------*/
  /*----Now based on Command Line, Do the corresponding job----*/
  /*----------------------------------------------------------------*/


  //int Job; set Job to be gloabl variables;
  PetscOptionsGetInt(PETSC_NULL,"-Job",&Job,&flg);  MyCheckAndOutputInt(flg,Job,"Job","The Job indicator you set");
  
  int numofvar=(Job==1)*DegFreeAll + (Job==3);

  /*--------   convert the epsopt array to epsSReal (if job!=optmization) --------*/
  if (Job==2 || Job ==3)
    {
      // copy epsilon from file to epsSReal; (different from FindOpt.c, because epsilon is not degree-of-freedoms in computeQ.
      // i) create a array to read file (done above in epsopt); ii) convert the array to epsSReal;
      int ns, ne;
      ierr = VecGetOwnershipRange(epsSReal,&ns,&ne);
      for(i=ns;i<ne;i++)
	{ ierr=VecSetValue(epsSReal,i,epsoptAll[i],INSERT_VALUES); 
	  CHKERRQ(ierr); }      
      if(withepsinldos)
	{ epsatinterest = epsoptAll[cx*Ny*Nz + cy*Nz + cz]  + epsair;
	  PetscPrintf(PETSC_COMM_WORLD, " the relative permitivity at the point of current is %.16e \n ",epsatinterest);}
      ierr = VecAssemblyBegin(epsSReal); CHKERRQ(ierr);
      ierr = VecAssemblyEnd(epsSReal);  CHKERRQ(ierr);
    }

  if (Job==1 || Job==3)  // optimization bounds setup;
    {      
      PetscOptionsGetInt(PETSC_NULL,"-maxeval",&maxeval,&flg);  MyCheckAndOutputInt(flg,maxeval,"maxeval","max number of evaluation");
      PetscOptionsGetInt(PETSC_NULL,"-maxtime",&maxtime,&flg);  MyCheckAndOutputInt(flg,maxtime,"maxtime","max time of evaluation");
      PetscOptionsGetInt(PETSC_NULL,"-mynloptalg",&mynloptalg,&flg);  MyCheckAndOutputInt(flg,mynloptalg,"mynloptalg","The algorithm used ");

      PetscOptionsGetReal(PETSC_NULL,"-mylb",&mylb,&flg);  MyCheckAndOutputDouble(flg,mylb,"mylb","optimization lb");
      PetscOptionsGetReal(PETSC_NULL,"-myub",&myub,&flg);  MyCheckAndOutputDouble(flg,myub,"myub","optimization ub");

      
 
      lb = (double *) malloc(numofvar*sizeof(double));
      ub = (double *) malloc(numofvar*sizeof(double));

      // the dielectric constant at center is fixed!
      for(i=0;i<numofvar;i++)
	{
	  lb[i] = mylb;
	  ub[i] = myub;
	}  //initial guess, lower bounds, upper bounds;

      // set lower and upper bounds for auxiliary variable;
      lb[numofvar-1]=0;
      ub[numofvar-1]=1.0/0.0;

      //fix the dielectric at the center to be high for topology optimization;
      if (Job==1 && fixpteps==1)
	{
	  epsoptAll[0]=myub;
	  lb[0]=myub;
	  ub[0]=myub;
	}



      opt = nlopt_create(mynloptalg, numofvar);
      
      myfundatatypeshg data[2] = {{omegaone, bone, weightedJ, epscoefone,kspone},{omegatwo, btwo, weightedJtwo, epscoeftwo,ksptwo}};

      nlopt_add_inequality_constraint(opt,ldosconstraint, &data[0], 1e-8);
      nlopt_add_inequality_constraint(opt,ldosconstraint, &data[1], 1e-8);

      nlopt_set_lower_bounds(opt,lb);
      nlopt_set_upper_bounds(opt,ub);
      nlopt_set_maxeval(opt,maxeval);
      nlopt_set_maxtime(opt,maxtime);


      /*add functionality to choose local optimizer; */
      int mynloptlocalalg;
      nlopt_opt local_opt;
      PetscOptionsGetInt(PETSC_NULL,"-mynloptlocalalg",&mynloptlocalalg,&flg);  MyCheckAndOutputInt(flg,mynloptlocalalg,"mynloptlocalalg","The local optimization algorithm used ");
      if (mynloptlocalalg)
	{ 
	  local_opt=nlopt_create(mynloptlocalalg,numofvar);
	  nlopt_set_ftol_rel(local_opt, 1e-14);
	  nlopt_set_maxeval(local_opt,100000);
	  nlopt_set_local_optimizer(opt,local_opt);
	}
    }

  switch (Job)
    {
    case 1:
      {
	if (minapproach)
	  nlopt_set_min_objective(opt,maxminobjfun,NULL);// NULL: no data to be passed because of global variables;
	else
	  nlopt_set_max_objective(opt,maxminobjfun,NULL);

	result = nlopt_optimize(opt,epsoptAll,&maxf);
      }      
      break;
    case 2 :  //AnalyzeStructure
      { 
	int Linear, Eig, maxeigit;
	PetscOptionsGetInt(PETSC_NULL,"-Linear",&Linear,&flg);  MyCheckAndOutputInt(flg,Linear,"Linear","Linear solver indicator");
	PetscOptionsGetInt(PETSC_NULL,"-Eig",&Eig,&flg);  MyCheckAndOutputInt(flg,Eig,"Eig","Eig solver indicator");
	PetscOptionsGetInt(PETSC_NULL,"-maxeigit",&maxeigit,&flg);  MyCheckAndOutputInt(flg,maxeigit,"maxeigit","maximum number of Eig solver iterations is");

	/*----------------------------------*/
	//EigenSolver(Linear, Eig, maxeigit);
	/*----------------------------------*/

	OutputVec(PETSC_COMM_WORLD, weight,filenameComm, "weight.m");
      }
      break;   
    default:
      PetscPrintf(PETSC_COMM_WORLD,"--------Interesting! You're doing nothing!--------\n ");
 }


  if(Job==1 || Job==3)
    {
      /* print the optimization parameters */
#if 0
      double xrel, frel, fabs;
      // double *xabs;
      frel=nlopt_get_ftol_rel(opt);
      fabs=nlopt_get_ftol_abs(opt);
      xrel=nlopt_get_xtol_rel(opt);
      PetscPrintf(PETSC_COMM_WORLD,"nlopt frel is %g \n",frel);
      PetscPrintf(PETSC_COMM_WORLD,"nlopt fabs is %g \n",fabs);
      PetscPrintf(PETSC_COMM_WORLD,"nlopt xrel is %g \n",xrel);
      //nlopt_result nlopt_get_xtol_abs(const nlopt_opt opt, double *tol);
#endif
      /*--------------*/

      if (result < 0) {
	PetscPrintf(PETSC_COMM_WORLD,"nlopt failed! \n", result);
      }
      else {
	PetscPrintf(PETSC_COMM_WORLD,"found extremum  %0.16e\n", minapproach?1.0/maxf:maxf); 
      }

      PetscPrintf(PETSC_COMM_WORLD,"nlopt returned value is %d \n", result);


      if(Job==1)
	{ //OutputVec(PETSC_COMM_WORLD, epsopt,filenameComm, "epsopt.m");
	  //OutputVec(PETSC_COMM_WORLD, epsgrad,filenameComm, "epsgrad.m");
	  //OutputVec(PETSC_COMM_WORLD, vgrad,filenameComm, "vgrad.m");
	  //OutputVec(PETSC_COMM_WORLD, x,filenameComm, "x.m");
	  int rankA;
	  MPI_Comm_rank(PETSC_COMM_WORLD, &rankA);

	  if(rankA==0)
	    {
	      ptf = fopen(strcat(filenameComm,"epsopt.txt"),"w");
	      for (i=0;i<DegFree;i++)
		fprintf(ptf,"%0.16e \n",epsoptAll[i]);
	      fclose(ptf);
	      PetscPrintf(PETSC_COMM_WORLD,"the t parameter is %.8e \n",epsoptAll[DegFreeAll-1]);
	    }  
	}

      nlopt_destroy(opt);
    }
     


  ierr = PetscPrintf(PETSC_COMM_WORLD,"--------Done!--------\n ");CHKERRQ(ierr);

  /*------------------------------------*/
 

  /* ----------------------Destroy Vecs and Mats----------------------------*/ 

  free(epsoptAll);
  free(lb);
  free(ub);
  ierr = VecDestroy(&J); CHKERRQ(ierr);
  ierr = VecDestroy(&b); CHKERRQ(ierr);
  ierr = VecDestroy(&weight); CHKERRQ(ierr);
  ierr = VecDestroy(&weightedJ); CHKERRQ(ierr);
  ierr = VecDestroy(&vR); CHKERRQ(ierr);
  ierr = VecDestroy(&epspml); CHKERRQ(ierr);
  ierr = VecDestroy(&epspmlQ); CHKERRQ(ierr);
  ierr = VecDestroy(&epsSReal); CHKERRQ(ierr);
  ierr = VecDestroy(&epsgrad); CHKERRQ(ierr);
  ierr = VecDestroy(&vgrad); CHKERRQ(ierr);  
  ierr = VecDestroy(&epsmedium); CHKERRQ(ierr);
  ierr = VecDestroy(&epsC); CHKERRQ(ierr);
  ierr = VecDestroy(&epsCi); CHKERRQ(ierr);
  ierr = VecDestroy(&epsP); CHKERRQ(ierr);
  ierr = VecDestroy(&x); CHKERRQ(ierr);
  ierr = VecDestroy(&vgradlocal);CHKERRQ(ierr);
  ierr = VecDestroy(&tmp); CHKERRQ(ierr);
  ierr = VecDestroy(&tmpa); CHKERRQ(ierr);
  ierr = VecDestroy(&tmpb); CHKERRQ(ierr);
  ierr = MatDestroy(&A); CHKERRQ(ierr);  
  ierr = MatDestroy(&D); CHKERRQ(ierr);
  ierr = MatDestroy(&M); CHKERRQ(ierr);  
 

  ierr = VecDestroy(&epscoefone); CHKERRQ(ierr);
  ierr = VecDestroy(&epscoeftwo); CHKERRQ(ierr);
  ierr = KSPDestroy(&kspone);CHKERRQ(ierr);
  ierr = KSPDestroy(&ksptwo);CHKERRQ(ierr);

  ISDestroy(&from);
  ISDestroy(&to);

  if (withepsinldos)
    {ierr=VecDestroy(&pickposvec); CHKERRQ(ierr);}

  if (lrzsqr)
    {
      ierr=VecDestroy(&epsFReal); CHKERRQ(ierr);
      ierr=VecDestroy(&xsqr); CHKERRQ(ierr);
      ierr=VecDestroy(&y); CHKERRQ(ierr);
      ierr=VecDestroy(&nb); CHKERRQ(ierr);
      ierr=MatDestroy(&C); CHKERRQ(ierr);
    }

  ierr = VecDestroy(&bone); CHKERRQ(ierr);
  ierr = VecDestroy(&btwo); CHKERRQ(ierr);
  ierr = VecDestroy(&Jtwo); CHKERRQ(ierr);
  

  /*------------ finalize the program -------------*/

  {
    int rank;
    MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
    //if (rank == 0) fgetc(stdin);
    MPI_Barrier(PETSC_COMM_WORLD);
  }
  
  ierr = PetscFinalize(); CHKERRQ(ierr);

  return 0;
}
Ejemplo n.º 5
0
nlopt_result
NLOPT_STDCALL nlopt_minimize_econstrained(
     nlopt_algorithm algorithm,
     int n, nlopt_func_old f, void *f_data,
     int m, nlopt_func_old fc, void *fc_data_, ptrdiff_t fc_datum_size,
     int p, nlopt_func_old h, void *h_data_, ptrdiff_t h_datum_size,
     const double *lb, const double *ub, /* bounds */
     double *x, /* in: initial guess, out: minimizer */
     double *minf, /* out: minimum */
     double minf_max, double ftol_rel, double ftol_abs,
     double xtol_rel, const double *xtol_abs,
     double htol_rel, double htol_abs,
     int maxeval, double maxtime)
{
     char *fc_data = (char *) fc_data_;
     char *h_data = (char *) h_data_;
     nlopt_opt opt;
     nlopt_result ret;
     int i;

     if (n < 0 || m < 0 || p < 0) return NLOPT_INVALID_ARGS;

     opt = nlopt_create(algorithm, (unsigned) n);
     if (!opt) return NLOPT_INVALID_ARGS;

     ret = nlopt_set_min_objective(opt, (nlopt_func) f, f_data);
     if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; }

     for (i = 0; i < m; ++i) {
	  ret = nlopt_add_inequality_constraint(opt, (nlopt_func) fc, 
						fc_data + i*fc_datum_size,
						0.0);
	  if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; }
     }

     (void) htol_rel; /* unused */
     for (i = 0; i < p; ++i) {
	  ret = nlopt_add_equality_constraint(opt, (nlopt_func) h, 
					      h_data + i*h_datum_size,
					      htol_abs);
	  if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; }
     }

     ret = nlopt_set_lower_bounds(opt, lb);
     if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; }
     ret = nlopt_set_upper_bounds(opt, ub);
     if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; }

     ret = nlopt_set_stopval(opt, minf_max);
     if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; }

     ret = nlopt_set_ftol_rel(opt, ftol_rel);
     if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; }
     ret = nlopt_set_ftol_abs(opt, ftol_abs);
     if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; }

     ret = nlopt_set_xtol_rel(opt, xtol_rel);
     if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; }
     ret = nlopt_set_xtol_abs(opt, xtol_abs);
     if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; }
     
     ret = nlopt_set_maxeval(opt, maxeval);
     if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; }

     ret = nlopt_set_maxtime(opt, maxtime);
     if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; }

     ret = nlopt_optimize(opt, x, minf);

     nlopt_destroy(opt);
     return ret;
}
Ejemplo n.º 6
0
void NloptOptimizationSolver<T>::solve ()
{
  START_LOG("solve()", "NloptOptimizationSolver");

  this->init ();

  unsigned int nlopt_size = this->system().solution->size();

  // We have to have an objective function
  libmesh_assert( this->objective_object );

  // Set routine for objective and (optionally) gradient evaluation
  {
    nlopt_result ierr =
      nlopt_set_min_objective(_opt,
                              __libmesh_nlopt_objective,
                              this);
    if (ierr < 0)
      libmesh_error_msg("NLopt failed to set min objective: " << ierr);
  }

  if (this->lower_and_upper_bounds_object)
    {
      // Need to actually compute the bounds vectors first
      this->lower_and_upper_bounds_object->lower_and_upper_bounds(this->system());

      std::vector<Real> nlopt_lb(nlopt_size);
      std::vector<Real> nlopt_ub(nlopt_size);
      for(unsigned int i=0; i<nlopt_size; i++)
        {
          nlopt_lb[i] = this->system().get_vector("lower_bounds")(i);
          nlopt_ub[i] = this->system().get_vector("upper_bounds")(i);
        }

      nlopt_set_lower_bounds(_opt, &nlopt_lb[0]);
      nlopt_set_upper_bounds(_opt, &nlopt_ub[0]);
    }

  // If we have an equality constraints object, tell NLopt about it.
  if (this->equality_constraints_object)
    {
      // NLopt requires a vector to specify the tolerance for each constraint.
      // NLopt makes a copy of this vector internally, so it's safe for us to
      // let it go out of scope.
      std::vector<double> equality_constraints_tolerances(this->system().C_eq->size(),
                                                          _constraints_tolerance);

      // It would be nice to call the C interface directly, at least it should return an error
      // code we could parse... unfortunately, there does not seem to be a way to extract
      // the underlying nlopt_opt object from the nlopt::opt class!
      nlopt_result ierr =
        nlopt_add_equality_mconstraint(_opt,
                                       equality_constraints_tolerances.size(),
                                       __libmesh_nlopt_equality_constraints,
                                       this,
                                       &equality_constraints_tolerances[0]);

      if (ierr < 0)
        libmesh_error_msg("NLopt failed to add equality constraint: " << ierr);
    }

  // If we have an inequality constraints object, tell NLopt about it.
  if (this->inequality_constraints_object)
    {
      // NLopt requires a vector to specify the tolerance for each constraint
      std::vector<double> inequality_constraints_tolerances(this->system().C_ineq->size(),
                                                            _constraints_tolerance);

      nlopt_add_inequality_mconstraint(_opt,
                                       inequality_constraints_tolerances.size(),
                                       __libmesh_nlopt_inequality_constraints,
                                       this,
                                       &inequality_constraints_tolerances[0]);
    }

  // Set a relative tolerance on the optimization parameters
  nlopt_set_ftol_rel(_opt, this->objective_function_relative_tolerance);

  // Set the maximum number of allowed objective function evaluations
  nlopt_set_maxeval(_opt, this->max_objective_function_evaluations);

  // Reset internal iteration counter
  this->_iteration_count = 0;

  // Perform the optimization
  std::vector<Real> x(nlopt_size);
  Real min_val = 0.;
  _result = nlopt_optimize(_opt, &x[0], &min_val);

  if (_result < 0)
    libMesh::out << "NLopt failed!" << std::endl;
  else
    libMesh::out << "NLopt obtained optimal value: "
                 << min_val
                 << " in "
                 << this->get_iteration_count()
                 << " iterations."
                 << std::endl;

  STOP_LOG("solve()", "NloptOptimizationSolver");
}
nlopt_result ccsa_quadratic_minimize(
     unsigned n, nlopt_func f, void *f_data,
     unsigned m, nlopt_constraint *fc,

     nlopt_precond pre, 

     const double *lb, const double *ub, /* bounds */
     double *x, /* in: initial guess, out: minimizer */
     double *minf,
     nlopt_stopping *stop,
     nlopt_opt dual_opt)
{
     nlopt_result ret = NLOPT_SUCCESS;
     double *xcur, rho, *sigma, *dfdx, *dfdx_cur, *xprev, *xprevprev, fcur;
     double *dfcdx, *dfcdx_cur;
     double *fcval, *fcval_cur, *rhoc, *gcval, *y, *dual_lb, *dual_ub;
     double *pre_lb, *pre_ub;
     unsigned i, ifc, j, k = 0;
     dual_data dd;
     int feasible;
     double infeasibility;
     unsigned mfc;
     unsigned no_precond;
     nlopt_opt pre_opt = NULL;

     m = nlopt_count_constraints(mfc = m, fc);
     if (nlopt_get_dimension(dual_opt) != m) return NLOPT_INVALID_ARGS;
     sigma = (double *) malloc(sizeof(double) * (6*n + 2*m*n + m*7));
     if (!sigma) return NLOPT_OUT_OF_MEMORY;
     dfdx = sigma + n;
     dfdx_cur = dfdx + n;
     xcur = dfdx_cur + n;
     xprev = xcur + n;
     xprevprev = xprev + n;
     fcval = xprevprev + n;
     fcval_cur = fcval + m;
     rhoc = fcval_cur + m;
     gcval = rhoc + m;
     dual_lb = gcval + m;
     dual_ub = dual_lb + m;
     y = dual_ub + m;
     dfcdx = y + m;
     dfcdx_cur = dfcdx + m*n;

     dd.n = n;
     dd.x = x;
     dd.lb = lb;
     dd.ub = ub;
     dd.sigma = sigma;
     dd.dfdx = dfdx;
     dd.dfcdx = dfcdx;
     dd.fcval = fcval;
     dd.rhoc = rhoc;
     dd.xcur = xcur;
     dd.gcval = gcval;
     dd.pre = pre; dd.pre_data = f_data;
     dd.prec = NULL; dd.prec_data = NULL;
     dd.scratch = NULL;

     if (m) {
	  dd.prec = (nlopt_precond *) malloc(sizeof(nlopt_precond) * m);
	  dd.prec_data = (void **) malloc(sizeof(void *) * m);
	  if (!dd.prec || !dd.prec_data) {
	       ret = NLOPT_OUT_OF_MEMORY;
	       goto done;
	  }
	  for (i = ifc = 0; ifc < mfc; ++ifc) {
	       unsigned inext = i + fc[ifc].m;
	       for (; i < inext; ++i) {
		    dd.prec[i] = fc[ifc].pre;
		    dd.prec_data[i] = fc[ifc].f_data;
	       }
	  }
     }

     no_precond = pre == NULL;
     if (dd.prec)
	  for (i = 0; i < m; ++i)
	       no_precond = no_precond && dd.prec[i] == NULL;

     if (!no_precond) {
	  dd.scratch = (double*) malloc(sizeof(double) * (4*n));
	  if (!dd.scratch) {
	       free(sigma);
	       return NLOPT_OUT_OF_MEMORY;
	  }
	  pre_lb = dd.scratch + 2*n;
	  pre_ub = pre_lb + n;

	  pre_opt = nlopt_create(nlopt_get_algorithm(dual_opt), n);
	  if (!pre_opt) { ret = NLOPT_FAILURE; goto done; }
	  ret = nlopt_set_min_objective(pre_opt, g0, &dd);
	  if (ret < 0) goto done;
	  ret = nlopt_add_inequality_mconstraint(pre_opt, m, gi, &dd, NULL);
	  if (ret < 0) goto done;
	  ret = nlopt_set_ftol_rel(pre_opt, nlopt_get_ftol_rel(dual_opt));
	  if (ret < 0) goto done;
	  ret = nlopt_set_ftol_abs(pre_opt, nlopt_get_ftol_abs(dual_opt));
	  if (ret < 0) goto done;
	  ret = nlopt_set_maxeval(pre_opt, nlopt_get_maxeval(dual_opt));
	  if (ret < 0) goto done;
     }
     
     for (j = 0; j < n; ++j) {
	  if (nlopt_isinf(ub[j]) || nlopt_isinf(lb[j]))
	       sigma[j] = 1.0; /* arbitrary default */
	  else
	       sigma[j] = 0.5 * (ub[j] - lb[j]);
     }
     rho = 1.0;
     for (i = 0; i < m; ++i) {
	  rhoc[i] = 1.0;
	  dual_lb[i] = y[i] = 0.0;
	  dual_ub[i] = HUGE_VAL;
     }

     dd.fval = fcur = *minf = f(n, x, dfdx, f_data);
     stop->nevals++;
     memcpy(xcur, x, sizeof(double) * n);
     if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; }

     feasible = 1; infeasibility = 0;
     for (i = ifc = 0; ifc < mfc; ++ifc) {
	  nlopt_eval_constraint(fcval + i, dfcdx + i*n,
				fc + ifc, n, x);
	  i += fc[ifc].m;
	  if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; }
     }
     for (i = 0; i < m; ++i) {
	  feasible = feasible && fcval[i] <= 0;
	  if (fcval[i] > infeasibility) infeasibility = fcval[i];
     }
     /* For non-feasible initial points, set a finite (large)
	upper-bound on the dual variables.  What this means is that,
	if no feasible solution is found from the dual problem, it
	will minimize the dual objective with the unfeasible
	constraint weighted by 1e40 -- basically, minimizing the
	unfeasible constraint until it becomes feasible or until we at
	least obtain a step towards a feasible point.
	
	Svanberg suggested a different approach in his 1987 paper, basically
	introducing additional penalty variables for unfeasible constraints,
	but this is easier to implement and at least as efficient. */
     if (!feasible)
	  for (i = 0; i < m; ++i) dual_ub[i] = 1e40;

     nlopt_set_min_objective(dual_opt, dual_func, &dd);
     nlopt_set_lower_bounds(dual_opt, dual_lb);
     nlopt_set_upper_bounds(dual_opt, dual_ub);
     nlopt_set_stopval(dual_opt, -HUGE_VAL);
     nlopt_remove_inequality_constraints(dual_opt);
     nlopt_remove_equality_constraints(dual_opt);

     while (1) { /* outer iterations */
	  double fprev = fcur;
	  if (nlopt_stop_forced(stop)) ret = NLOPT_FORCED_STOP;
	  else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED;
	  else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED;
	  else if (feasible && *minf < stop->minf_max) 
	       ret = NLOPT_MINF_MAX_REACHED;
	  if (ret != NLOPT_SUCCESS) goto done;
	  if (++k > 1) memcpy(xprevprev, xprev, sizeof(double) * n);
	  memcpy(xprev, xcur, sizeof(double) * n);

	  while (1) { /* inner iterations */
	       double min_dual, infeasibility_cur;
	       int feasible_cur, inner_done;
	       unsigned save_verbose;
	       nlopt_result reti;

	       if (no_precond) {
		    /* solve dual problem */
		    dd.rho = rho; dd.count = 0;
		    save_verbose = ccsa_verbose;
		    ccsa_verbose = 0; /* no recursive verbosity */
		    reti = nlopt_optimize_limited(dual_opt, y, &min_dual,
						  0,
						  stop->maxtime 
						  - (nlopt_seconds() 
						     - stop->start));
		    ccsa_verbose = save_verbose;
		    if (reti < 0 || reti == NLOPT_MAXTIME_REACHED) {
			 ret = reti;
			 goto done;
		    }
		    
		    dual_func(m, y, NULL, &dd); /* evaluate final xcur etc. */
	       }
	       else {
		    double pre_min;
		    for (j = 0; j < n; ++j) {
			 pre_lb[j] = MAX(lb[j], x[j] - sigma[j]);
			 pre_ub[j] = MIN(ub[j], x[j] + sigma[j]);
			 xcur[j] = x[j];
		    }
		    nlopt_set_lower_bounds(pre_opt, pre_lb);
		    nlopt_set_upper_bounds(pre_opt, pre_ub);

		    dd.rho = rho; dd.count = 0;
		    save_verbose = ccsa_verbose;
		    ccsa_verbose = 0; /* no recursive verbosity */
		    reti = nlopt_optimize_limited(pre_opt, xcur, &pre_min,
						  0, stop->maxtime
                                                  - (nlopt_seconds()
                                                     - stop->start));
		    ccsa_verbose = save_verbose;
		    if (reti < 0 || reti == NLOPT_MAXTIME_REACHED) {
			 ret = reti;
			 goto done;
		    }

		    /* evaluate final xcur etc */
		    dd.gval = g0(n, xcur, NULL, &dd);
		    gi(m, dd.gcval, n, xcur, NULL, &dd);
	       }

	       if (ccsa_verbose) {
		    printf("CCSA dual converged in %d iters to g=%g:\n",
			   dd.count, dd.gval);
		    for (i = 0; i < MIN(ccsa_verbose, m); ++i)
			 printf("    CCSA y[%d]=%g, gc[%d]=%g\n",
				i, y[i], i, dd.gcval[i]);
	       }

	       fcur = f(n, xcur, dfdx_cur, f_data);
	       stop->nevals++;
	       if (nlopt_stop_forced(stop)) { 
		    ret = NLOPT_FORCED_STOP; goto done; }
	       feasible_cur = 1; infeasibility_cur = 0;
	       inner_done = dd.gval >= fcur;
	       for (i = ifc = 0; ifc < mfc; ++ifc) {
		    nlopt_eval_constraint(fcval_cur + i, dfcdx_cur + i*n,
					  fc + ifc, n, xcur);
		    i += fc[ifc].m;
		    if (nlopt_stop_forced(stop)) { 
			 ret = NLOPT_FORCED_STOP; goto done; }
	       }
	       for (i = ifc = 0; ifc < mfc; ++ifc) {
		    unsigned i0 = i, inext = i + fc[ifc].m;
		    for (; i < inext; ++i) {
			 feasible_cur = feasible_cur 
			      && fcval_cur[i] <= fc[ifc].tol[i-i0];
			 inner_done = inner_done && 
			      (dd.gcval[i] >= fcval_cur[i]);
			 if (fcval_cur[i] > infeasibility_cur)
			      infeasibility_cur = fcval_cur[i];
		    }
	       }

	       if ((fcur < *minf && (inner_done || feasible_cur || !feasible))
		    || (!feasible && infeasibility_cur < infeasibility)) {
		    if (ccsa_verbose && !feasible_cur)
			 printf("CCSA - using infeasible point?\n");
		    dd.fval = *minf = fcur;
		    infeasibility = infeasibility_cur;
		    memcpy(fcval, fcval_cur, sizeof(double)*m);
		    memcpy(x, xcur, sizeof(double)*n);
		    memcpy(dfdx, dfdx_cur, sizeof(double)*n);
		    memcpy(dfcdx, dfcdx_cur, sizeof(double)*n*m);
		    
		    /* once we have reached a feasible solution, the
		       algorithm should never make the solution infeasible
		       again (if inner_done), although the constraints may
		       be violated slightly by rounding errors etc. so we
		       must be a little careful about checking feasibility */
		    if (infeasibility_cur == 0) {
			 if (!feasible) { /* reset upper bounds to infin. */
			      for (i = 0; i < m; ++i) dual_ub[i] = HUGE_VAL;
			      nlopt_set_upper_bounds(dual_opt, dual_ub);
			 }
			 feasible = 1;
		    }

	       }
	       if (nlopt_stop_forced(stop)) ret = NLOPT_FORCED_STOP;
	       else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED;
	       else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED;
	       else if (feasible && *minf < stop->minf_max) 
		    ret = NLOPT_MINF_MAX_REACHED;
	       if (ret != NLOPT_SUCCESS) goto done;

	       if (inner_done) break;

	       if (fcur > dd.gval)
		    rho = MIN(10*rho, 1.1 * (rho + (fcur-dd.gval) / dd.wval));
	       for (i = 0; i < m; ++i)
		    if (fcval_cur[i] > dd.gcval[i])
			 rhoc[i] = 
			      MIN(10*rhoc[i], 
				  1.1 * (rhoc[i] + (fcval_cur[i]-dd.gcval[i]) 
					 / dd.wval));
	       
	       if (ccsa_verbose)
		    printf("CCSA inner iteration: rho -> %g\n", rho);
	       for (i = 0; i < MIN(ccsa_verbose, m); ++i)
		    printf("                CCSA rhoc[%d] -> %g\n", i,rhoc[i]);
	  }

	  if (nlopt_stop_ftol(stop, fcur, fprev))
	       ret = NLOPT_FTOL_REACHED;
	  if (nlopt_stop_x(stop, xcur, xprev))
	       ret = NLOPT_XTOL_REACHED;
	  if (ret != NLOPT_SUCCESS) goto done;
	       
	  /* update rho and sigma for iteration k+1 */
	  rho = MAX(0.1 * rho, CCSA_RHOMIN);
	  if (ccsa_verbose)
	       printf("CCSA outer iteration: rho -> %g\n", rho);
	  for (i = 0; i < m; ++i)
	       rhoc[i] = MAX(0.1 * rhoc[i], CCSA_RHOMIN);
	  for (i = 0; i < MIN(ccsa_verbose, m); ++i)
	       printf("                 CCSA rhoc[%d] -> %g\n", i, rhoc[i]);
	  if (k > 1) {
	       for (j = 0; j < n; ++j) {
		    double dx2 = (xcur[j]-xprev[j]) * (xprev[j]-xprevprev[j]);
		    double gam = dx2 < 0 ? 0.7 : (dx2 > 0 ? 1.2 : 1);
		    sigma[j] *= gam;
		    if (!nlopt_isinf(ub[j]) && !nlopt_isinf(lb[j])) {
			 sigma[j] = MIN(sigma[j], 10*(ub[j]-lb[j]));
			 /* use a smaller lower bound than Svanberg's
			    0.01*(ub-lb), which seems unnecessarily large */
			 sigma[j] = MAX(sigma[j], 1e-8*(ub[j]-lb[j]));
		    }
	       }
	       for (j = 0; j < MIN(ccsa_verbose, n); ++j)
		    printf("                 CCSA sigma[%d] -> %g\n", 
			   j, sigma[j]);
	  }
     }

 done:
     nlopt_destroy(pre_opt);
     if (dd.scratch) free(dd.scratch);
     if (m) {
	  free(dd.prec_data);
	  free(dd.prec);
     }
     free(sigma);
     return ret;
}
Ejemplo n.º 8
0
int CNLopt::run(double (*error_func)(unsigned int nParams, const double* params, double* grad, void* misc))
{
	// Create a member function pointer

	unsigned int n_data = mWorkerThread->GetDataSize();
        mOpt = nlopt_create(mAlgorithm, mNParams);

	//	xopt = new double [mNParams];
	lb = new double [mNParams];
	ub = new double [mNParams];

	// Copy out the initial values for the parameters:
	CModelListPtr model_list = mWorkerThread->GetModelList();
	model_list->GetFreeParameters(mParams, mNParams, false);
	vector<string> names = model_list->GetFreeParamNames();
	vector< pair<double, double> > min_max = model_list->GetFreeParamMinMaxes();

	// Init parameter values
	for(int i = 0; i < mNParams; i++)
	{
		lb[i] = min_max[i].first;
		ub[i] = min_max[i].second;
		//	xopt = mParams[i];
	}

	nlopt_set_lower_bounds(mOpt,lb);
	nlopt_set_upper_bounds(mOpt,ub);

	nlopt_set_ftol_rel(mOpt, 1e-4); // stopping criterion = when chi2 changes by less than 0.1%
	nlopt_set_min_objective(mOpt, error_func, (void*)this);

	int major=0, minor=0, bugfix=0;
	nlopt_version(&major, &minor, &bugfix);
	printf("Starting NLopt version %d.%d.%d\n", major, minor, bugfix);
	printf("Algorithm = %s \n", nlopt_algorithm_name(mAlgorithm));


	if(mAlgorithm == NLOPT_G_MLSL_LDS) // set local optimizer to be used with a global search
	  {
	    printf("Secondary Algorithm = %s \n", nlopt_algorithm_name(mAlgorithmSecondary));
	    mOptSecondary = nlopt_create(mAlgorithmSecondary, mNParams);
	    nlopt_set_lower_bounds(mOptSecondary,lb);
	    nlopt_set_upper_bounds(mOptSecondary,ub);
	    nlopt_set_ftol_rel(mOptSecondary, 1e-4); // stopping criterion = when chi2 changes by less than 0.1%
	    nlopt_set_min_objective(mOptSecondary, error_func, (void*)this);
	    nlopt_set_local_optimizer(mOpt, mOptSecondary);
	  }

	mIsRunning = true;
	mEvals = 0;
	double minf;
	// Call NLopt.  Note, the results are saved in mParams upon completion.
	nlopt_result result = nlopt_optimize(mOpt, mParams, &minf);

	mIsRunning = false;
	printresult(mParams, mNParams, n_data, names, minf, result);

	delete(lb);
	delete(ub);

	nlopt_destroy(mOpt);
	if(mAlgorithm == NLOPT_G_MLSL_LDS) // also destroy local optimizer
	  {
	   nlopt_destroy(mOptSecondary);
	  }


	return mEvals;
}
Ejemplo n.º 9
0
/********************************************************************
 * nlopt main function
 * *****************************************************************/
SEXP TKF92LikelihoodFunction3DMain_nlopt(SEXP seq1IntR, SEXP seq2IntR,
    SEXP expectedLength, SEXP probMatR, SEXP eqFrequenciesR,
    SEXP method){
  int ncol, nrow;
  ncol = INTEGER(GET_DIM(probMatR))[1];
  nrow = INTEGER(GET_DIM(probMatR))[0];
  int i, j;

  // probMat
  gsl_matrix *probMat = gsl_matrix_alloc(nrow, ncol);
  for(i = 0; i < nrow; i++)
    for(j = 0; j < ncol; j++)
      gsl_matrix_set(probMat, i, j, REAL(probMatR)[i+j*ncol]);

  // eqFrequenciesR
  gsl_vector *eqFrequencies = gsl_vector_alloc(GET_LENGTH(eqFrequenciesR));
  for(i = 0; i < GET_LENGTH(eqFrequenciesR); i++){
    gsl_vector_set(eqFrequencies, i, REAL(eqFrequenciesR)[i]);
  }

  // seqInt preparation
  int *seq1Int, *seq2Int;
  seq1Int = (int *) R_alloc(GET_LENGTH(seq1IntR), sizeof(int));
  seq2Int = (int *) R_alloc(GET_LENGTH(seq2IntR), sizeof(int));
  for(i = 0; i < GET_LENGTH(seq1IntR); i++){
    seq1Int[i] = INTEGER(seq1IntR)[i];
  }
  for(i = 0; i < GET_LENGTH(seq2IntR); i++){
    seq2Int[i] = INTEGER(seq2IntR)[i];
  }
  
  // construct params
  struct TKF92LikelihoodFunction3D_params params;
  params.len = REAL(expectedLength)[0];
  params.substModel = probMat;
  params.eqFrequencies = eqFrequencies;
  params.seq1Int = seq1Int;
  params.seq2Int = seq2Int;
  params.SA = GET_LENGTH(seq1IntR);
  params.SB = GET_LENGTH(seq2IntR);

  // nlopt main procedure
  double lb[3] = {0.0494497, 1e-20, 1e-20}; // lower bounds
  double ub[3] = {2000, 0.1, 1-1e-20};  // upper bounds
  //double dx[3] = {20, 0.01, 0.1}; // The initial step size

  nlopt_opt opt;
  if(strcmp(CHAR(STRING_ELT(method, 0)), "NM") == 0){
    opt = nlopt_create(NLOPT_LN_NELDERMEAD, 3); /* algorithm and dimensionality */
  }else if(strcmp(CHAR(STRING_ELT(method, 0)), "Sbplx") == 0){
    opt = nlopt_create(NLOPT_LN_SBPLX, 3);
  }else if(strcmp(CHAR(STRING_ELT(method, 0)), "COBYLA") == 0){
    opt = nlopt_create(NLOPT_LN_COBYLA, 3);
  }else if(strcmp(CHAR(STRING_ELT(method, 0)), "BOBYQA") == 0){
    opt = nlopt_create(NLOPT_LN_BOBYQA, 3);
  }else if(strcmp(CHAR(STRING_ELT(method, 0)), "PRAXIS") == 0){
    opt = nlopt_create(NLOPT_LN_PRAXIS, 3);
  }else{
    error("Wrong optimisation method!");
  }

  nlopt_set_lower_bounds(opt, lb);
  nlopt_set_upper_bounds(opt, ub);
  
  nlopt_set_min_objective(opt, TKF92LikelihoodFunction3D_nlopt, &params);
  nlopt_set_ftol_rel(opt, F_TOL); // stopping criteria
  //nlopt_set_initial_step(opt, dx); // initial step size
  nlopt_set_maxeval(opt, MAX_ITER);

  double x[3] = {100, exp(-3), 0.5};  /* some initial guess */
  double minf; /* the minimum objective value, upon return */
  if (nlopt_optimize(opt, x, &minf) < 0) {
    Rprintf("nlopt failed!\n");
  }else{
    Rprintf("found minimum at f(%g,%g,%g) = %0.10g using %s algorithm\n",
        x[0], x[1], x[2], minf, CHAR(STRING_ELT(method, 0)));
  }

  SEXP ans, ansNames;
  PROTECT(ans = NEW_NUMERIC(4)); // a vector of distance, mu, r and the negative log likelihood
  PROTECT(ansNames = NEW_CHARACTER(4));
  REAL(ans)[0] = x[0];
  REAL(ans)[1] = x[1];
  REAL(ans)[2] = x[2];
  REAL(ans)[3] = minf;
  SET_STRING_ELT(ansNames, 0, mkChar("PAM"));
  SET_STRING_ELT(ansNames, 1, mkChar("Mu"));
  SET_STRING_ELT(ansNames, 2, mkChar("r"));
  SET_STRING_ELT(ansNames, 3, mkChar("negLogLikelihood"));
  SET_NAMES(ans, ansNames);

  // free everything
  nlopt_destroy(opt);
  gsl_vector_free(eqFrequencies);
  gsl_matrix_free(probMat);

  UNPROTECT(2);
  return ans;
}
/* unlike nlopt_optimize() below, only handles minimization case */
static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf)
{
     const double *lb, *ub;
     nlopt_algorithm algorithm;
     nlopt_func f; void *f_data;
     unsigned n, i;
     int ni;
     nlopt_stopping stop;

     if (!opt || !x || !minf || !opt->f
	 || opt->maximize) return NLOPT_INVALID_ARGS;

     /* reset stopping flag */
     nlopt_set_force_stop(opt, 0);
     opt->force_stop_child = NULL;
     
     /* copy a few params to local vars for convenience */
     n = opt->n;
     ni = (int) n; /* most of the subroutines take "int" arg */
     lb = opt->lb; ub = opt->ub;
     algorithm = opt->algorithm;
     f = opt->f; f_data = opt->f_data;

     if (n == 0) { /* trivial case: no degrees of freedom */
	  *minf = opt->f(n, x, NULL, opt->f_data);
	  return NLOPT_SUCCESS;
     }

     *minf = HUGE_VAL;
     
     /* make sure rand generator is inited */
     nlopt_srand_time_default(); /* default is non-deterministic */

     /* check bound constraints */
     for (i = 0; i < n; ++i)
	  if (lb[i] > ub[i] || x[i] < lb[i] || x[i] > ub[i])
	       return NLOPT_INVALID_ARGS;

     stop.n = n;
     stop.minf_max = opt->stopval;
     stop.ftol_rel = opt->ftol_rel;
     stop.ftol_abs = opt->ftol_abs;
     stop.xtol_rel = opt->xtol_rel;
     stop.xtol_abs = opt->xtol_abs;
     stop.nevals = 0;
     stop.maxeval = opt->maxeval;
     stop.maxtime = opt->maxtime;
     stop.start = nlopt_seconds();
     stop.force_stop = &(opt->force_stop);

     switch (algorithm) {
	 case NLOPT_GN_DIRECT:
	 case NLOPT_GN_DIRECT_L: 
	 case NLOPT_GN_DIRECT_L_RAND: 
	      if (!finite_domain(n, lb, ub)) return NLOPT_INVALID_ARGS;
	      return cdirect(ni, f, f_data, 
			     lb, ub, x, minf, &stop, 0.0, 
			     (algorithm != NLOPT_GN_DIRECT)
			     + 3 * (algorithm == NLOPT_GN_DIRECT_L_RAND 
				    ? 2 : (algorithm != NLOPT_GN_DIRECT))
			     + 9 * (algorithm == NLOPT_GN_DIRECT_L_RAND 
				    ? 1 : (algorithm != NLOPT_GN_DIRECT)));
	      
	 case NLOPT_GN_DIRECT_NOSCAL:
	 case NLOPT_GN_DIRECT_L_NOSCAL: 
	 case NLOPT_GN_DIRECT_L_RAND_NOSCAL: 
	      if (!finite_domain(n, lb, ub)) return NLOPT_INVALID_ARGS;
	      return cdirect_unscaled(ni, f, f_data, lb, ub, x, minf, 
				      &stop, 0.0, 
				      (algorithm != NLOPT_GN_DIRECT)
				      + 3 * (algorithm == NLOPT_GN_DIRECT_L_RAND ? 2 : (algorithm != NLOPT_GN_DIRECT))
				      + 9 * (algorithm == NLOPT_GN_DIRECT_L_RAND ? 1 : (algorithm != NLOPT_GN_DIRECT)));
	      
	 case NLOPT_GN_ORIG_DIRECT:
	 case NLOPT_GN_ORIG_DIRECT_L: {
	      direct_return_code dret;
	      if (!finite_domain(n, lb, ub)) return NLOPT_INVALID_ARGS;
	      opt->work = malloc(sizeof(double) *
				 nlopt_max_constraint_dim(opt->m,
							  opt->fc));
	      if (!opt->work) return NLOPT_OUT_OF_MEMORY;
	      dret = direct_optimize(f_direct, opt, ni, lb, ub, x, minf,
				     stop.maxeval, -1,
				     stop.start, stop.maxtime,
				     0.0, 0.0,
				     pow(stop.xtol_rel, (double) n), -1.0,
				     stop.force_stop,
				     stop.minf_max, 0.0,
				     NULL, 
				     algorithm == NLOPT_GN_ORIG_DIRECT
				     ? DIRECT_ORIGINAL
				     : DIRECT_GABLONSKY);
	      free(opt->work); opt->work = NULL;
	      switch (dret) {
		  case DIRECT_INVALID_BOUNDS:
		  case DIRECT_MAXFEVAL_TOOBIG:
		  case DIRECT_INVALID_ARGS:
		       return NLOPT_INVALID_ARGS;
		  case DIRECT_INIT_FAILED:
		  case DIRECT_SAMPLEPOINTS_FAILED:
		  case DIRECT_SAMPLE_FAILED:
		       return NLOPT_FAILURE;
		  case DIRECT_MAXFEVAL_EXCEEDED:
		  case DIRECT_MAXITER_EXCEEDED:
		       return NLOPT_MAXEVAL_REACHED;
		  case DIRECT_MAXTIME_EXCEEDED:
		       return NLOPT_MAXTIME_REACHED;
		  case DIRECT_GLOBAL_FOUND:
		       return NLOPT_MINF_MAX_REACHED;
		  case DIRECT_VOLTOL:
		  case DIRECT_SIGMATOL:
		       return NLOPT_XTOL_REACHED;
		  case DIRECT_OUT_OF_MEMORY:
		       return NLOPT_OUT_OF_MEMORY;
		  case DIRECT_FORCED_STOP:
		       return NLOPT_FORCED_STOP;
	      }
	      break;
	 }

	 case NLOPT_GD_STOGO:
	 case NLOPT_GD_STOGO_RAND:
#ifdef WITH_CXX
	      if (!finite_domain(n, lb, ub)) return NLOPT_INVALID_ARGS;
	      if (!stogo_minimize(ni, f, f_data, x, minf, lb, ub, &stop,
				  algorithm == NLOPT_GD_STOGO
				  ? 0 : (int) POP(2*n)))
		   return NLOPT_FAILURE;
	      break;
#else
	      return NLOPT_INVALID_ARGS;
#endif

#if 0
	      /* lacking a free/open-source license, we no longer use
		 Rowan's code, and instead use by "sbplx" re-implementation */
	 case NLOPT_LN_SUBPLEX: {
	      int iret, freedx = 0;
	      if (!opt->dx) {
		   freedx = 1;
		   if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS)
			return NLOPT_OUT_OF_MEMORY;
	      }		       
	      iret = nlopt_subplex(f_bound, minf, x, n, opt, &stop, opt->dx);
	      if (freedx) { free(opt->dx); opt->dx = NULL; }
	      switch (iret) {
		  case -2: return NLOPT_INVALID_ARGS;
		  case -20: return NLOPT_FORCED_STOP;
		  case -10: return NLOPT_MAXTIME_REACHED;
		  case -1: return NLOPT_MAXEVAL_REACHED;
		  case 0: return NLOPT_XTOL_REACHED;
		  case 1: return NLOPT_SUCCESS;
		  case 2: return NLOPT_MINF_MAX_REACHED;
		  case 20: return NLOPT_FTOL_REACHED;
		  case -200: return NLOPT_OUT_OF_MEMORY;
		  default: return NLOPT_FAILURE; /* unknown return code */
	      }
	      break;
	 }
#endif

	 case NLOPT_LN_PRAXIS: {
	      double step;
	      if (initial_step(opt, x, &step) != NLOPT_SUCCESS)
		   return NLOPT_OUT_OF_MEMORY;
	      return praxis_(0.0, DBL_EPSILON, 
			     step, ni, x, f_bound, opt, &stop, minf);
	 }

	 case NLOPT_LD_LBFGS: 
	      return luksan_plis(ni, f, f_data, lb, ub, x, minf, 
				 &stop, opt->vector_storage);

	 case NLOPT_LD_VAR1: 
	 case NLOPT_LD_VAR2: 
	      return luksan_plip(ni, f, f_data, lb, ub, x, minf, 
				 &stop, opt->vector_storage,
				 algorithm == NLOPT_LD_VAR1 ? 1 : 2);

	 case NLOPT_LD_TNEWTON: 
	 case NLOPT_LD_TNEWTON_RESTART: 
	 case NLOPT_LD_TNEWTON_PRECOND: 
	 case NLOPT_LD_TNEWTON_PRECOND_RESTART: 
	      return luksan_pnet(ni, f, f_data, lb, ub, x, minf,
				 &stop, opt->vector_storage,
				 1 + (algorithm - NLOPT_LD_TNEWTON) % 2,
				 1 + (algorithm - NLOPT_LD_TNEWTON) / 2);

	 case NLOPT_GN_CRS2_LM:
	      if (!finite_domain(n, lb, ub)) return NLOPT_INVALID_ARGS;
	      return crs_minimize(ni, f, f_data, lb, ub, x, minf, &stop, 
				  (int) POP(0), 0);

	 case NLOPT_G_MLSL:
	 case NLOPT_G_MLSL_LDS:
	 case NLOPT_GN_MLSL:
	 case NLOPT_GD_MLSL:
	 case NLOPT_GN_MLSL_LDS:
	 case NLOPT_GD_MLSL_LDS: {
	      nlopt_opt local_opt = opt->local_opt;
	      nlopt_result ret;
	      if (!finite_domain(n, lb, ub)) return NLOPT_INVALID_ARGS;
	      if (!local_opt && (algorithm == NLOPT_G_MLSL 
				 || algorithm == NLOPT_G_MLSL_LDS))
		   return NLOPT_INVALID_ARGS;
	      if (!local_opt) { /* default */
		   nlopt_algorithm local_alg = (algorithm == NLOPT_GN_MLSL ||
						algorithm == NLOPT_GN_MLSL_LDS)
			? nlopt_local_search_alg_nonderiv
			: nlopt_local_search_alg_deriv;
		   /* don't call MLSL recursively! */
		   if (local_alg >= NLOPT_GN_MLSL
		       && local_alg <= NLOPT_GD_MLSL_LDS)
			local_alg = (algorithm == NLOPT_GN_MLSL ||
				     algorithm == NLOPT_GN_MLSL_LDS)
			     ? NLOPT_LN_COBYLA : NLOPT_LD_MMA;
		   local_opt = nlopt_create(local_alg, n);
		   if (!local_opt) return NLOPT_FAILURE;
		   nlopt_set_ftol_rel(local_opt, opt->ftol_rel);
		   nlopt_set_ftol_abs(local_opt, opt->ftol_abs);
		   nlopt_set_xtol_rel(local_opt, opt->xtol_rel);
		   nlopt_set_xtol_abs(local_opt, opt->xtol_abs);
		   nlopt_set_maxeval(local_opt, nlopt_local_search_maxeval);
	      }
	      if (opt->dx) nlopt_set_initial_step(local_opt, opt->dx);
	      for (i = 0; i < n && stop.xtol_abs[i] > 0; ++i) ;
	      if (local_opt->ftol_rel <= 0 && local_opt->ftol_abs <= 0 &&
		  local_opt->xtol_rel <= 0 && i < n) {
		   /* it is not sensible to call MLSL without *some*
		      nonzero tolerance for the local search */
		   nlopt_set_ftol_rel(local_opt, 1e-15);
		   nlopt_set_xtol_rel(local_opt, 1e-7);
	      }
	      opt->force_stop_child = local_opt;
	      ret = mlsl_minimize(ni, f, f_data, lb, ub, x, minf, &stop,
				  local_opt, (int) POP(0),
				  algorithm >= NLOPT_GN_MLSL_LDS &&
				  algorithm != NLOPT_G_MLSL);
	      opt->force_stop_child = NULL;
	      if (!opt->local_opt) nlopt_destroy(local_opt);
	      return ret;
	 }

	 case NLOPT_LD_MMA: case NLOPT_LD_CCSAQ: {
	      nlopt_opt dual_opt;
	      nlopt_result ret;
#define LO(param, def) (opt->local_opt ? opt->local_opt->param : (def))
	      dual_opt = nlopt_create(LO(algorithm,
					 nlopt_local_search_alg_deriv),
				      nlopt_count_constraints(opt->m,
							      opt->fc));
	      if (!dual_opt) return NLOPT_FAILURE;
	      nlopt_set_ftol_rel(dual_opt, LO(ftol_rel, 1e-14));
	      nlopt_set_ftol_abs(dual_opt, LO(ftol_abs, 0.0));
	      nlopt_set_maxeval(dual_opt, LO(maxeval, 100000));
#undef LO

	      if (algorithm == NLOPT_LD_MMA)
		   ret = mma_minimize(n, f, f_data, opt->m, opt->fc,
				      lb, ub, x, minf, &stop, dual_opt);
	      else
		   ret = ccsa_quadratic_minimize(
			n, f, f_data, opt->m, opt->fc, opt->pre,
			lb, ub, x, minf, &stop, dual_opt);
	      nlopt_destroy(dual_opt);
	      return ret;
	 }

	 case NLOPT_LN_COBYLA: {
	      nlopt_result ret;
	      int freedx = 0;
	      if (!opt->dx) {
		   freedx = 1;
		   if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS)
			return NLOPT_OUT_OF_MEMORY;
	      }
	      return cobyla_minimize(n, f, f_data, 
				     opt->m, opt->fc,
				     opt->p, opt->h,
				     lb, ub, x, minf, &stop,
				     opt->dx);
	      if (freedx) { free(opt->dx); opt->dx = NULL; }
	      return ret;
	 }
				     
	 case NLOPT_LN_NEWUOA: {
	      double step;
	      if (initial_step(opt, x, &step) != NLOPT_SUCCESS)
		   return NLOPT_OUT_OF_MEMORY;
	      return newuoa(ni, 2*n+1, x, 0, 0, step,
			    &stop, minf, f_noderiv, opt);
	 }
				     
	 case NLOPT_LN_NEWUOA_BOUND: {
	      double step;
	      if (initial_step(opt, x, &step) != NLOPT_SUCCESS)
		   return NLOPT_OUT_OF_MEMORY;
	      return newuoa(ni, 2*n+1, x, lb, ub, step,
			    &stop, minf, f_noderiv, opt);
	 }

	 case NLOPT_LN_BOBYQA: {
	      nlopt_result ret;
	      int freedx = 0;
	      if (!opt->dx) {
		   freedx = 1;
		   if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS)
			return NLOPT_OUT_OF_MEMORY;
	      }
	      ret = bobyqa(ni, 2*n+1, x, lb, ub, opt->dx,
			   &stop, minf, opt->f, opt->f_data);
	      if (freedx) { free(opt->dx); opt->dx = NULL; }
	      return ret;
	 }

	 case NLOPT_LN_NELDERMEAD: 
	 case NLOPT_LN_SBPLX: 
	 {
	      nlopt_result ret;
	      int freedx = 0;
	      if (!opt->dx) {
		   freedx = 1;
		   if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS)
			return NLOPT_OUT_OF_MEMORY;
	      }
	      if (algorithm == NLOPT_LN_NELDERMEAD)
		   ret= nldrmd_minimize(ni,f,f_data,lb,ub,x,minf,opt->dx,&stop);
	      else
		   ret= sbplx_minimize(ni,f,f_data,lb,ub,x,minf,opt->dx,&stop);
	      if (freedx) { free(opt->dx); opt->dx = NULL; }
	      return ret;
	 }

	 case NLOPT_AUGLAG:
	 case NLOPT_AUGLAG_EQ:
	 case NLOPT_LN_AUGLAG:
	 case NLOPT_LN_AUGLAG_EQ:
	 case NLOPT_LD_AUGLAG:
	 case NLOPT_LD_AUGLAG_EQ: {
	      nlopt_opt local_opt = opt->local_opt;
	      nlopt_result ret;
	      if ((algorithm == NLOPT_AUGLAG || algorithm == NLOPT_AUGLAG_EQ)
		  && !local_opt)
		   return NLOPT_INVALID_ARGS;
	      if (!local_opt) { /* default */
		   local_opt = nlopt_create(
			algorithm == NLOPT_LN_AUGLAG || 
			algorithm == NLOPT_LN_AUGLAG_EQ
			? nlopt_local_search_alg_nonderiv
			: nlopt_local_search_alg_deriv, n);
		   if (!local_opt) return NLOPT_FAILURE;
		   nlopt_set_ftol_rel(local_opt, opt->ftol_rel);
		   nlopt_set_ftol_abs(local_opt, opt->ftol_abs);
		   nlopt_set_xtol_rel(local_opt, opt->xtol_rel);
		   nlopt_set_xtol_abs(local_opt, opt->xtol_abs);
		   nlopt_set_maxeval(local_opt, nlopt_local_search_maxeval);
	      }
	      if (opt->dx) nlopt_set_initial_step(local_opt, opt->dx);
	      opt->force_stop_child = local_opt;
	      ret = auglag_minimize(ni, f, f_data, 
				    opt->m, opt->fc, 
				    opt->p, opt->h,
				    lb, ub, x, minf, &stop,
				    local_opt,
				    algorithm == NLOPT_AUGLAG_EQ
				    || algorithm == NLOPT_LN_AUGLAG_EQ
				    || algorithm == NLOPT_LD_AUGLAG_EQ);
	      opt->force_stop_child = NULL;
	      if (!opt->local_opt) nlopt_destroy(local_opt);
	      return ret;
	 }

	 case NLOPT_GN_ISRES:
	      if (!finite_domain(n, lb, ub)) return NLOPT_INVALID_ARGS;
	      return isres_minimize(ni, f, f_data, 
				    (int) (opt->m), opt->fc,
				    (int) (opt->p), opt->h,
				    lb, ub, x, minf, &stop,
				    (int) POP(0));

// 	case NLOPT_GN_ESCH:
// 	      if (!finite_domain(n, lb, ub)) return NLOPT_INVALID_ARGS;
// 	      return chevolutionarystrategy(n, f, f_data, 
// 					    lb, ub, x, minf, &stop,
// 					    (unsigned) POP(0),
// 					    (unsigned) (POP(0)*1.5));

	 case NLOPT_LD_SLSQP:
	      return nlopt_slsqp(n, f, f_data,
				 opt->m, opt->fc,
				 opt->p, opt->h,
				 lb, ub, x, minf, &stop);
				     
	 default:
	      return NLOPT_INVALID_ARGS;
     }

     return NLOPT_SUCCESS; /* never reached */
}
Ejemplo n.º 11
0
void omxInvokeNLOPT(double *est, GradientOptimizerContext &goc)
{
	goc.optName = "SLSQP";
	goc.setupSimpleBounds();
	goc.useGradient = true;

	FitContext *fc = goc.fc;
	int oldWanted = fc->wanted;
	fc->wanted = 0;
	omxState *globalState = fc->state;
    
        nlopt_opt opt = nlopt_create(NLOPT_LD_SLSQP, fc->numParam);
	goc.extraData = opt;
        //local_opt = nlopt_create(NLOPT_LD_SLSQP, n); // Subsidiary algorithm
        
        //nlopt_set_local_optimizer(opt, local_opt);
        nlopt_set_lower_bounds(opt, goc.solLB.data());
        nlopt_set_upper_bounds(opt, goc.solUB.data());

	int eq, ieq;
	globalState->countNonlinearConstraints(eq, ieq);

	if (fc->CI) {
		nlopt_set_xtol_rel(opt, 5e-3);
		std::vector<double> tol(fc->numParam, std::numeric_limits<double>::epsilon());
		nlopt_set_xtol_abs(opt, tol.data());
	} else {
		// The *2 is there to roughly equate accuracy with NPSOL.
		nlopt_set_ftol_rel(opt, goc.ControlTolerance * 2);
		nlopt_set_ftol_abs(opt, std::numeric_limits<double>::epsilon());
	}
        
	nlopt_set_min_objective(opt, SLSQP::nloptObjectiveFunction, &goc);

	double feasibilityTolerance = Global->feasibilityTolerance;
	SLSQP::context ctx(goc);
        if (eq + ieq) {
		ctx.origeq = eq;
                if (ieq > 0){
			goc.inequality.resize(ieq);
			std::vector<double> tol(ieq, feasibilityTolerance);
			nlopt_add_inequality_mconstraint(opt, ieq, SLSQP::nloptInequalityFunction, &goc, tol.data());
                }
                
                if (eq > 0){
			goc.equality.resize(eq);
			std::vector<double> tol(eq, feasibilityTolerance);
			nlopt_add_equality_mconstraint(opt, eq, SLSQP::nloptEqualityFunction, &ctx, tol.data());
                }
	}
        
	int priorIterations = fc->iterations;

	int code = nlopt_optimize(opt, est, &fc->fit);
	if (ctx.eqredundent) {
		nlopt_remove_equality_constraints(opt);
		eq -= ctx.eqredundent;
		std::vector<double> tol(eq, feasibilityTolerance);
		nlopt_add_equality_mconstraint(opt, eq, SLSQP::nloptEqualityFunction, &ctx, tol.data());

		code = nlopt_optimize(opt, est, &fc->fit);
	}

	if (goc.verbose >= 2) mxLog("nlopt_optimize returned %d", code);

        nlopt_destroy(opt);

	fc->wanted = oldWanted;

	if (code == NLOPT_INVALID_ARGS) {
		Rf_error("NLOPT invoked with invalid arguments");
	} else if (code == NLOPT_OUT_OF_MEMORY) {
		Rf_error("NLOPT ran out of memory");
	} else if (code == NLOPT_FORCED_STOP) {
		if (fc->iterations - priorIterations <= 1) {
			goc.informOut = INFORM_STARTING_VALUES_INFEASIBLE;
		} else {
			goc.informOut = INFORM_ITERATION_LIMIT;
		}
	} else if (code == NLOPT_ROUNDOFF_LIMITED) {
		if (fc->iterations - priorIterations <= 2) {
			Rf_error("%s: Failed due to singular matrix E or C in LSQ subproblem or "
				 "rank-deficient equality constraint subproblem or "
				 "positive directional derivative in line search", goc.optName);
		} else {
			goc.informOut = INFORM_NOT_AT_OPTIMUM;  // is this correct? TODO
		}
	} else if (code < 0) {
		Rf_error("NLOPT fatal error %d", code);
	} else if (code == NLOPT_MAXEVAL_REACHED) {
		goc.informOut = INFORM_ITERATION_LIMIT;
	} else {
		goc.informOut = INFORM_CONVERGED_OPTIMUM;
	}
}
Ejemplo n.º 12
0
static int test_function(int ifunc)
{
    nlopt_opt opt;
    testfunc func;
    int i, iter;
    double *x, minf, minf_max, f0, *xtabs, *lb, *ub;
    nlopt_result ret;
    double start = nlopt_seconds();
    int total_count = 0, max_count = 0, min_count = 1 << 30;
    double total_err = 0, max_err = 0;
    bounds_wrap_data bw;

    if (ifunc < 0 || ifunc >= NTESTFUNCS) {
        fprintf(stderr, "testopt: invalid function %d\n", ifunc);
        listfuncs(stderr);
        return 0;
    }
    func = testfuncs[ifunc];
    x = (double *) malloc(sizeof(double) * func.n * 5);
    if (!x) {
        fprintf(stderr, "testopt: Out of memory!\n");
        return 0;
    }

    lb = x + func.n * 3;
    ub = lb + func.n;
    xtabs = x + func.n * 2;
    bw.lb = lb;
    bw.ub = ub;
    bw.f = func.f;
    bw.f_data = func.f_data;

    for (i = 0; i < func.n; ++i)
        xtabs[i] = xtol_abs;
    minf_max = minf_max_delta > (-HUGE_VAL) ? minf_max_delta + func.minf : (-HUGE_VAL);

    printf("-----------------------------------------------------------\n");
    printf("Optimizing %s (%d dims) using %s algorithm\n", func.name, func.n, nlopt_algorithm_name(algorithm));
    printf("lower bounds at lb = [");
    for (i = 0; i < func.n; ++i)
        printf(" %g", func.lb[i]);
    printf("]\n");
    printf("upper bounds at ub = [");
    for (i = 0; i < func.n; ++i)
        printf(" %g", func.ub[i]);
    printf("]\n");
    memcpy(lb, func.lb, func.n * sizeof(double));
    memcpy(ub, func.ub, func.n * sizeof(double));
    for (i = 0; i < func.n; ++i)
        if (fix_bounds[i]) {
            printf("fixing bounds for dim[%d] to xmin[%d]=%g\n", i, i, func.xmin[i]);
            lb[i] = ub[i] = func.xmin[i];
        }
    if (force_constraints) {
        for (i = 0; i < func.n; ++i) {
            if (nlopt_iurand(2) == 0)
                ub[i] = nlopt_urand(lb[i], func.xmin[i]);
            else
                lb[i] = nlopt_urand(func.xmin[i], ub[i]);
        }
        printf("adjusted lower bounds at lb = [");
        for (i = 0; i < func.n; ++i)
            printf(" %g", lb[i]);
        printf("]\n");
        printf("adjusted upper bounds at ub = [");
        for (i = 0; i < func.n; ++i)
            printf(" %g", ub[i]);
        printf("]\n");
    }

    if (fabs(func.f(func.n, func.xmin, 0, func.f_data) - func.minf) > 1e-8) {
        fprintf(stderr, "BUG: function does not achieve given lower bound!\n");
        fprintf(stderr, "f(%g", func.xmin[0]);
        for (i = 1; i < func.n; ++i)
            fprintf(stderr, ", %g", func.xmin[i]);
        fprintf(stderr, ") = %0.16g instead of %0.16g, |diff| = %g\n", func.f(func.n, func.xmin, 0, func.f_data), func.minf, fabs(func.f(func.n, func.xmin, 0, func.f_data) - func.minf));
        free(x);
        return 0;
    }

    for (iter = 0; iter < iterations; ++iter) {
        double val;
        testfuncs_counter = 0;

        printf("Starting guess x = [");
        for (i = 0; i < func.n; ++i) {
            if (center_start)
                x[i] = (ub[i] + lb[i]) * 0.5;
            else if (xinit_tol < 0) {   /* random starting point near center of box */
                double dx = (ub[i] - lb[i]) * 0.25;
                double xm = 0.5 * (ub[i] + lb[i]);
                x[i] = nlopt_urand(xm - dx, xm + dx);
            } else {
                x[i] = nlopt_urand(-xinit_tol, xinit_tol)
                    + (1 + nlopt_urand(-xinit_tol, xinit_tol)) * func.xmin[i];
                if (x[i] > ub[i])
                    x[i] = ub[i];
                else if (x[i] < lb[i])
                    x[i] = lb[i];
            }
            printf(" %g", x[i]);
        }
        printf("]\n");
        f0 = func.f(func.n, x, x + func.n, func.f_data);
        printf("Starting function value = %g\n", f0);

        if (iter == 0 && testfuncs_verbose && func.has_gradient) {
            printf("checking gradient:\n");
            for (i = 0; i < func.n; ++i) {
                double f;
                x[i] *= 1 + 1e-6;
                f = func.f(func.n, x, NULL, func.f_data);
                x[i] /= 1 + 1e-6;
                printf("  grad[%d] = %g vs. numerical derivative %g\n", i, x[i + func.n], (f - f0) / (x[i] * 1e-6));
            }
        }

        testfuncs_counter = 0;
        opt = nlopt_create(algorithm, func.n);
        nlopt_set_min_objective(opt, bounds_wrap_func, &bw);
        nlopt_set_lower_bounds(opt, lb);
        nlopt_set_upper_bounds(opt, ub);
        nlopt_set_stopval(opt, minf_max);
        nlopt_set_ftol_rel(opt, ftol_rel);
        nlopt_set_ftol_abs(opt, ftol_abs);
        nlopt_set_xtol_rel(opt, xtol_rel);
        nlopt_set_xtol_abs(opt, xtabs);
        nlopt_set_maxeval(opt, maxeval);
        nlopt_set_maxtime(opt, maxtime);
        ret = nlopt_optimize(opt, x, &minf);
        printf("finished after %g seconds.\n", nlopt_seconds() - start);
        printf("return code %d from nlopt_minimize\n", ret);
        if (ret < 0 && ret != NLOPT_ROUNDOFF_LIMITED && ret != NLOPT_FORCED_STOP) {
            fprintf(stderr, "testopt: error in nlopt_minimize\n");
            free(x);
            return 0;
        }
        printf("Found minimum f = %g after %d evaluations (numevals = %d).\n", minf, testfuncs_counter, nlopt_get_numevals(opt));
        nlopt_destroy(opt);
        total_count += testfuncs_counter;
        if (testfuncs_counter > max_count)
            max_count = testfuncs_counter;
        if (testfuncs_counter < min_count)
            min_count = testfuncs_counter;
        printf("Minimum at x = [");
        for (i = 0; i < func.n; ++i)
            printf(" %g", x[i]);
        printf("]\n");
        if (func.minf == 0)
            printf("|f - minf| = %g\n", fabs(minf - func.minf));
        else
            printf("|f - minf| = %g, |f - minf| / |minf| = %e\n", fabs(minf - func.minf), fabs(minf - func.minf) / fabs(func.minf));
        total_err += fabs(minf - func.minf);
        if (fabs(minf - func.minf) > max_err)
            max_err = fabs(minf - func.minf);
        printf("vs. global minimum f = %g at x = [", func.minf);
        for (i = 0; i < func.n; ++i)
            printf(" %g", func.xmin[i]);
        printf("]\n");

        val = func.f(func.n, x, NULL, func.f_data);
        if (fabs(val - minf) > 1e-12) {
            fprintf(stderr, "Mismatch %g between returned minf=%g and f(x) = %g\n", minf - val, minf, val);
            free(x);
            return 0;
        }
    }
    if (iterations > 1)
        printf("average #evaluations = %g (%d-%d)\naverage |f-minf| = %g, max |f-minf| = %g\n", total_count * 1.0 / iterations, min_count, max_count, total_err / iterations, max_err);

    free(x);
    return 1;
}