\name{snomadr}
\alias{snomadr}
\title{
R interface to NOMAD
}
\description{
\code{snomadr} is an R interface to NOMAD (Nonsmooth Optimization by
Mesh Adaptive Direct Search, Abramson, Audet, Couture and Le Digabel
(2011)), an open source software C++ implementation of the Mesh Adaptive
Direct Search (MADS, Le Digabel (2011)) algorithm designed for
constrained optimization of blackbox functions.

NOMAD is designed to find (local) solutions of mathematical optimization
problems of the form

  \preformatted{
   min     f(x)
x in R^n

s.t.       g(x) <= 0
           x_L <=  x   <= x_U
}

where \eqn{f(x)\colon R^n \to R^k}{f(x): R^n --> R^k} is the objective
function, and \eqn{g(x)\colon R^n \to R^m}{g(x): R^n --> R^m} are
the constraint functions. The vectors \eqn{x_L}{x_L} and \eqn{x_U}{x_U}
are the bounds on the variables \eqn{x}. The functions \eqn{f(x)} and
\eqn{g(x)} can be nonlinear and nonconvex. The variables can be integer,
continuous real number, binary, and categorical.

Kindly see \url{https://www.gerad.ca/en/software/nomad} and the
references below for details.

}

\usage{
snomadr(eval.f,
        n,
        bbin = NULL,
        bbout = NULL,
        x0 = NULL,
        lb = NULL,
        ub = NULL,
        nmulti = 0,
        random.seed = 0,
        opts = list(),
        display.nomad.progress = TRUE,
        information = list(),
        snomadr.environment = new.env(),
        ... )
}

\arguments{
\subsection{Objective, Dimension, And Evaluation Environment}{
These arguments identify the objective, dimension, black-box types, and evaluation environment.
}

    \item{bbin}{
      types of variables. Variable types are 0 (CONTINUOUS), 1
        (INTEGER), 2 (CATEGORICAL), 3 (BINARY)
      }


    \item{bbout}{
      types of output of \code{eval.f}.  See the NOMAD User Guide
      \url{https://nomad-4-user-guide.readthedocs.io/en/latest/#}
    }


    \item{eval.f}{
        function that returns the value of the objective function
    }

    \item{n}{
        the number of variables
    }


    \item{snomadr.environment}{
        environment that is used to evaluate the functions. Use this to pass
        additional data or parameters to a function
    }


\subsection{Multi-Start Controls}{
These arguments control multistart execution and reproducibility settings.
}

    \item{nmulti}{
      when it is missing, or it is equal to 0 and \code{x0} is provided,
        \code{snomadRSolve} will be called to solve the problem. Otherwise,
        \code{smultinomadRSolve} will be called
      }

    \item{random.seed}{
      when it is not missing and not equal to 0, the initial points  will
      be generated using this seed when \code{nmulti > 0}
      }


\subsection{NOMAD Options And Information Queries}{
These arguments control NOMAD options and optional information queries.
}

    \item{information}{
      is a list. \code{snomadr} will call \code{snomadRInfo} to return
      the information about NOMAD according to the values of \code{"info"},
      \code{"version"} and \code{"help"}.

      \code{"info"="-i"}: display the usage and copyright of NOMAD

      \code{"version"="-v"}: display the version of NOMAD you are using

      \code{"help"="-h"}: display all options

      You also can display a specific option, for example,
      \code{"help"="-h x0"}, this will tell you how to set \code{x0}
    }


    \item{opts}{
      list of options for NOMAD, see the NOMAD user guide
      \url{https://nomad-4-user-guide.readthedocs.io/en/latest/#}.  Options
      can also be set by nomad.opt which should be in the folder where R
      (\code{snomadr}) is executed.

      This interface uses NOMAD 4 option names directly (for example
      \code{MIN_FRAME_SIZE}).

      A complete option catalog generated from the embedded NOMAD 4.5.0
      definitions is bundled at
      \code{system.file("nomad", "NOMAD_4_5_0_OPTIONS_REFERENCE.md", package="crs")}.

      To improve comparability with historical NOMAD 3.9.1 behavior,
      \code{snomadr} applies a small NOMAD4 compatibility profile when
      these options are not user-supplied (user \code{opts} always take
      precedence):
      \code{QUAD_MODEL_SEARCH},
      \code{SGTELIB_MODEL_SEARCH},
      \code{NM_SEARCH},
      \code{SPECULATIVE_SEARCH},
      \code{EVAL_OPPORTUNISTIC},
      \code{EVAL_QUEUE_SORT},
      \code{DIRECTION_TYPE},
      \code{QUAD_MODEL_SEARCH_BOX_FACTOR},
      and \code{QUAD_MODEL_BOX_FACTOR}.

      A few high-impact options are:

      \code{"MAX_BB_EVAL"=10000}

      \code{"INITIAL_MESH_SIZE"=1}

      \code{"MIN_MESH_SIZE"="r1.0e-10"}

      \code{"MIN_FRAME_SIZE"=1}

      Note that the \code{"r..."} denotes relative measurement (relative
      to \code{lb} and \code{ub})

      Note that decreasing the maximum number of black box evaluations
      (\code{"MAX_BB_EVAL"}) will terminate search sooner and may result
      in a less accurate solution. For complicated problems you may want
      to increase this value. When experimenting, \code{"DISPLAY_DEGREE"=1}
      or \code{"DISPLAY_DEGREE"=2} can provide additional native NOMAD
      output. Higher native display degrees are currently rejected by the
      embedded \code{snomadr()} interface because NOMAD4's verbose block
      output queue can abort repeated R-session solves.

      }


\subsection{Starting Values, Bounds, And Variable Types}{
These arguments identify starting values, bounds, and variable types.
}

    \item{lb}{
        vector with lower bounds of the controls (use -1.0e19 for controls without lower bound)
    }

    \item{ub}{
        vector with upper bounds of the controls (use  1.0e19 for controls without upper bound)
    }


    \item{x0}{
      vector with starting values for the optimization. If it is
        provided and nmulti is bigger than 1, \code{x0} will be the first
        initial point for multiple initial points
      }

\subsection{Additional Arguments}{
These arguments control displayed progress and pass-through values.
}

    \item{...}{
      arguments that will be passed to the user-defined objective and
      constraints functions. See the examples below
    }

    \item{display.nomad.progress}{
      when FALSE, no output from \code{snomadr} is displayed on the
      screen. If the NOMAD option \code{"DISPLAY_DEGREE"=0,} is set,
      there will also be no output from NOMAD. Supported native
      \code{"DISPLAY_DEGREE"} values are 0, 1, and 2 in this embedded
      interface.
    }
  }

  \details{

    \code{snomadr} is used in the \pkg{crs} package to numerically
    minimize an objective function with respect to the spline degree,
    number of knots, and optionally the kernel bandwidths when using
    \code{\link{crs}} with the option \code{cv="nomad"} (default). This
    is a constrained mixed integer combinatoric problem and is known to
    be computationally \sQuote{hard}. See \code{\link{frscvNOMAD}} and
    \code{\link{krscvNOMAD}} for the functions called when
    \code{cv="nomad"} while using \code{\link{crs}}.

    However, the user should note that for simple problems involving one
    predictor exhaustive search may be faster and potentially more
    accurate, so please bear in mind that \code{cv="exhaustive"} can be
    useful when using \code{\link{crs}}.

    Naturally, exhaustive search is also useful for verifying solutions
    returned by \code{snomadr}. See \code{\link{frscv}} and
    \code{\link{krscv}} for the functions called when
    \code{cv="exhaustive"} while using \code{\link{crs}}.

  }

\value{
    The return value contains a list with the inputs, and additional elements
    \item{call}{the call that was made to solve}
    \item{status}{integer value with the status of the optimization }
    \item{message}{more informative message with the status of the optimization}
    \item{bbe}{number of blackbox evaluations reported by the interface}
    \item{cache.hits}{number of NOMAD native cache hits during the run}
    \item{cache.size}{number of points in NOMAD's native cache at the end of the run}
    \item{callback.evaluations}{number of evaluations sent to the R callback}
    \item{total.evaluations}{total evaluations represented by callback evaluations plus cache hits}
    \item{iterations}{number of iterations that were executed, if multiple initial points are set,
        this number will be the sum for each initial point.}
    \item{objective}{value if the objective function in the solution}
    \item{solution}{optimal value of the controls}
}
\references{

  Abramson, M.A. and C. Audet and G. Couture and J.E. Dennis Jr. and
  S. Le Digabel (2011), \dQuote{The NOMAD project}. Software available
  at https://www.gerad.ca/en/software/nomad/

  Le Digabel, S. (2011), \dQuote{Algorithm 909: NOMAD: Nonlinear
  Optimization With The MADS Algorithm}. ACM Transactions on
  Mathematical Software, 37(4):44:1-44:15.

}
\author{
  Zhenghua Nie <niez@mcmaster.ca>
}
\seealso{
    \code{\link{optim}}, \code{\link{nlm}}, \code{\link{nlminb}}
}
\examples{
\dontrun{
## List all options
snomadr(information=list("help"="-h"))

## Print given option,  for example,  MESH_SIZE
snomadr(information=list("help"="-h MESH_SIZE"))

## Print the version of NOMAD
snomadr(information=list("version"="-v"))

## Print usage and copyright
snomadr(information=list("info"="-i"))

## This is the example found in
## NOMAD/examples/basic/library/single_obj/basic_lib.cpp

eval.f <- function ( x ) {

    f <- c(Inf, Inf, Inf);
    n <- length (x);

    if ( n == 5 && ( is.double(x) || is.integer(x) ) ) {
        f[1] <- x[5];
        f[2] <- sum ( (x-1)^2 ) - 25;
        f[3] <- 25 - sum ( (x+1)^2 );
    }

    return ( as.double(f) );
}

## Initial values
x0 <- rep(0.0, 5 )

bbin <-c(1, 1, 1, 1, 1)
## Bounds
lb <- rep(-6.0,5 )
ub <- c(5.0, 6.0, 7.0, 1000000, 100000)

bbout <-c(0, 2, 1)
## Options
opts <-list("MAX_BB_EVAL"=500,
            "MIN_MESH_SIZE"=0.001,
            "INITIAL_MESH_SIZE"=0.1,
            "MIN_FRAME_SIZE"=1)

snomadr(eval.f=eval.f,n=5,  x0=x0, bbin=bbin, bbout=bbout, lb=lb, ub=ub, opts=opts)


## How to transfer other parameters into eval.f
##
## First example: supply additional arguments in user-defined functions
##

## objective function and gradient in terms of parameters
eval.f.ex1 <- function(x, params) {
    return( params[1]*x^2 + params[2]*x + params[3] )
}

## Define parameters that we want to use
params <- c(1,2,3)

## Define initial value of the optimization problem
x0 <- 0

## solve using snomadr
snomadr( n          =1,
        x0          = x0,
        eval.f      = eval.f.ex1,
        params      = params )


##
## Second example: define an environment that contains extra parameters
##

## Objective function and gradient in terms of parameters
## without supplying params as an argument
eval.f.ex2 <- function(x) {
    return( params[1]*x^2 + params[2]*x + params[3] )
}

## Define initial value of the optimization problem
x0 <- 0

## Define a new environment that contains params
auxdata        <- new.env()
auxdata$params <- c(1,2,3)

## pass The environment that should be used to evaluate functions to snomadr
snomadr(n                  =1,
        x0                 = x0,
        eval.f             = eval.f.ex2,
        snomadr.environment = auxdata )

## Solve using algebra
cat( paste( "Minimizing f(x) = ax^2 + bx + c\n" ) )
cat( paste( "Optimal value of control is -b/(2a) = ", -params[2]/(2*params[1]), "\n" ) )
cat( paste( "With value of the objective function f(-b/(2a)) = ",
           eval.f.ex1( -params[2]/(2*params[1]), params ), "\n" ) )

## The following example is NOMAD/examples/advanced/multi_start/multi.cpp
## This will call smultinomadRSolve to resolve the problem.
eval.f.ex1 <- function(x, params) {
    M<-as.numeric(params$M)
    NBC<-as.numeric(params$NBC)

    f<-rep(0, M+1)
    x<-as.numeric(x)

    x1 <- rep(0.0, NBC)
    y1 <- rep(0.0, NBC)

    x1[1]<-x[1]
    x1[2]<-x[2]
    y1[3]<-x[3]
    x1[4]<-x[4]
    y1[4]<-x[5]

    epi <- 6
    for(i in 5:NBC){
        x1[i]<-x[epi]
        epi <- epi+1
        y1[i]<-x[epi]
        epi<-epi+1
    }
    constraint <- 0.0
    ic <- 1
    f[ic]<-constraint
    ic <- ic+1

    constraint <- as.numeric(1.0)
    distmax <- as.numeric(0.0)
    avg_dist <- as.numeric(0.0)
    dist1<-as.numeric(0.0)

    for(i in 1:(NBC-1)){
        for (j in (i+1):NBC){
            dist1 <- as.numeric((x1[i]-x1[j])*(x1[i]-x1[j])+(y1[i]-y1[j])*(y1[i]-y1[j]))

            if((dist1 > distmax)) {distmax <- as.numeric(dist1)}
            if((dist1[1]) < 1) {constraint <- constraint*sqrt(dist1)}
            else if((dist1) > 14) {avg_dist <- avg_dist+sqrt(dist1)}
        }
    }

    if(constraint < 0.9999) constraint <- 1001.0-constraint
    else constraint = sqrt(distmax)+avg_dist/(10.0*NBC)

    f[2] <- 0.0
    f[M+1] <- constraint


    return(as.numeric(f) )
}

## Define parameters that we want to use
params<-list()
NBC <- 5
M <- 2
n<-2*NBC-3

params$NBC<-NBC
params$M<-M
x0<-rep(0.1, n)
lb<-rep(0, n)
ub<-rep(4.5, n)

eval.f.ex1(x0, params)

bbout<-c(2, 2, 0)
nmulti=5
bbin<-rep(0, n)
## Define initial value of the optimization problem

## Solve using snomadRSolve
snomadr(n            = as.integer(n),
        x0           = x0,
        eval.f       = eval.f.ex1,
        bbin         = bbin,
        bbout        = bbout,
        lb           = lb,
        ub           = ub,
        params       = params )

## Solve using smultinomadRSolve, if x0 is provided,  x0 will
## be the first initial point,  otherwise,  the program will
## check best_x.txt,  if it exists,  it will be read in as
## the first initial point. Other initial points will be
## generated by uniform distribution.
## nmulti represents the number of mads will run.
##
snomadr(n            = as.integer(n),
        eval.f       = eval.f.ex1,
        bbin         = bbin,
        bbout        = bbout,
        lb           = lb,
        ub           = ub,
        nmulti = as.integer(nmulti),
        display.nomad.progress = TRUE,
        params       = params )
} % end dontrun
}
\keyword{ optimize }
\keyword{ interface }
